@viamrobotics/motion-tools 1.15.8 → 1.18.0

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 (87) 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/{Lasso → Selection}/Debug.svelte +8 -8
  35. package/dist/components/{Lasso → Selection}/Debug.svelte.d.ts +2 -2
  36. package/dist/components/Selection/Ellipse.svelte +294 -0
  37. package/dist/components/Selection/Ellipse.svelte.d.ts +7 -0
  38. package/dist/components/{Lasso → Selection}/Lasso.svelte +33 -61
  39. package/dist/components/{Lasso → Selection}/Lasso.svelte.d.ts +1 -0
  40. package/dist/components/Selection/Tool.svelte +94 -0
  41. package/dist/components/{Lasso → Selection}/Tool.svelte.d.ts +2 -2
  42. package/dist/components/{Lasso → Selection}/traits.d.ts +11 -2
  43. package/dist/components/{Lasso → Selection}/traits.js +7 -2
  44. package/dist/components/Selection/useSelectionPlugin.svelte.d.ts +8 -0
  45. package/dist/components/Selection/useSelectionPlugin.svelte.js +24 -0
  46. package/dist/components/Selection/utils.d.ts +5 -0
  47. package/dist/components/Selection/utils.js +38 -0
  48. package/dist/components/Snapshot.svelte +4 -2
  49. package/dist/components/overlay/AddRelationship.svelte +1 -2
  50. package/dist/components/overlay/AddRelationship.svelte.d.ts +1 -1
  51. package/dist/components/overlay/Details.svelte +12 -12
  52. package/dist/components/overlay/Details.svelte.d.ts +8 -1
  53. package/dist/components/overlay/settings/Settings.svelte +8 -1
  54. package/dist/components/xr/OriginMarker.svelte +94 -17
  55. package/dist/components/xr/XR.svelte +1 -1
  56. package/dist/draw.d.ts +13 -0
  57. package/dist/draw.js +428 -0
  58. package/dist/ecs/traits.d.ts +31 -13
  59. package/dist/ecs/traits.js +25 -8
  60. package/dist/geometry.js +3 -0
  61. package/dist/hooks/useDrawAPI.svelte.js +61 -24
  62. package/dist/hooks/useDrawService.svelte.d.ts +12 -0
  63. package/dist/hooks/useDrawService.svelte.js +240 -0
  64. package/dist/hooks/usePointcloudObjects.svelte.js +7 -2
  65. package/dist/hooks/usePointclouds.svelte.js +7 -2
  66. package/dist/hooks/useSettings.svelte.d.ts +3 -2
  67. package/dist/hooks/useSettings.svelte.js +2 -2
  68. package/dist/hooks/useWorldState.svelte.js +5 -52
  69. package/dist/index.d.ts +9 -1
  70. package/dist/index.js +10 -1
  71. package/dist/lib.d.ts +2 -0
  72. package/dist/lib.js +2 -0
  73. package/dist/loaders/pcd/index.d.ts +1 -1
  74. package/dist/loaders/pcd/messages.d.ts +2 -2
  75. package/dist/loaders/pcd/worker.inline.d.ts +1 -1
  76. package/dist/loaders/pcd/worker.inline.js +229 -187
  77. package/dist/loaders/pcd/worker.js +2 -2
  78. package/dist/metadata.d.ts +9 -15
  79. package/dist/metadata.js +45 -9
  80. package/dist/plugins/bvh.svelte.js +6 -2
  81. package/dist/snapshot.d.ts +3 -9
  82. package/dist/snapshot.js +11 -204
  83. package/dist/three/InstancedArrows/InstancedArrows.js +3 -2
  84. package/package.json +14 -11
  85. package/dist/components/Lasso/Tool.svelte +0 -108
  86. package/dist/components/xr/Hands.svelte +0 -23
  87. package/dist/components/xr/Hands.svelte.d.ts +0 -18
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
  */
@@ -54,7 +54,12 @@ export const Material = trait({
54
54
  export const DepthTest = trait(() => true);
55
55
  export const Arrow = trait(() => true);
56
56
  export const Positions = trait(() => new Float32Array());
57
+ /** Per-vertex RGB colors packed as [r, g, b, ...], stride of 3, values 0-255. */
57
58
  export const Colors = trait(() => new Uint8Array());
59
+ /**
60
+ * Per-vertex opacity values packed as uint8 (0-255).
61
+ */
62
+ export const Opacities = trait(() => new Uint8Array());
58
63
  export const Instances = trait({
59
64
  count: 0,
60
65
  });
@@ -77,12 +82,7 @@ export const Capsule = trait({ l: 200, r: 50 });
77
82
  * A sphere, in mm
78
83
  */
79
84
  export const Sphere = trait({ r: 200 });
80
- export const PointColor = trait({ r: 0, g: 0, b: 0 });
81
- /** format [x, y, z, ...] */
82
- export const LinePositions = trait(() => new Float32Array());
83
85
  export const BufferGeometry = trait(() => new ThreeBufferGeometry());
84
- /** format [r, g, b, ...] */
85
- export const VertexColors = trait(() => new Float32Array());
86
86
  export const GLTF = trait(() => ({
87
87
  source: { url: '' },
88
88
  animationName: '',
@@ -91,6 +91,7 @@ export const Scale = trait({ x: 1, y: 1, z: 1 });
91
91
  export const FramesAPI = trait(() => true);
92
92
  export const GeometriesAPI = trait(() => true);
93
93
  export const DrawAPI = trait(() => true);
94
+ export const DrawServiceAPI = trait(() => true);
94
95
  export const WorldStateStoreAPI = trait(() => true);
95
96
  export const SnapshotAPI = trait(() => true);
96
97
  /**
@@ -98,16 +99,32 @@ export const SnapshotAPI = trait(() => true);
98
99
  */
99
100
  export const DroppedFile = trait(() => true);
100
101
  export const ShowAxesHelper = trait(() => true);
101
- // === Shape Properties ===
102
+ /**
103
+ * Marker trait for entities that should be rendered in screen space (CSS pixels)
104
+ */
105
+ export const ScreenSpace = trait(() => true);
102
106
  /**
103
107
  * Point size, in mm
104
108
  */
105
- export const PointSize = trait(() => 10);
109
+ export const PointSize = trait(() => 5);
110
+ /**
111
+ * Line positions, format [x, y, z, ...]
112
+ */
113
+ export const LinePositions = trait(() => new Float32Array());
106
114
  /**
107
- * Line width, in mm
115
+ * Line width, in mm when in world units, or CSS pixels when in screen space
108
116
  */
109
117
  export const LineWidth = trait(() => 5);
118
+ /**
119
+ * Dot colors for line vertices, format [r, g, b, a, ...]
120
+ */
121
+ export const DotColors = trait(() => new Uint8Array());
122
+ /**
123
+ * Dot size for line vertices, in mm when in world units, or CSS pixels when in screen space
124
+ */
125
+ export const DotSize = trait(() => 10);
110
126
  export const ReferenceFrame = trait(() => true);
127
+ export const SelectToolInteractionLayer = trait(() => true);
111
128
  /**
112
129
  * This entity can be safetly removed from the scene by the user
113
130
  */
package/dist/geometry.js CHANGED
@@ -58,3 +58,6 @@ export const createSphere = (sphere) => {
58
58
  r: sphere?.radiusMm ?? 0,
59
59
  };
60
60
  };
61
+ export const isPointCloud = (geometry) => {
62
+ return geometry?.case === 'pointcloud';
63
+ };