@viamrobotics/motion-tools 1.16.0 → 1.18.1

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.
Files changed (77) hide show
  1. package/dist/attribute.d.ts +3 -2
  2. package/dist/attribute.js +24 -16
  3. package/dist/buf/draw/v1/drawing_pb.d.ts +33 -16
  4. package/dist/buf/draw/v1/drawing_pb.js +35 -17
  5. package/dist/buf/draw/v1/metadata_pb.d.ts +44 -3
  6. package/dist/buf/draw/v1/metadata_pb.js +54 -3
  7. package/dist/buf/draw/v1/scene_pb.d.ts +6 -6
  8. package/dist/buf/draw/v1/scene_pb.js +7 -7
  9. package/dist/buffer.d.ts +54 -45
  10. package/dist/buffer.js +91 -57
  11. package/dist/color.d.ts +1 -2
  12. package/dist/color.js +5 -12
  13. package/dist/components/App.svelte +18 -3
  14. package/dist/components/App.svelte.d.ts +15 -2
  15. package/dist/components/Entities/Arrows/ArrowGroups.svelte +5 -6
  16. package/dist/components/Entities/Arrows/Arrows.svelte +9 -0
  17. package/dist/components/Entities/Entities.svelte +18 -1
  18. package/dist/components/Entities/Frame.svelte +7 -1
  19. package/dist/components/Entities/GLTF.svelte +13 -2
  20. package/dist/components/Entities/Line.svelte +46 -18
  21. package/dist/components/Entities/LineDots.svelte +38 -8
  22. package/dist/components/Entities/LineDots.svelte.d.ts +2 -2
  23. package/dist/components/Entities/LineGeometry.svelte +2 -1
  24. package/dist/components/Entities/LineGeometry.svelte.d.ts +2 -0
  25. package/dist/components/Entities/Mesh.svelte +8 -1
  26. package/dist/components/Entities/Points.svelte +22 -11
  27. package/dist/components/Entities/hooks/useEntityEvents.svelte.js +6 -2
  28. package/dist/components/FileDrop/FileDrop.svelte +5 -1
  29. package/dist/components/KeyboardControls.svelte +2 -10
  30. package/dist/components/PCD.svelte +11 -4
  31. package/dist/components/PCD.svelte.d.ts +3 -1
  32. package/dist/components/SceneProviders.svelte +2 -0
  33. package/dist/components/Selected.svelte +2 -12
  34. package/dist/components/Selection/Ellipse.svelte +2 -0
  35. package/dist/components/Selection/Lasso.svelte +2 -0
  36. package/dist/components/Selection/Tool.svelte +7 -56
  37. package/dist/components/Selection/Tool.svelte.d.ts +2 -2
  38. package/dist/components/Selection/useSelectionPlugin.svelte.d.ts +8 -0
  39. package/dist/components/Selection/useSelectionPlugin.svelte.js +24 -0
  40. package/dist/components/Snapshot.svelte +4 -2
  41. package/dist/components/overlay/AddRelationship.svelte +1 -2
  42. package/dist/components/overlay/AddRelationship.svelte.d.ts +1 -1
  43. package/dist/components/overlay/Details.svelte +12 -12
  44. package/dist/components/overlay/Details.svelte.d.ts +8 -1
  45. package/dist/components/overlay/settings/Settings.svelte +8 -1
  46. package/dist/components/xr/XR.svelte +1 -1
  47. package/dist/draw.d.ts +13 -0
  48. package/dist/draw.js +428 -0
  49. package/dist/ecs/traits.d.ts +31 -13
  50. package/dist/ecs/traits.js +25 -8
  51. package/dist/geometry.js +3 -0
  52. package/dist/hooks/useDrawAPI.svelte.js +61 -24
  53. package/dist/hooks/useDrawService.svelte.d.ts +12 -0
  54. package/dist/hooks/useDrawService.svelte.js +240 -0
  55. package/dist/hooks/usePointcloudObjects.svelte.js +7 -2
  56. package/dist/hooks/usePointclouds.svelte.js +7 -2
  57. package/dist/hooks/useSettings.svelte.d.ts +2 -1
  58. package/dist/hooks/useSettings.svelte.js +1 -1
  59. package/dist/hooks/useWorldState.svelte.js +5 -52
  60. package/dist/index.d.ts +8 -0
  61. package/dist/index.js +9 -0
  62. package/dist/lib.d.ts +2 -0
  63. package/dist/lib.js +2 -0
  64. package/dist/loaders/pcd/index.d.ts +1 -1
  65. package/dist/loaders/pcd/messages.d.ts +2 -2
  66. package/dist/loaders/pcd/worker.inline.d.ts +1 -1
  67. package/dist/loaders/pcd/worker.inline.js +229 -187
  68. package/dist/loaders/pcd/worker.js +2 -2
  69. package/dist/metadata.d.ts +9 -15
  70. package/dist/metadata.js +45 -9
  71. package/dist/plugins/bvh.svelte.js +6 -2
  72. package/dist/snapshot.d.ts +3 -9
  73. package/dist/snapshot.js +11 -204
  74. package/dist/three/InstancedArrows/InstancedArrows.js +3 -2
  75. package/package.json +14 -11
  76. package/dist/components/xr/Hands.svelte +0 -23
  77. package/dist/components/xr/Hands.svelte.d.ts +0 -18
