@viamrobotics/motion-tools 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attribute.d.ts +3 -0
- package/dist/attribute.js +30 -0
- package/dist/components/Entities.svelte +2 -1
- package/dist/components/FileDrop/FileDrop.svelte +9 -4
- package/dist/components/Points.svelte +25 -38
- package/dist/components/Tree/TreeContainer.svelte +1 -0
- package/dist/components/shared/Table.svelte +0 -24
- package/dist/ecs/traits.d.ts +4 -1
- package/dist/ecs/traits.js +4 -1
- package/dist/hooks/useDrawAPI.svelte.js +12 -18
- package/dist/hooks/usePointclouds.svelte.js +15 -11
- package/dist/snapshot.js +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BufferGeometry } from 'three';
|
|
2
|
+
export declare const createBufferGeometry: (positions: Float32Array, colors?: Float32Array | null) => BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
|
|
3
|
+
export declare const updateBufferGeometry: (geometry: BufferGeometry, positions: Float32Array, colors?: Float32Array | null) => void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BufferGeometry, BufferAttribute } from 'three';
|
|
2
|
+
export const createBufferGeometry = (positions, colors) => {
|
|
3
|
+
const geometry = new BufferGeometry();
|
|
4
|
+
geometry.setAttribute('position', new BufferAttribute(positions, 3));
|
|
5
|
+
if (colors) {
|
|
6
|
+
geometry.setAttribute('color', new BufferAttribute(colors, 3));
|
|
7
|
+
}
|
|
8
|
+
return geometry;
|
|
9
|
+
};
|
|
10
|
+
export const updateBufferGeometry = (geometry, positions, colors) => {
|
|
11
|
+
const positionAttr = geometry.getAttribute('position');
|
|
12
|
+
if (positionAttr && positionAttr.array.length >= positions.length) {
|
|
13
|
+
positionAttr.array.set(positions, 0);
|
|
14
|
+
geometry.setDrawRange(0, positions.length);
|
|
15
|
+
positionAttr.needsUpdate = true;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
geometry.setAttribute('position', new BufferAttribute(positions, 3));
|
|
19
|
+
}
|
|
20
|
+
if (colors) {
|
|
21
|
+
const colorAttr = geometry.getAttribute('color');
|
|
22
|
+
if (colorAttr && colorAttr.array.length >= colors.length) {
|
|
23
|
+
colorAttr.array.set(colors, 0);
|
|
24
|
+
colorAttr.needsUpdate = true;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
geometry.setAttribute('color', new BufferAttribute(colors, 3));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
@@ -37,10 +37,11 @@
|
|
|
37
37
|
Not(traits.FramesAPI),
|
|
38
38
|
Not(traits.GeometriesAPI),
|
|
39
39
|
Not(traits.WorldStateStoreAPI),
|
|
40
|
+
Not(traits.Points),
|
|
40
41
|
Or(traits.Box, traits.Capsule, traits.Sphere, traits.BufferGeometry, traits.ReferenceFrame)
|
|
41
42
|
)
|
|
42
43
|
|
|
43
|
-
const points = useQuery(traits.
|
|
44
|
+
const points = useQuery(traits.Points)
|
|
44
45
|
const lines = useQuery(traits.LinePositions)
|
|
45
46
|
const gltfs = useQuery(traits.GLTF)
|
|
46
47
|
</script>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { traits } from '../../ecs'
|
|
8
8
|
import { spawnSnapshotEntities } from '../../snapshot'
|
|
9
9
|
import { useCameraControls } from '../../hooks/useControls.svelte'
|
|
10
|
+
import { createBufferGeometry } from '../../attribute'
|
|
10
11
|
|
|
11
12
|
const props: HTMLAttributes<HTMLDivElement> = $props()
|
|
12
13
|
|
|
@@ -34,21 +35,25 @@
|
|
|
34
35
|
|
|
35
36
|
break
|
|
36
37
|
}
|
|
37
|
-
case 'pcd':
|
|
38
|
+
case 'pcd': {
|
|
39
|
+
const geometry = createBufferGeometry(result.pcd.positions, result.pcd.colors)
|
|
40
|
+
|
|
38
41
|
world.spawn(
|
|
39
42
|
traits.Name(result.name),
|
|
40
|
-
traits.
|
|
41
|
-
|
|
43
|
+
traits.BufferGeometry(geometry),
|
|
44
|
+
traits.Points,
|
|
42
45
|
traits.DroppedFile
|
|
43
46
|
)
|
|
44
47
|
break
|
|
45
|
-
|
|
48
|
+
}
|
|
49
|
+
case 'ply': {
|
|
46
50
|
world.spawn(
|
|
47
51
|
traits.Name(result.name),
|
|
48
52
|
traits.BufferGeometry(result.ply),
|
|
49
53
|
traits.DroppedFile
|
|
50
54
|
)
|
|
51
55
|
break
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
toast({ message: `${result.name} loaded.`, variant: ToastVariant.Success })
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
Points,
|
|
4
|
-
BufferAttribute,
|
|
5
|
-
BufferGeometry,
|
|
6
|
-
PointsMaterial,
|
|
7
|
-
OrthographicCamera,
|
|
8
|
-
} from 'three'
|
|
2
|
+
import { Points, PointsMaterial, OrthographicCamera } from 'three'
|
|
9
3
|
import { T, useTask, useThrelte } from '@threlte/core'
|
|
10
4
|
import { Portal } from '@threlte/extras'
|
|
11
5
|
import { useObjectEvents } from '../hooks/useObjectEvents.svelte'
|
|
@@ -28,9 +22,8 @@
|
|
|
28
22
|
const name = useTrait(() => entity, traits.Name)
|
|
29
23
|
const parent = useTrait(() => entity, traits.Parent)
|
|
30
24
|
const pose = useTrait(() => entity, traits.Pose)
|
|
31
|
-
const
|
|
25
|
+
const geometry = useTrait(() => entity, traits.BufferGeometry)
|
|
32
26
|
const color = useTrait(() => entity, traits.Color)
|
|
33
|
-
const colors = useTrait(() => entity, traits.VertexColors)
|
|
34
27
|
const opacity = useTrait(() => entity, traits.Opacity)
|
|
35
28
|
const entityPointSize = useTrait(() => entity, traits.PointSize)
|
|
36
29
|
|
|
@@ -40,8 +33,7 @@
|
|
|
40
33
|
const orthographic = $derived(settings.current.cameraMode === 'orthographic')
|
|
41
34
|
|
|
42
35
|
const points = new Points()
|
|
43
|
-
const
|
|
44
|
-
const material = new PointsMaterial()
|
|
36
|
+
const material = points.material as PointsMaterial
|
|
45
37
|
material.toneMapped = false
|
|
46
38
|
|
|
47
39
|
$effect.pre(() => {
|
|
@@ -49,7 +41,7 @@
|
|
|
49
41
|
})
|
|
50
42
|
|
|
51
43
|
$effect.pre(() => {
|
|
52
|
-
if (
|
|
44
|
+
if (geometry.current?.getAttribute('color')) {
|
|
53
45
|
material.color.set(0xffffff)
|
|
54
46
|
} else if (color.current) {
|
|
55
47
|
material.color.setRGB(color.current.r, color.current.g, color.current.b)
|
|
@@ -74,25 +66,18 @@
|
|
|
74
66
|
})
|
|
75
67
|
|
|
76
68
|
$effect.pre(() => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
})
|
|
69
|
+
const colors = geometry.current?.getAttribute('color')
|
|
70
|
+
const positions = geometry.current?.getAttribute('position')
|
|
81
71
|
|
|
82
|
-
|
|
83
|
-
material.vertexColors = colors.current !== undefined
|
|
72
|
+
material.vertexColors = colors !== undefined
|
|
84
73
|
|
|
85
|
-
if (colors
|
|
86
|
-
const
|
|
87
|
-
const hasAlphaChannel = positions.current.length / vertexColors.length === 0.75
|
|
88
|
-
const itemSize = hasAlphaChannel ? 4 : 3
|
|
89
|
-
geometry.setAttribute('color', new BufferAttribute(vertexColors, itemSize))
|
|
90
|
-
geometry.attributes.color.needsUpdate = true
|
|
74
|
+
if (colors && positions) {
|
|
75
|
+
const hasAlphaChannel = positions.array.length / colors.array.length === 0.75
|
|
91
76
|
|
|
92
77
|
let transparent = false
|
|
93
78
|
if (hasAlphaChannel) {
|
|
94
|
-
for (let i = 3, l =
|
|
95
|
-
if (
|
|
79
|
+
for (let i = 3, l = colors.array.length; i < l; i += 4) {
|
|
80
|
+
if (colors.array[i] < 1) {
|
|
96
81
|
transparent = true
|
|
97
82
|
break
|
|
98
83
|
}
|
|
@@ -133,15 +118,17 @@
|
|
|
133
118
|
})
|
|
134
119
|
</script>
|
|
135
120
|
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
</
|
|
121
|
+
{#if geometry.current}
|
|
122
|
+
<Portal id={parent.current}>
|
|
123
|
+
<T
|
|
124
|
+
is={points}
|
|
125
|
+
name={name.current}
|
|
126
|
+
{...events}
|
|
127
|
+
bvh={{ maxDepth: 40, maxLeafTris: 20 }}
|
|
128
|
+
>
|
|
129
|
+
<T is={geometry.current} />
|
|
130
|
+
<T is={material} />
|
|
131
|
+
{@render children?.()}
|
|
132
|
+
</T>
|
|
133
|
+
</Portal>
|
|
134
|
+
{/if}
|
|
@@ -11,27 +11,3 @@
|
|
|
11
11
|
<table class="motion-tools-table">
|
|
12
12
|
{@render children?.()}
|
|
13
13
|
</table>
|
|
14
|
-
|
|
15
|
-
<style>
|
|
16
|
-
@reference "../../../app.css";
|
|
17
|
-
|
|
18
|
-
.motion-tools-table {
|
|
19
|
-
@apply w-full table-auto;
|
|
20
|
-
}
|
|
21
|
-
.motion-tools-table :global(thead) {
|
|
22
|
-
@apply border-light bg-light border;
|
|
23
|
-
}
|
|
24
|
-
.motion-tools-table :global(thead th) {
|
|
25
|
-
@apply border-light text-subtle-1 border px-2.5 py-1 text-xs font-normal whitespace-nowrap;
|
|
26
|
-
}
|
|
27
|
-
.motion-tools-table :global(thead th abbr) {
|
|
28
|
-
@apply text-disabled;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.motion-tools-table :global(tbody) {
|
|
32
|
-
@apply border-light border;
|
|
33
|
-
}
|
|
34
|
-
.motion-tools-table :global(tbody th) {
|
|
35
|
-
@apply border-light font-roboto-mono text-default h-[40px] gap-2 border px-1.5 text-center text-xs font-normal;
|
|
36
|
-
}
|
|
37
|
-
</style>
|
package/dist/ecs/traits.d.ts
CHANGED
|
@@ -45,6 +45,10 @@ export declare const Color: import("koota").Trait<{
|
|
|
45
45
|
b: number;
|
|
46
46
|
}>;
|
|
47
47
|
export declare const Arrow: import("koota").TagTrait;
|
|
48
|
+
/**
|
|
49
|
+
* Render entity as points
|
|
50
|
+
*/
|
|
51
|
+
export declare const Points: import("koota").TagTrait;
|
|
48
52
|
/**
|
|
49
53
|
* A box, in mm
|
|
50
54
|
*/
|
|
@@ -73,7 +77,6 @@ export declare const PointColor: import("koota").Trait<{
|
|
|
73
77
|
}>;
|
|
74
78
|
/** format [x, y, z, ...] */
|
|
75
79
|
export declare const LinePositions: import("koota").Trait<() => Float32Array<ArrayBuffer>>;
|
|
76
|
-
export declare const PointsPositions: import("koota").Trait<() => Float32Array<ArrayBuffer>>;
|
|
77
80
|
export declare const BufferGeometry: import("koota").Trait<() => ThreeBufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>>;
|
|
78
81
|
/** format [r, g, b, ...] */
|
|
79
82
|
export declare const VertexColors: import("koota").Trait<() => Float32Array<ArrayBuffer>>;
|
package/dist/ecs/traits.js
CHANGED
|
@@ -19,6 +19,10 @@ export const Opacity = trait(() => 1);
|
|
|
19
19
|
*/
|
|
20
20
|
export const Color = trait({ r: 0, g: 0, b: 0 });
|
|
21
21
|
export const Arrow = trait();
|
|
22
|
+
/**
|
|
23
|
+
* Render entity as points
|
|
24
|
+
*/
|
|
25
|
+
export const Points = trait();
|
|
22
26
|
/**
|
|
23
27
|
* A box, in mm
|
|
24
28
|
*/
|
|
@@ -34,7 +38,6 @@ export const Sphere = trait({ r: 200 });
|
|
|
34
38
|
export const PointColor = trait({ r: 0, g: 0, b: 0 });
|
|
35
39
|
/** format [x, y, z, ...] */
|
|
36
40
|
export const LinePositions = trait(() => new Float32Array());
|
|
37
|
-
export const PointsPositions = trait(() => new Float32Array());
|
|
38
41
|
export const BufferGeometry = trait(() => new ThreeBufferGeometry());
|
|
39
42
|
/** format [r, g, b, ...] */
|
|
40
43
|
export const VertexColors = trait(() => new Float32Array());
|
|
@@ -2,7 +2,6 @@ import { getContext, setContext } from 'svelte';
|
|
|
2
2
|
import { Color, Vector3, Vector4 } from 'three';
|
|
3
3
|
import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
|
|
4
4
|
import { UuidTool } from 'uuid-tool';
|
|
5
|
-
import { parsePcdInWorker } from '../loaders/pcd';
|
|
6
5
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
7
6
|
import { createPose, createPoseFromFrame } from '../transform';
|
|
8
7
|
import { useCameraControls } from './useControls.svelte';
|
|
@@ -13,6 +12,7 @@ import { parsePlyInput } from '../ply';
|
|
|
13
12
|
import { useLogs } from './useLogs.svelte';
|
|
14
13
|
import { createBox, createCapsule, createSphere } from '../geometry';
|
|
15
14
|
import { useDrawConnectionConfig } from './useDrawConnectionConfig.svelte';
|
|
15
|
+
import { createBufferGeometry, updateBufferGeometry } from '../attribute';
|
|
16
16
|
const colorUtil = new Color();
|
|
17
17
|
const bufferTypes = {
|
|
18
18
|
DRAW_POINTS: 0,
|
|
@@ -74,7 +74,6 @@ export const provideDrawAPI = () => {
|
|
|
74
74
|
const drawConnectionConfig = useDrawConnectionConfig();
|
|
75
75
|
const backendIP = $derived(drawConnectionConfig.current?.backendIP);
|
|
76
76
|
const websocketPort = $derived(drawConnectionConfig.current?.websocketPort);
|
|
77
|
-
let pointsIndex = 0;
|
|
78
77
|
let geometryIndex = 0;
|
|
79
78
|
let poseIndex = 0;
|
|
80
79
|
let reconnectDelay = 200;
|
|
@@ -126,13 +125,6 @@ export const provideDrawAPI = () => {
|
|
|
126
125
|
entities.set(name, entity);
|
|
127
126
|
}
|
|
128
127
|
};
|
|
129
|
-
const drawPCD = async (buffer) => {
|
|
130
|
-
const { positions, colors } = await parsePcdInWorker(new Uint8Array(buffer));
|
|
131
|
-
const entity = world.spawn(traits.Name(`Points ${++pointsIndex}`), traits.PointsPositions(positions), traits.DrawAPI);
|
|
132
|
-
if (colors) {
|
|
133
|
-
entity.add(traits.VertexColors(colors));
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
128
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
137
129
|
const drawGeometry = (data, color, parent) => {
|
|
138
130
|
const name = data.label ?? `geometry ${++geometryIndex}`;
|
|
@@ -225,9 +217,6 @@ export const provideDrawAPI = () => {
|
|
|
225
217
|
for (let i = 0; i < labelLen; i++) {
|
|
226
218
|
label += String.fromCharCode(reader.read());
|
|
227
219
|
}
|
|
228
|
-
const entities = world.query(traits.DrawAPI);
|
|
229
|
-
const entity = entities.find((entity) => entity.get(traits.Name) === label);
|
|
230
|
-
entity?.destroy();
|
|
231
220
|
// Read counts
|
|
232
221
|
const nPoints = reader.read();
|
|
233
222
|
const nColors = reader.read();
|
|
@@ -250,7 +239,17 @@ export const provideDrawAPI = () => {
|
|
|
250
239
|
colors[offset + 1] = g;
|
|
251
240
|
colors[offset + 2] = b;
|
|
252
241
|
}
|
|
253
|
-
|
|
242
|
+
const entities = world.query(traits.DrawAPI);
|
|
243
|
+
const entity = entities.find((entity) => entity.get(traits.Name) === label);
|
|
244
|
+
if (entity) {
|
|
245
|
+
const geometry = entity.get(traits.BufferGeometry);
|
|
246
|
+
if (geometry) {
|
|
247
|
+
updateBufferGeometry(geometry, positions, colors);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const geometry = createBufferGeometry(positions, colors);
|
|
252
|
+
world.spawn(traits.Name(label), traits.Color(colorUtil.set(r, g, b)), traits.BufferGeometry(geometry), traits.Points, traits.DrawAPI);
|
|
254
253
|
};
|
|
255
254
|
const drawLine = async (reader) => {
|
|
256
255
|
// Read label length
|
|
@@ -310,7 +309,6 @@ export const provideDrawAPI = () => {
|
|
|
310
309
|
entity.destroy();
|
|
311
310
|
}
|
|
312
311
|
entities.clear();
|
|
313
|
-
pointsIndex = 0;
|
|
314
312
|
geometryIndex = 0;
|
|
315
313
|
poseIndex = 0;
|
|
316
314
|
};
|
|
@@ -364,10 +362,6 @@ export const provideDrawAPI = () => {
|
|
|
364
362
|
operation = 'DrawLine';
|
|
365
363
|
drawLine(reader);
|
|
366
364
|
}
|
|
367
|
-
else if (type === bufferTypes.DRAW_PCD) {
|
|
368
|
-
operation = 'DrawPCD';
|
|
369
|
-
drawPCD(reader.buffer);
|
|
370
|
-
}
|
|
371
365
|
else if (type === bufferTypes.DRAW_GLTF) {
|
|
372
366
|
operation = 'DrawGLTF';
|
|
373
367
|
drawGLTF(reader.buffer);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CameraClient } from '@viamrobotics/sdk';
|
|
2
|
-
import { setContext, getContext
|
|
2
|
+
import { setContext, getContext } from 'svelte';
|
|
3
3
|
import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
4
4
|
import { parsePcdInWorker } from '../loaders/pcd';
|
|
5
5
|
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
@@ -7,6 +7,7 @@ import { useLogs } from './useLogs.svelte';
|
|
|
7
7
|
import { RefetchRates } from '../components/RefreshRate.svelte';
|
|
8
8
|
import { traits, useWorld } from '../ecs';
|
|
9
9
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
10
|
+
import { createBufferGeometry, updateBufferGeometry } from '../attribute';
|
|
10
11
|
const typeSafeObjectFromEntries = (entries) => {
|
|
11
12
|
return Object.fromEntries(entries);
|
|
12
13
|
};
|
|
@@ -26,12 +27,13 @@ export const providePointclouds = (partID) => {
|
|
|
26
27
|
refetchInterval: false,
|
|
27
28
|
}),
|
|
28
29
|
]));
|
|
29
|
-
const fetchedPropQueries = propQueries.every(([, query]) => query.isPending === false);
|
|
30
|
+
const fetchedPropQueries = $derived(propQueries.every(([, query]) => query.isPending === false));
|
|
30
31
|
const interval = $derived(refreshRates.get(RefreshRates.pointclouds));
|
|
31
32
|
const enabledClients = $derived.by(() => {
|
|
32
33
|
const results = [];
|
|
33
34
|
for (const client of clients) {
|
|
34
|
-
if (
|
|
35
|
+
if (environment.current.viewerMode === 'monitor' &&
|
|
36
|
+
fetchedPropQueries &&
|
|
35
37
|
client.current?.name &&
|
|
36
38
|
interval !== RefetchRates.OFF &&
|
|
37
39
|
disabledCameras.get(client.current?.name) !== true) {
|
|
@@ -57,7 +59,6 @@ export const providePointclouds = (partID) => {
|
|
|
57
59
|
}
|
|
58
60
|
});
|
|
59
61
|
const options = $derived({
|
|
60
|
-
enabled: environment.current.viewerMode === 'edit',
|
|
61
62
|
refetchInterval: interval,
|
|
62
63
|
});
|
|
63
64
|
const queries = $derived(enabledClients.map((client) => [client.current.name, createResourceQuery(client, 'getPointCloud', () => options)]));
|
|
@@ -72,7 +73,7 @@ export const providePointclouds = (partID) => {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
});
|
|
75
|
-
|
|
76
|
+
let pcObjects = $state.raw([]);
|
|
76
77
|
$effect(() => {
|
|
77
78
|
const binaries = [];
|
|
78
79
|
for (const [name, query] of queries) {
|
|
@@ -85,14 +86,16 @@ export const providePointclouds = (partID) => {
|
|
|
85
86
|
const { positions, colors } = await parsePcdInWorker(new Uint8Array(uint8array));
|
|
86
87
|
return { name, positions, colors };
|
|
87
88
|
})).then((results) => {
|
|
89
|
+
const fulfilledResults = [];
|
|
88
90
|
for (const result of results) {
|
|
89
91
|
if (result.status === 'fulfilled') {
|
|
90
|
-
|
|
92
|
+
fulfilledResults.push(result.value);
|
|
91
93
|
}
|
|
92
94
|
else if (result.status === 'rejected') {
|
|
93
95
|
logs.add(result.reason, 'error');
|
|
94
96
|
}
|
|
95
97
|
}
|
|
98
|
+
pcObjects = fulfilledResults;
|
|
96
99
|
});
|
|
97
100
|
});
|
|
98
101
|
const entities = new Map();
|
|
@@ -101,13 +104,14 @@ export const providePointclouds = (partID) => {
|
|
|
101
104
|
for (const { name, positions, colors } of pcObjects) {
|
|
102
105
|
const existing = entities.get(name);
|
|
103
106
|
if (existing) {
|
|
104
|
-
existing.
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
+
const geometry = existing.get(traits.BufferGeometry);
|
|
108
|
+
if (geometry) {
|
|
109
|
+
updateBufferGeometry(geometry, positions, colors);
|
|
110
|
+
continue;
|
|
107
111
|
}
|
|
108
|
-
continue;
|
|
109
112
|
}
|
|
110
|
-
const
|
|
113
|
+
const geometry = createBufferGeometry(positions, colors);
|
|
114
|
+
const entity = world.spawn(traits.Parent(name), traits.Name(`${name} pointcloud`), traits.BufferGeometry(geometry), traits.Points);
|
|
111
115
|
entities.set(name, entity);
|
|
112
116
|
}
|
|
113
117
|
// Clean up old entities
|
package/dist/snapshot.js
CHANGED
|
@@ -8,6 +8,7 @@ import { parseMetadata } from './WorldObject.svelte';
|
|
|
8
8
|
import { rgbaBytesToFloat32, rgbaToHex } from './color';
|
|
9
9
|
import { asFloat32Array, STRIDE } from './buffer';
|
|
10
10
|
import { createPose } from './transform';
|
|
11
|
+
import { createBufferGeometry } from './attribute';
|
|
11
12
|
const vec3 = new Vector3();
|
|
12
13
|
const origin = new Vector3();
|
|
13
14
|
const direction = new Vector3();
|
|
@@ -222,10 +223,15 @@ const spawnEntitiesFromDrawing = (world, drawing) => {
|
|
|
222
223
|
for (let i = 0, l = positions.length; i < l; i += 1) {
|
|
223
224
|
positions[i] *= 0.001;
|
|
224
225
|
}
|
|
225
|
-
|
|
226
|
+
const colors = drawing.metadata?.colors
|
|
227
|
+
? rgbaBytesToFloat32(drawing.metadata.colors)
|
|
228
|
+
: undefined;
|
|
229
|
+
const geometry = createBufferGeometry(positions, colors);
|
|
230
|
+
entityTraits.push(traits.BufferGeometry(geometry));
|
|
226
231
|
if (geometryType.value.pointSize) {
|
|
227
232
|
entityTraits.push(traits.PointSize(geometryType.value.pointSize * 0.001));
|
|
228
233
|
}
|
|
234
|
+
entityTraits.push(traits.Points);
|
|
229
235
|
}
|
|
230
236
|
else if (geometryType?.case === 'nurbs') {
|
|
231
237
|
const { degree = 3, knots: knotsBuffer, weights: weightsBuffer, controlPoints: controlPointsBuffer, } = geometryType.value;
|