-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Expand file tree
/
Copy pathapp.tsx
More file actions
116 lines (103 loc) · 3.23 KB
/
app.tsx
File metadata and controls
116 lines (103 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
/* eslint-disable no-unused-vars */
import React, {useState, useEffect, useCallback} from 'react';
import {createRoot} from 'react-dom/client';
import {DeckGL} from '@deck.gl/react';
import {OrbitView, LinearInterpolator} from '@deck.gl/core';
import {PointCloudLayer} from '@deck.gl/layers';
import {LASLoader} from '@loaders.gl/las';
import type {OrbitViewState} from '@deck.gl/core';
import {Device} from '@luma.gl/core';
// TODO - export from loaders?
type LASMesh = (typeof LASLoader)['dataType'];
// Data source: kaarta.com
const LAZ_SAMPLE =
'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/point-cloud-laz/indoor.0.1.laz';
const INITIAL_VIEW_STATE: OrbitViewState = {
target: [0, 0, 0],
rotationX: 0,
rotationOrbit: 0,
minZoom: 0,
maxZoom: 10,
zoom: 1
};
const transitionInterpolator = new LinearInterpolator(['rotationOrbit']);
export default function App({
onLoad,
device
}: {
onLoad?: (data: {count: number; progress: number}) => void;
device?: Device;
}) {
const [viewState, updateViewState] = useState<OrbitViewState>(INITIAL_VIEW_STATE);
const [isLoaded, setIsLoaded] = useState<boolean>(false);
useEffect(() => {
if (!isLoaded) {
return;
}
const rotateCamera = () => {
updateViewState(v => ({
...v,
rotationOrbit: v.rotationOrbit! + 120,
transitionDuration: 2400,
transitionInterpolator,
onTransitionEnd: rotateCamera
}));
};
rotateCamera();
}, [isLoaded]);
const onDataLoad = useCallback((data: any) => {
const header = (data as LASMesh).header!;
const pos = (data as LASMesh).attributes.POSITION;
// TODO: (kaapp) webgpu won't allow us to just downgrade
// to Float32 and not supply the low value as webgl so kindly did.
const f64Pos = new Float64Array(pos.value.length);
for (let i = 0; i < pos.value.length; i++) {
f64Pos[i] = pos.value[i];
}
(data as LASMesh).attributes.POSITION.value = f64Pos;
if (header.boundingBox) {
const [mins, maxs] = header.boundingBox;
// File contains bounding box info
updateViewState({
...INITIAL_VIEW_STATE,
target: [(mins[0] + maxs[0]) / 2, (mins[1] + maxs[1]) / 2, (mins[2] + maxs[2]) / 2],
/* global window */
zoom: Math.log2(window.innerWidth / (maxs[0] - mins[0])) - 1
});
setIsLoaded(true);
}
if (onLoad) {
onLoad({count: header.vertexCount, progress: 1});
}
}, []);
const layers = [
new PointCloudLayer<LASMesh>({
id: 'laz-point-cloud-layer',
data: LAZ_SAMPLE,
onDataLoad,
getNormal: [0, 1, 0],
getColor: [255, 255, 255],
opacity: 0.5,
pointSize: 0.5,
// Additional format support can be added here
loaders: [LASLoader],
// TODO (kaapp) currently webgpu requirement to ensure instanceColors are supplied
pickable: true
})
];
return (
<DeckGL
device={device}
views={new OrbitView({orbitAxis: 'Y', fovy: 50})}
initialViewState={viewState}
controller={true}
layers={layers}
/>
);
}
export function renderToDOM(container: HTMLDivElement) {
createRoot(container).render(<App />);
}