@@ -12,6 +12,9 @@
12
12
  </script>
13
13
 
14
14
  <script lang="ts">
15
+ import type { Entity } from 'koota'
16
+ import type { Snippet } from 'svelte'
17
+
15
18
  import { draggable } from '@neodrag/svelte'
16
19
  import { isInstanceOf, useTask } from '@threlte/core'
17
20
  import { Button, Icon, Input, Select, Tooltip } from '@viamrobotics/prime-core'
@@ -34,7 +37,11 @@
34
37
  } from '../../hooks/useSelection.svelte'
35
38
  import { createPose } from '../../transform'
36
39
 
37
- const { ...rest } = $props()
40
+ interface Props {
41
+ details?: Snippet<[{ entity: Entity }]>
42
+ }
43
+
44
+ const { details }: Props = $props()
38
45
 
39
46
  const world = useWorld()
40
47
  const controls = useCameraControls()
@@ -94,7 +101,7 @@
94
101
  }
95
102
  }
96
103
 
97
- const { start, stop } = useTask(
104
+ useTask(
98
105
  () => {
99
106
  object3d?.getWorldPosition(vec3)
100
107
  if (!vec3.equals(worldPosition)) {
@@ -114,19 +121,11 @@
114
121
  }
115
122
  },
116
123
  {
117
- autoStart: false,
118
124
  autoInvalidate: false,
125
+ running: () => object3d !== undefined,
119
126
  }
120
127
  )
121
128
 
122
- $effect.pre(() => {
123
- if (object3d) {
124
- start()
125
- } else {
126
- stop()
127
- }
128
- })
129
-
130
129
  $effect(() => {
131
130
  if (entity) {
132
131
  const worldPose = createPose({
@@ -266,7 +265,6 @@
266
265
  bounds: 'body',
267
266
  handle: dragElement,
268
267
  }}
269
- {...rest}
270
268
  >
271
269
  <div
272
270
  class="flex cursor-move items-center justify-between gap-2 pb-2"
@@ -662,6 +660,8 @@
662
660
  </div>
663
661
  {/if}
664
662
 
663
+ {@render details?.({ entity })}
664
+
665
665
  <h3 class="text-subtle-2 pt-3 pb-2">Actions</h3>
666
666
 
667
667
  {#if focusedEntity.current}
@@ -1,3 +1,10 @@
1
- declare const Details: import("svelte").Component<Record<string, any>, {}, "">;
1
+ import type { Entity } from 'koota';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ details?: Snippet<[{
5
+ entity: Entity;
6
+ }]>;
7
+ }
8
+ declare const Details: import("svelte").Component<Props, {}, "">;
2
9
  type Details = ReturnType<typeof Details>;
3
10
  export default Details;
@@ -5,6 +5,7 @@
5
5
  import { useResourceNames } from '@viamrobotics/svelte-sdk'
6
6
  import { PersistedState } from 'runed'
7
7
  import { onMount } from 'svelte'
8
+ import { Color } from 'three'
8
9
 
9
10
  import DashboardButton from '../dashboard/Button.svelte'
10
11
  import XRControllerSettings from '../../xr/XRControllerSettings.svelte'
@@ -54,6 +55,8 @@
54
55
 
55
56
  const isOpen = new PersistedState('settings-is-open', false)
56
57
  const activeTab = new PersistedState('settings-active-tab', 'Connection')
58
+
59
+ const colorHex = $derived(`#${new Color(settings.current.pointColor).getHexString()}`)
57
60
  </script>
58
61
 
59
62
  <Portal id="dashboard">
@@ -122,7 +125,11 @@
122
125
  <div class="w-20">
123
126
  <Input
124
127
  type="color"
125
- bind:value={settings.current.pointColor}
128
+ value={colorHex}
129
+ on:change={(event) => {
130
+ const value = (event.target as HTMLInputElement).value
131
+ settings.current.pointColor = value
132
+ }}
126
133
  on:keydown={(event) => event.stopImmediatePropagation()}
127
134
  />
128
135
  </div>
@@ -72,7 +72,7 @@
72
72
  {#if enableXR}
73
73
  <XR
74
74
  onsessionstart={() => {
75
- origin.set([0, 0, -2])
75
+ origin.set([-1, -1, 0])
76
76
  }}
77
77
  onsessionend={() => {
78
78
  origin.set([0, 0, 0])
package/dist/draw.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { TransformWithUUID } from '@viamrobotics/sdk';
2
+ import type { Entity, Trait, World } from 'koota';
3
+ import type { Transform as TransformProto } from './buf/common/v1/common_pb';
4
+ import type { Drawing } from './buf/draw/v1/drawing_pb';
5
+ export type Transform = TransformWithUUID | TransformProto;
6
+ type Options = {
7
+ removable?: boolean;
8
+ };
9
+ export declare const drawTransform: (world: World, { referenceFrame, poseInObserverFrame, physicalObject, metadata }: Transform, api: Trait, options?: Options) => Entity;
10
+ export declare const drawDrawing: (world: World, drawing: Drawing, api: Trait, options?: Options) => Entity[];
11
+ export declare const updateTransform: (entity: Entity, { poseInObserverFrame, physicalObject, metadata }: Transform, options?: Options) => void;
12
+ export declare const updateDrawing: (world: World, entities: Entity[], drawing: Drawing, api: Trait, options?: Options) => Entity[];
13
+ export {};
package/dist/draw.js ADDED
@@ -0,0 +1,428 @@
1
+ import { Vector3, Vector4 } from 'three';
2
+ import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
3
+ import { createBufferGeometry, updateBufferGeometry } from './attribute';
4
+ import { asFloat32Array, asOpacity, asRGB, inMeters, isSingleColor, isVertexColors, STRIDE, } from './buffer';
5
+ import { traits } from './ecs';
6
+ import { parsePcdInWorker } from './loaders/pcd';
7
+ import { metadataFromStruct } from './metadata';
8
+ import { createPose } from './transform';
9
+ import { ColorFormat } from './buf/draw/v1/metadata_pb';
10
+ import { isPointCloud } from './geometry';
11
+ const vec3 = new Vector3();
12
+ const rgb = { r: 0, g: 0, b: 0 };
13
+ const DEFAULT_LINE_WIDTH = 5;
14
+ const DEFAULT_POINT_SIZE = 10;
15
+ const DEFAULT_NURBS_DEGREE = 3;
16
+ const DEFAULT_NURBS_WEIGHT = 1;
17
+ const DEFAULT_ANIMATION_NAME = '';
18
+ const DEFAULT_ARROWS_COLORS = new Uint8Array([0, 255, 0]);
19
+ const DEFAULT_LINE_COLORS = new Uint8Array([0, 128, 255]);
20
+ const DEFAULT_LINE_DOT_COLORS = new Uint8Array([0, 0, 139]);
21
+ const DEFAULT_POINTS_COLORS = new Uint8Array([51, 51, 51]);
22
+ const DEFAULT_NURBS_COLORS = new Uint8Array([0, 255, 255]);
23
+ const DEFAULT_OPACITY = 1;
24
+ export const drawTransform = (world, { referenceFrame, poseInObserverFrame, physicalObject, metadata }, api, options = { removable: true }) => {
25
+ const entityTraits = [
26
+ traits.Name(referenceFrame),
27
+ traits.Pose(createPose(poseInObserverFrame?.pose)),
28
+ api,
29
+ ];
30
+ if (physicalObject) {
31
+ entityTraits.push(traits.Geometry(physicalObject));
32
+ const center = physicalObject.center;
33
+ if (center)
34
+ entityTraits.push(traits.Center(center));
35
+ }
36
+ else {
37
+ entityTraits.push(traits.ReferenceFrame);
38
+ }
39
+ if (options.removable)
40
+ entityTraits.push(traits.Removable);
41
+ const parent = poseInObserverFrame?.referenceFrame;
42
+ if (parent && parent !== 'world')
43
+ entityTraits.push(traits.Parent(parent));
44
+ const parsedMetadata = metadataFromStruct(metadata?.fields);
45
+ if (parsedMetadata.showAxesHelper)
46
+ entityTraits.push(traits.ShowAxesHelper);
47
+ if (parsedMetadata.invisible)
48
+ entityTraits.push(traits.Invisible);
49
+ const { colors, opacities } = parsedMetadata;
50
+ const pointCloud = isPointCloud(physicalObject?.geometryType)
51
+ ? physicalObject.geometryType.value.pointCloud
52
+ : undefined;
53
+ if (colors && !pointCloud) {
54
+ if (isVertexColors(colors)) {
55
+ entityTraits.push(traits.Colors(colors));
56
+ }
57
+ else {
58
+ entityTraits.push(traits.Color(asRGB(colors, rgb)));
59
+ }
60
+ }
61
+ entityTraits.push(traits.Opacity(asOpacity(opacities, DEFAULT_OPACITY)));
62
+ const entity = world.spawn(...entityTraits);
63
+ if (pointCloud)
64
+ parsePointCloud(world, entity, pointCloud, parsedMetadata);
65
+ return entity;
66
+ };
67
+ export const drawDrawing = (world, drawing, api, options = { removable: true }) => {
68
+ const { referenceFrame, poseInObserverFrame, physicalObject, metadata } = drawing;
69
+ if (physicalObject?.geometryType?.case === 'model')
70
+ return drawModel(world, drawing, api, options);
71
+ const entity = world.spawn(traits.Name(referenceFrame), traits.Pose(createPose(poseInObserverFrame?.pose)), api);
72
+ const parent = poseInObserverFrame?.referenceFrame;
73
+ if (parent && parent !== 'world')
74
+ entity.add(traits.Parent(parent));
75
+ if (options.removable)
76
+ entity.add(traits.Removable);
77
+ if (metadata?.showAxesHelper)
78
+ entity.add(traits.ShowAxesHelper);
79
+ if (metadata?.invisible)
80
+ entity.add(traits.Invisible);
81
+ applyShape(entity, drawing);
82
+ return [entity];
83
+ };
84
+ export const updateTransform = (entity, { poseInObserverFrame, physicalObject, metadata }, options = { removable: true }) => {
85
+ entity.set(traits.Pose, createPose(poseInObserverFrame?.pose));
86
+ const parent = poseInObserverFrame?.referenceFrame;
87
+ if (parent && parent !== 'world')
88
+ entity.set(traits.Parent, parent);
89
+ if (physicalObject) {
90
+ traits.updateGeometryTrait(entity, physicalObject);
91
+ const center = physicalObject.center;
92
+ if (center) {
93
+ entity.set(traits.Center, center);
94
+ }
95
+ else {
96
+ entity.remove(traits.Center);
97
+ }
98
+ }
99
+ const parsedMetadata = metadataFromStruct(metadata?.fields);
100
+ if (parsedMetadata.showAxesHelper)
101
+ entity.add(traits.ShowAxesHelper);
102
+ else
103
+ entity.remove(traits.ShowAxesHelper);
104
+ if (parsedMetadata.invisible)
105
+ entity.add(traits.Invisible);
106
+ else
107
+ entity.remove(traits.Invisible);
108
+ const { colors, opacities } = parsedMetadata;
109
+ if (colors) {
110
+ if (isPointCloud(physicalObject?.geometryType)) {
111
+ updateColors(entity, parsedMetadata);
112
+ }
113
+ else {
114
+ addColorTraits(entity, colors);
115
+ }
116
+ }
117
+ const opacity = asOpacity(opacities, DEFAULT_OPACITY);
118
+ if (opacity < 1)
119
+ entity.add(traits.Opacity(opacity));
120
+ if (options.removable)
121
+ entity.add(traits.Removable);
122
+ if (!options.removable)
123
+ entity.remove(traits.Removable);
124
+ };
125
+ export const updateDrawing = (world, entities, drawing, api, options = { removable: true }) => {
126
+ const { poseInObserverFrame, physicalObject, metadata } = drawing;
127
+ if (physicalObject?.geometryType?.case === 'model') {
128
+ for (const entity of entities) {
129
+ if (world.has(entity))
130
+ entity.destroy();
131
+ }
132
+ return drawDrawing(world, drawing, api, options);
133
+ }
134
+ if (entities.length === 0)
135
+ return entities;
136
+ const entity = entities[0];
137
+ if (!world.has(entity))
138
+ return entities;
139
+ entity.set(traits.Pose, createPose(poseInObserverFrame?.pose));
140
+ const parent = poseInObserverFrame?.referenceFrame;
141
+ if (parent && parent !== 'world')
142
+ entity.set(traits.Parent, parent);
143
+ if (metadata?.showAxesHelper)
144
+ entity.add(traits.ShowAxesHelper);
145
+ if (!metadata?.showAxesHelper)
146
+ entity.remove(traits.ShowAxesHelper);
147
+ if (metadata?.invisible)
148
+ entity.add(traits.Invisible);
149
+ if (!metadata?.invisible)
150
+ entity.remove(traits.Invisible);
151
+ updateShape(entity, drawing);
152
+ return entities;
153
+ };
154
+ const applyShape = (entity, { physicalObject, metadata }) => {
155
+ const colors = metadata?.colors;
156
+ const opacities = metadata?.opacities;
157
+ const geometryType = physicalObject?.geometryType;
158
+ const opacity = asOpacity(opacities, DEFAULT_OPACITY);
159
+ entity.add(traits.Opacity(opacity));
160
+ switch (geometryType?.case) {
161
+ case 'arrows': {
162
+ const poses = asFloat32Array(geometryType.value.poses);
163
+ entity.add(traits.Positions(poses));
164
+ entity.add(traits.Instances({ count: poses.length / STRIDE.ARROWS }));
165
+ addColorTraits(entity, colors ?? DEFAULT_ARROWS_COLORS);
166
+ entity.add(traits.Arrows({ headAtPose: true }));
167
+ break;
168
+ }
169
+ case 'line': {
170
+ const positions = asFloat32Array(geometryType.value.positions, inMeters);
171
+ const center = physicalObject?.center;
172
+ if (center)
173
+ entity.add(traits.Center(center));
174
+ addColorTraits(entity, colors ?? DEFAULT_LINE_COLORS);
175
+ const lineWidth = geometryType.value.lineWidth ?? DEFAULT_LINE_WIDTH;
176
+ entity.add(traits.LineWidth(lineWidth));
177
+ entity.add(traits.DotSize(geometryType.value.dotSize ?? lineWidth));
178
+ entity.add(traits.LinePositions(positions));
179
+ entity.add(traits.DotColors(geometryType.value.dotColors ?? DEFAULT_LINE_DOT_COLORS));
180
+ break;
181
+ }
182
+ case 'points': {
183
+ const positions = asFloat32Array(geometryType.value.positions, inMeters);
184
+ const center = physicalObject?.center;
185
+ if (center)
186
+ entity.add(traits.Center(center));
187
+ addColorTraits(entity, colors ?? DEFAULT_POINTS_COLORS);
188
+ entity.add(traits.PointSize(geometryType.value.pointSize ?? DEFAULT_POINT_SIZE));
189
+ entity.add(traits.BufferGeometry(createBufferGeometry(positions, {
190
+ colors: isVertexColors(colors) ? colors : undefined,
191
+ colorFormat: metadata?.colorFormat ?? ColorFormat.UNSPECIFIED,
192
+ })));
193
+ entity.add(traits.Points);
194
+ break;
195
+ }
196
+ case 'nurbs': {
197
+ const { degree = DEFAULT_NURBS_DEGREE, knots: knotsBuffer, weights: weightsBuffer, controlPoints: controlPointsBuffer, } = geometryType.value;
198
+ const knots = asFloat32Array(knotsBuffer).values().toArray();
199
+ const weights = weightsBuffer ? asFloat32Array(weightsBuffer) : [];
200
+ const controlPointsArray = asFloat32Array(controlPointsBuffer);
201
+ const numControlPoints = controlPointsArray.length / STRIDE.NURBS_CONTROL_POINTS;
202
+ const controlPoints = Array.from({ length: numControlPoints });
203
+ for (let j = 0; j < numControlPoints; j += 1) {
204
+ const idx = j * STRIDE.NURBS_CONTROL_POINTS;
205
+ vec3
206
+ .set(controlPointsArray[idx], controlPointsArray[idx + 1], controlPointsArray[idx + 2])
207
+ .multiplyScalar(0.001);
208
+ controlPoints[j] = new Vector4(vec3.x, vec3.y, vec3.z, weights[j] ?? DEFAULT_NURBS_WEIGHT);
209
+ }
210
+ const curve = new NURBSCurve(degree, knots, controlPoints);
211
+ const numPoints = 600;
212
+ const points = new Float32Array(numPoints * 3);
213
+ for (let i = 0; i < numPoints; i += 1) {
214
+ const t = i / (numPoints - 1);
215
+ curve.getPointAt(t, vec3);
216
+ points[i * 3 + 0] = vec3.x;
217
+ points[i * 3 + 1] = vec3.y;
218
+ points[i * 3 + 2] = vec3.z;
219
+ }
220
+ const center = physicalObject?.center;
221
+ if (center)
222
+ entity.add(traits.Center(center));
223
+ addColorTraits(entity, colors ?? DEFAULT_NURBS_COLORS);
224
+ entity.add(traits.LineWidth(geometryType.value.lineWidth ?? DEFAULT_LINE_WIDTH));
225
+ entity.add(traits.LinePositions(points));
226
+ break;
227
+ }
228
+ default: {
229
+ const center = physicalObject?.center;
230
+ if (center)
231
+ entity.add(traits.Center(center));
232
+ if (colors)
233
+ addColorTraits(entity, colors);
234
+ break;
235
+ }
236
+ }
237
+ };
238
+ const drawModel = (world, { referenceFrame, poseInObserverFrame, physicalObject, metadata }, api, { removable = true }) => {
239
+ const entities = [];
240
+ const parent = poseInObserverFrame?.referenceFrame;
241
+ const geometryType = physicalObject?.geometryType;
242
+ if (geometryType?.case !== 'model')
243
+ return entities;
244
+ const baseTraits = [
245
+ traits.Name(referenceFrame),
246
+ traits.Pose(createPose(poseInObserverFrame?.pose)),
247
+ api,
248
+ ];
249
+ if (parent && parent !== 'world')
250
+ baseTraits.push(traits.Parent(parent));
251
+ if (removable)
252
+ baseTraits.push(traits.Removable);
253
+ if (metadata?.invisible)
254
+ baseTraits.push(traits.Invisible);
255
+ entities.push(world.spawn(...baseTraits, traits.ReferenceFrame));
256
+ const { scale, animationName } = geometryType.value;
257
+ let i = 1;
258
+ for (const asset of geometryType.value.assets) {
259
+ const subEntityTraits = [
260
+ traits.Name(`${referenceFrame} model ${i++}`),
261
+ traits.Parent(referenceFrame),
262
+ api,
263
+ ];
264
+ if (scale)
265
+ subEntityTraits.push(traits.Scale(scale));
266
+ if (asset.content.case === 'url') {
267
+ subEntityTraits.push(traits.GLTF({
268
+ source: { url: asset.content.value },
269
+ animationName: animationName ?? DEFAULT_ANIMATION_NAME,
270
+ }));
271
+ }
272
+ else if (asset.content.value) {
273
+ subEntityTraits.push(traits.GLTF({
274
+ source: { glb: asset.content.value },
275
+ animationName: animationName ?? DEFAULT_ANIMATION_NAME,
276
+ }));
277
+ }
278
+ entities.push(world.spawn(...subEntityTraits));
279
+ }
280
+ return entities;
281
+ };
282
+ const parsePointCloud = (world, entity, pointCloud, metadata) => {
283
+ parsePcdInWorker(new Uint8Array(pointCloud)).then((pointcloud) => {
284
+ if (!world.has(entity)) {
285
+ console.error('Entity was destroyed before pointcloud could be added');
286
+ return;
287
+ }
288
+ const { colors, colorFormat } = metadata;
289
+ const numPoints = pointcloud.positions.length / STRIDE.POSITIONS;
290
+ if (colors && isSingleColor(colors))
291
+ entity.add(traits.Color(asRGB(colors, rgb)));
292
+ let vertexColors = pointcloud.colors;
293
+ if (colors && colors.length > 0)
294
+ vertexColors = parseColors(colors, numPoints);
295
+ const geometry = createBufferGeometry(pointcloud.positions, {
296
+ colors: vertexColors ?? undefined,
297
+ colorFormat,
298
+ });
299
+ entity.add(traits.BufferGeometry(geometry));
300
+ entity.add(traits.Points);
301
+ });
302
+ };
303
+ const updateColors = (entity, metadata) => {
304
+ const buffer = entity.get(traits.BufferGeometry);
305
+ if (!buffer) {
306
+ if (metadata.colors)
307
+ addColorTraits(entity, metadata.colors);
308
+ return;
309
+ }
310
+ const position = buffer.getAttribute('position');
311
+ const count = position?.count ?? 0;
312
+ const array = position?.array;
313
+ updateBufferGeometry(buffer, array, {
314
+ colors: parseColors(metadata.colors, count),
315
+ colorFormat: metadata.colorFormat,
316
+ });
317
+ };
318
+ const parseColors = (from, count) => {
319
+ const colors = from ?? new Uint8Array([255, 0, 0]);
320
+ if (isVertexColors(colors))
321
+ return colors;
322
+ const expanded = new Uint8Array(count * STRIDE.COLORS_RGB);
323
+ for (let i = 0; i < count; i++) {
324
+ for (let c = 0; c < STRIDE.COLORS_RGB; c++) {
325
+ expanded[i * STRIDE.COLORS_RGB + c] = colors[c];
326
+ }
327
+ }
328
+ return expanded;
329
+ };
330
+ const updateShape = (entity, { physicalObject, metadata }) => {
331
+ const geometryType = physicalObject?.geometryType;
332
+ entity.set(traits.Opacity, asOpacity(metadata?.opacities, DEFAULT_OPACITY));
333
+ switch (geometryType?.case) {
334
+ case 'arrows': {
335
+ const poses = asFloat32Array(geometryType.value.poses, inMeters);
336
+ entity.set(traits.Positions, poses);
337
+ entity.set(traits.Instances, { count: poses.length / STRIDE.ARROWS });
338
+ setColorTraits(entity, metadata?.colors ?? DEFAULT_ARROWS_COLORS);
339
+ break;
340
+ }
341
+ case 'line': {
342
+ const positions = asFloat32Array(geometryType.value.positions, inMeters);
343
+ const center = physicalObject?.center;
344
+ if (center)
345
+ entity.set(traits.Center, center);
346
+ setColorTraits(entity, metadata?.colors ?? DEFAULT_LINE_COLORS);
347
+ const lineWidth = geometryType.value.lineWidth ?? DEFAULT_LINE_WIDTH;
348
+ entity.set(traits.LineWidth, lineWidth);
349
+ entity.set(traits.DotSize, geometryType.value.dotSize ?? lineWidth);
350
+ entity.set(traits.LinePositions, positions);
351
+ const dotColors = geometryType.value.dotColors;
352
+ entity.set(traits.DotColors, dotColors ?? DEFAULT_LINE_DOT_COLORS);
353
+ break;
354
+ }
355
+ case 'points': {
356
+ const positions = asFloat32Array(geometryType.value.positions, inMeters);
357
+ const center = physicalObject?.center;
358
+ if (center)
359
+ entity.set(traits.Center, center);
360
+ setColorTraits(entity, metadata?.colors ?? DEFAULT_POINTS_COLORS);
361
+ entity.set(traits.PointSize, geometryType.value.pointSize ?? DEFAULT_POINT_SIZE);
362
+ const vertexColors = isVertexColors(metadata?.colors) ? metadata?.colors : undefined;
363
+ const pointsMetadata = {
364
+ colors: vertexColors,
365
+ colorFormat: metadata?.colorFormat ?? ColorFormat.UNSPECIFIED,
366
+ };
367
+ const buffer = entity.get(traits.BufferGeometry);
368
+ if (buffer) {
369
+ updateBufferGeometry(buffer, positions, pointsMetadata);
370
+ }
371
+ else {
372
+ entity.add(traits.BufferGeometry(createBufferGeometry(positions, pointsMetadata)));
373
+ entity.add(traits.Points);
374
+ }
375
+ break;
376
+ }
377
+ case 'nurbs': {
378
+ const { degree = DEFAULT_NURBS_DEGREE, knots: knotsBuffer, weights: weightsBuffer, controlPoints: controlPointsBuffer, } = geometryType.value;
379
+ const knots = [...asFloat32Array(knotsBuffer)];
380
+ const weights = weightsBuffer ? [...asFloat32Array(weightsBuffer)] : [];
381
+ const controlPointsArray = [...asFloat32Array(controlPointsBuffer)];
382
+ const numControlPoints = controlPointsArray.length / STRIDE.NURBS_CONTROL_POINTS;
383
+ const controlPoints = Array.from({ length: numControlPoints });
384
+ for (let j = 0; j < numControlPoints; j += 1) {
385
+ const idx = j * STRIDE.NURBS_CONTROL_POINTS;
386
+ vec3
387
+ .set(controlPointsArray[idx], controlPointsArray[idx + 1], controlPointsArray[idx + 2])
388
+ .multiplyScalar(0.001);
389
+ controlPoints[j] = new Vector4(vec3.x, vec3.y, vec3.z, weights[j] ?? DEFAULT_NURBS_WEIGHT);
390
+ }
391
+ const curve = new NURBSCurve(degree, knots, controlPoints);
392
+ const numPoints = 600;
393
+ const points = new Float32Array(numPoints * 3);
394
+ for (let i = 0; i < numPoints; i += 1) {
395
+ const t = i / (numPoints - 1);
396
+ curve.getPointAt(t, vec3);
397
+ points[i * 3 + 0] = vec3.x;
398
+ points[i * 3 + 1] = vec3.y;
399
+ points[i * 3 + 2] = vec3.z;
400
+ }
401
+ const center = physicalObject?.center;
402
+ if (center)
403
+ entity.set(traits.Center, center);
404
+ setColorTraits(entity, metadata?.colors ?? DEFAULT_NURBS_COLORS);
405
+ entity.set(traits.LineWidth, geometryType.value.lineWidth ?? DEFAULT_LINE_WIDTH);
406
+ entity.set(traits.LinePositions, points);
407
+ break;
408
+ }
409
+ }
410
+ };
411
+ const addColorTraits = (entity, colors) => {
412
+ if (isVertexColors(colors)) {
413
+ entity.add(traits.Colors(colors));
414
+ }
415
+ else {
416
+ entity.add(traits.Color(asRGB(colors, rgb)));
417
+ }
418
+ };
419
+ const setColorTraits = (entity, colors) => {
420
+ if (isVertexColors(colors)) {
421
+ entity.set(traits.Colors, colors);
422
+ entity.remove(traits.Color);
423
+ }
424
+ else {
425
+ entity.set(traits.Color, asRGB(colors, rgb));
426
+ entity.remove(traits.Colors);
427
+ }
428
+ };
@@ -80,8 +80,13 @@ export declare const Material: import("koota").Trait<{
80
80
  }>;
81
81
  export declare const DepthTest: import("koota").Trait<() => boolean>;
82
82
  export declare const Arrow: import("koota").Trait<() => boolean>;
83
- export declare const Positions: import("koota").Trait<() => Float32Array<ArrayBuffer>>;
84
- export declare const Colors: import("koota").Trait<() => Uint8Array<ArrayBuffer>>;
83
+ export declare const Positions: import("koota").Trait<() => Float32Array<ArrayBufferLike>>;
84
+ /** Per-vertex RGB colors packed as [r, g, b, ...], stride of 3, values 0-255. */
85
+ export declare const Colors: import("koota").Trait<() => Uint8Array<ArrayBufferLike>>;
86
+ /**
87
+ * Per-vertex opacity values packed as uint8 (0-255).
88
+ */
89
+ export declare const Opacities: import("koota").Trait<() => Uint8Array<ArrayBuffer>>;
85
90
  export declare const Instances: import("koota").Trait<{
86
91
  count: number;
87
92
  }>;
@@ -113,23 +118,14 @@ export declare const Capsule: import("koota").Trait<{
113
118
  export declare const Sphere: import("koota").Trait<{
114
119
  r: number;
115
120
  }>;
116
- export declare const PointColor: import("koota").Trait<{
117
- r: number;
118
- g: number;
119
- b: number;
120
- }>;
121
- /** format [x, y, z, ...] */
122
- export declare const LinePositions: import("koota").Trait<() => Float32Array<ArrayBuffer>>;
123
121
  export declare const BufferGeometry: import("koota").Trait<() => ThreeBufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>>;
124
- /** format [r, g, b, ...] */
125
- export declare const VertexColors: import("koota").Trait<() => Float32Array<ArrayBuffer>>;
126
122
  export declare const GLTF: import("koota").Trait<() => {
127
123
  source: {
128
124
  url: string;
129
125
  } | {
130
126
  gltf: ThreeGltf;
131
127
  } | {
132
- glb: Uint8Array<ArrayBuffer>;
128
+ glb: Uint8Array;
133
129
  };
134
130
  animationName: string;
135
131
  }>;
@@ -141,6 +137,7 @@ export declare const Scale: import("koota").Trait<{
141
137
  export declare const FramesAPI: import("koota").Trait<() => boolean>;
142
138
  export declare const GeometriesAPI: import("koota").Trait<() => boolean>;
143
139
  export declare const DrawAPI: import("koota").Trait<() => boolean>;
140
+ export declare const DrawServiceAPI: import("koota").Trait<() => boolean>;
144
141
  export declare const WorldStateStoreAPI: import("koota").Trait<() => boolean>;
145
142
  export declare const SnapshotAPI: import("koota").Trait<() => boolean>;
146
143
  /**
@@ -148,15 +145,36 @@ export declare const SnapshotAPI: import("koota").Trait<() => boolean>;
148
145
  */
149
146
  export declare const DroppedFile: import("koota").Trait<() => boolean>;
150
147
  export declare const ShowAxesHelper: import("koota").Trait<() => boolean>;
148
+ /**
149
+ * Marker trait for entities that should be rendered in screen space (CSS pixels)
150
+ */
151
+ export declare const ScreenSpace: import("koota").Trait<() => boolean>;
151
152
  /**
152
153
  * Point size, in mm
153
154
  */
154
155
  export declare const PointSize: import("koota").Trait<() => number>;
155
156
  /**
156
- * Line width, in mm
157
+ * Line positions, format [x, y, z, ...]
158
+ */
159
+ export declare const LinePositions: import("koota").Trait<() => Float32Array<ArrayBufferLike>>;
160
+ /**
161
+ * Line width, in mm when in world units, or CSS pixels when in screen space
157
162
  */
158
163
  export declare const LineWidth: import("koota").Trait<() => number>;
164
+ /**
165
+ * Dot colors for line vertices, format [r, g, b, a, ...]
166
+ */
167
+ export declare const DotColors: import("koota").Trait<() => Uint8Array<ArrayBufferLike>>;
168
+ /**
169
+ * Dot size for line vertices, in mm when in world units, or CSS pixels when in screen space
170
+ */
171
+ export declare const DotSize: import("koota").Trait<() => number>;
159
172
  export declare const ReferenceFrame: import("koota").Trait<() => boolean>;
173
+ /**
174
+ * Interaction layers for entities
175
+ */
176
+ export type InteractionLayerValue = 'selectTool';
177
+ export declare const SelectToolInteractionLayer: import("koota").Trait<() => boolean>;
160
178
  /**
161
179
  * This entity can be safetly removed from the scene by the user
162
180
  */