@viamrobotics/motion-tools 1.1.5 → 1.2.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 (36) hide show
  1. package/dist/WorldObject.svelte.js +23 -0
  2. package/dist/buffer.d.ts +50 -0
  3. package/dist/buffer.js +69 -0
  4. package/dist/color.d.ts +2 -0
  5. package/dist/color.js +20 -3
  6. package/dist/components/BatchedArrows.svelte +2 -2
  7. package/dist/components/BatchedGeometry.svelte +0 -0
  8. package/dist/components/BatchedGeometry.svelte.d.ts +26 -0
  9. package/dist/components/Entities.svelte +52 -37
  10. package/dist/components/FileDrop/FileDrop.svelte +18 -38
  11. package/dist/components/Frame.svelte +29 -12
  12. package/dist/components/GLTF.svelte +76 -15
  13. package/dist/components/GLTF.svelte.d.ts +1 -1
  14. package/dist/components/Geometry2.svelte +95 -94
  15. package/dist/components/Geometry2.svelte.d.ts +2 -1
  16. package/dist/components/Line.svelte +27 -28
  17. package/dist/components/LineDots.svelte +45 -0
  18. package/dist/components/LineDots.svelte.d.ts +9 -0
  19. package/dist/components/{Pointcloud.svelte → Points.svelte} +41 -6
  20. package/dist/components/Points.svelte.d.ts +10 -0
  21. package/dist/components/Scene.svelte +0 -1
  22. package/dist/components/Snapshot.svelte +60 -0
  23. package/dist/components/Snapshot.svelte.d.ts +21 -0
  24. package/dist/ecs/traits.d.ts +30 -12
  25. package/dist/ecs/traits.js +22 -13
  26. package/dist/hooks/useDrawAPI.svelte.js +23 -11
  27. package/dist/hooks/usePointclouds.svelte.js +2 -2
  28. package/dist/hooks/useSettings.svelte.d.ts +1 -1
  29. package/dist/hooks/useSettings.svelte.js +3 -0
  30. package/dist/hooks/useWorldState.svelte.js +9 -2
  31. package/dist/lib.d.ts +2 -1
  32. package/dist/lib.js +3 -2
  33. package/dist/snapshot.d.ts +7 -0
  34. package/dist/snapshot.js +255 -0
  35. package/package.json +1 -1
  36. package/dist/components/Pointcloud.svelte.d.ts +0 -9
@@ -1,9 +1,8 @@
1
1
  import { trait } from 'koota';
2
- import { MathUtils, BufferGeometry as ThreeBufferGeometry } from 'three';
2
+ import { BufferGeometry as ThreeBufferGeometry } from 'three';
3
3
  import { Geometry as ViamGeometry } from '@viamrobotics/sdk';
4
4
  import { createBox, createCapsule, createSphere } from '../geometry';
5
5
  import { parsePlyInput } from '../ply';
6
- export const UUID = trait(() => MathUtils.generateUUID());
7
6
  export const Name = trait(() => '');
8
7
  export const Parent = trait(() => 'world');
9
8
  export const Pose = trait({ x: 0, y: 0, z: 0, oX: 0, oY: 0, oZ: 1, theta: 0 });
@@ -18,7 +17,7 @@ export const Opacity = trait(() => 1);
18
17
  * The color of an object
19
18
  * @default { r: 1, g: 0, b: 0 }
20
19
  */
21
- export const Color = trait({ r: 1, g: 0, b: 0 });
20
+ export const Color = trait({ r: 0, g: 0, b: 0 });
22
21
  export const Arrow = trait();
23
22
  /**
24
23
  * A box, in mm
@@ -32,26 +31,36 @@ export const Capsule = trait({ l: 200, r: 50 });
32
31
  * A sphere, in mm
33
32
  */
34
33
  export const Sphere = trait({ r: 200 });
35
- /**
36
- *
37
- */
38
- export const DottedLineColor = trait({ r: 0, g: 0, b: 0 });
39
- export const LineGeometry = trait(() => []);
40
- export const PointsGeometry = trait(() => new Float32Array());
34
+ export const PointColor = trait({ r: 0, g: 0, b: 0 });
35
+ /** format [x, y, z, ...] */
36
+ export const LinePositions = trait(() => new Float32Array());
37
+ export const PointsPositions = trait(() => new Float32Array());
41
38
  export const BufferGeometry = trait(() => new ThreeBufferGeometry());
39
+ /** format [r, g, b, ...] */
42
40
  export const VertexColors = trait(() => new Float32Array());
43
- export const GLTF = trait(() => ({}));
44
- export const DrawAPI = trait();
41
+ export const GLTF = trait(() => ({
42
+ source: { url: '' },
43
+ animationName: '',
44
+ }));
45
+ export const Scale = trait({ x: 1, y: 1, z: 1 });
46
+ export const FramesAPI = trait();
45
47
  export const GeometriesAPI = trait();
48
+ export const DrawAPI = trait();
46
49
  export const WorldStateStoreAPI = trait();
50
+ export const SnapshotAPI = trait();
47
51
  /**
48
52
  * Marker trait for entities created from user-dropped files (PLY, PCD, etc.)
49
53
  */
50
54
  export const DroppedFile = trait();
55
+ // === Shape Properties ===
51
56
  /**
52
- * An entity with data from the FrameSystemConfig() API
57
+ * Point size, in mm
53
58
  */
54
- export const FramesAPI = trait();
59
+ export const PointSize = trait(() => 10);
60
+ /**
61
+ * Line width, in mm
62
+ */
63
+ export const LineWidth = trait(() => 5);
55
64
  export const ReferenceFrame = trait();
56
65
  export const Geometry = (geometry) => {
57
66
  if (geometry.geometryType.case === 'box') {
@@ -128,7 +128,7 @@ export const provideDrawAPI = () => {
128
128
  };
129
129
  const drawPCD = async (buffer) => {
130
130
  const { positions, colors } = await parsePcdInWorker(new Uint8Array(buffer));
131
- const entity = world.spawn(traits.Name(`Points ${++pointsIndex}`), traits.PointsGeometry(positions), traits.DrawAPI);
131
+ const entity = world.spawn(traits.Name(`Points ${++pointsIndex}`), traits.PointsPositions(positions), traits.DrawAPI);
132
132
  if (colors) {
133
133
  entity.add(traits.VertexColors(colors));
134
134
  }
@@ -172,12 +172,20 @@ export const provideDrawAPI = () => {
172
172
  const existing = entities.get(name);
173
173
  const controlPoints = data.ControlPts.map((point) => new Vector4(point.x / 1000, point.y / 1000, point.z / 1000));
174
174
  const curve = new NURBSCurve(data.Degree, data.Knots, controlPoints);
175
- const points = curve.getPoints(200);
175
+ const numPoints = 600;
176
+ const points = new Float32Array(numPoints * 3);
177
+ const l = numPoints * 3;
178
+ for (let i = 0; i < l; i += 3) {
179
+ curve.getPointAt(i / (l - 1), vec3);
180
+ points[i + 0] = vec3.x;
181
+ points[i + 1] = vec3.y;
182
+ points[i + 2] = vec3.z;
183
+ }
176
184
  if (existing) {
177
- existing.set(traits.LineGeometry, points);
185
+ existing.set(traits.LinePositions, points);
178
186
  return;
179
187
  }
180
- const entity = world.spawn(traits.Name(name), traits.Color(colorUtil.set(color)), traits.LineGeometry(points), traits.DrawAPI);
188
+ const entity = world.spawn(traits.Name(name), traits.Color(colorUtil.set(color)), traits.LinePositions(points), traits.DrawAPI);
181
189
  entities.set(name, entity);
182
190
  };
183
191
  const vec3 = new Vector3();
@@ -189,11 +197,11 @@ export const provideDrawAPI = () => {
189
197
  const arrowHeadAtPose = reader.read();
190
198
  const entities = [];
191
199
  for (let i = 0; i < nPoints; i += 1) {
192
- origin.set(reader.read(), reader.read(), reader.read()).multiplyScalar(0.001);
200
+ origin.set(reader.read(), reader.read(), reader.read());
193
201
  direction.set(reader.read(), reader.read(), reader.read());
194
202
  if (arrowHeadAtPose === 1) {
195
203
  // Compute the base position so the arrow ends at the origin
196
- origin.sub(vec3.copy(direction).multiplyScalar(/** arrow length */ 0.1));
204
+ origin.sub(vec3.copy(direction).multiplyScalar(/** arrow length */ 100));
197
205
  }
198
206
  pose.x = origin.x;
199
207
  pose.y = origin.y;
@@ -242,7 +250,7 @@ export const provideDrawAPI = () => {
242
250
  colors[offset + 1] = g;
243
251
  colors[offset + 2] = b;
244
252
  }
245
- world.spawn(traits.Name(label), traits.Color(colorUtil.set(r, g, b)), traits.PointsGeometry(positions), traits.VertexColors(colors), traits.DrawAPI);
253
+ world.spawn(traits.Name(label), traits.Color(colorUtil.set(r, g, b)), traits.PointsPositions(positions), traits.VertexColors(colors), traits.DrawAPI);
246
254
  };
247
255
  const drawLine = async (reader) => {
248
256
  // Read label length
@@ -264,11 +272,13 @@ export const provideDrawAPI = () => {
264
272
  const dotG = reader.read();
265
273
  const dotB = reader.read();
266
274
  // Read positions
267
- const points = [];
275
+ const points = new Float32Array(nPoints * 3);
268
276
  for (let i = 0; i < nPoints * 3; i += 3) {
269
- points.push(new Vector3(reader.read(), reader.read(), reader.read()));
277
+ points[i + 0] = reader.read();
278
+ points[i + 1] = reader.read();
279
+ points[i + 2] = reader.read();
270
280
  }
271
- world.spawn(traits.Name(label), traits.Color({ r, g, b }), traits.LineGeometry(points), traits.DottedLineColor({ r: dotR, g: dotG, b: dotB }), traits.DrawAPI);
281
+ world.spawn(traits.Name(label), traits.Color({ r, g, b }), traits.LinePositions(points), traits.PointColor({ r: dotR, g: dotG, b: dotB }), traits.DrawAPI);
272
282
  };
273
283
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
274
284
  const drawGeometries = (geometries, colors, parent) => {
@@ -282,7 +292,7 @@ export const provideDrawAPI = () => {
282
292
  const blob = new Blob([buffer], { type: 'model/gltf-binary' });
283
293
  const url = URL.createObjectURL(blob);
284
294
  const gltf = await loader.loadAsync(url);
285
- world.spawn(traits.Name(gltf.scene.name), traits.GLTF(gltf), traits.DrawAPI);
295
+ world.spawn(traits.Name(gltf.scene.name), traits.GLTF({ source: { gltf }, animationName: '' }), traits.DrawAPI);
286
296
  URL.revokeObjectURL(url);
287
297
  };
288
298
  const remove = (names) => {
@@ -290,6 +300,7 @@ export const provideDrawAPI = () => {
290
300
  for (const entity of world.query(traits.DrawAPI)) {
291
301
  if (entity.get(traits.Name) === name) {
292
302
  entity.destroy();
303
+ entities.delete(name);
293
304
  }
294
305
  }
295
306
  }
@@ -298,6 +309,7 @@ export const provideDrawAPI = () => {
298
309
  for (const entity of world.query(traits.DrawAPI)) {
299
310
  entity.destroy();
300
311
  }
312
+ entities.clear();
301
313
  pointsIndex = 0;
302
314
  geometryIndex = 0;
303
315
  poseIndex = 0;
@@ -101,13 +101,13 @@ export const providePointclouds = (partID) => {
101
101
  for (const { name, positions, colors } of pcObjects) {
102
102
  const existing = entities.get(name);
103
103
  if (existing) {
104
- existing.set(traits.PointsGeometry, positions);
104
+ existing.set(traits.PointsPositions, positions);
105
105
  if (colors) {
106
106
  existing.set(traits.VertexColors, colors);
107
107
  }
108
108
  continue;
109
109
  }
110
- const entity = world.spawn(traits.Parent(name), traits.Name(`${name} pointcloud`), traits.PointsGeometry(positions), colors ? traits.VertexColors(colors) : traits.Color);
110
+ const entity = world.spawn(traits.Parent(name), traits.Name(`${name} pointcloud`), traits.PointsPositions(positions), colors ? traits.VertexColors(colors) : traits.Color);
111
111
  entities.set(name, entity);
112
112
  }
113
113
  // Clean up old entities
@@ -1,4 +1,4 @@
1
- interface Settings {
1
+ export interface Settings {
2
2
  isLoaded: boolean;
3
3
  cameraMode: 'orthographic' | 'perspective';
4
4
  transforming: boolean;
@@ -43,6 +43,9 @@ export const provideSettings = () => {
43
43
  get current() {
44
44
  return settings;
45
45
  },
46
+ set current(value) {
47
+ settings = value;
48
+ },
46
49
  };
47
50
  setContext(key, context);
48
51
  return context;
@@ -48,10 +48,17 @@ const createWorldState = (client) => {
48
48
  entityTraits.push(traits.Geometry(transform.physicalObject));
49
49
  }
50
50
  if (metadata.shape === 'line' && metadata.points) {
51
- entityTraits.push(traits.LineGeometry(metadata.points), traits.DottedLineColor(metadata.lineDotColor));
51
+ const { points } = metadata;
52
+ const positions = new Float32Array(points.length * 3);
53
+ for (let i = 0, j = 0, l = points.length * 3; i < l; i += 3, j += 1) {
54
+ positions[i + 0] = points[j].x;
55
+ positions[i + 1] = points[j].y;
56
+ positions[i + 2] = points[j].z;
57
+ }
58
+ entityTraits.push(traits.LinePositions(positions), traits.PointColor(metadata.lineDotColor));
52
59
  }
53
60
  if (metadata.gltf) {
54
- entityTraits.push(traits.GLTF(metadata.gltf));
61
+ entityTraits.push(traits.GLTF({ source: { gltf: metadata.gltf }, animationName: '' }));
55
62
  }
56
63
  if (metadata.shape === 'arrow') {
57
64
  entityTraits.push(traits.Arrow);
package/dist/lib.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { default as Geometry } from './components/Geometry.svelte';
2
2
  export { default as AxesHelper } from './components/AxesHelper.svelte';
3
- export { Snapshot } from './draw/v1/snapshot_pb';
3
+ export { default as Snapshot } from './components/Snapshot.svelte';
4
+ export { Snapshot as SnapshotProto } from './draw/v1/snapshot_pb';
4
5
  export { BatchedArrow } from './three/BatchedArrow';
5
6
  export { CapsuleGeometry } from './three/CapsuleGeometry';
6
7
  export { OrientationVector } from './three/OrientationVector';
package/dist/lib.js CHANGED
@@ -3,8 +3,9 @@
3
3
  // ensure you write a corresponding unit test to assert the component works in absence of parent providers in /src/lib/__tests__/PureComponents.svelte.spec.ts
4
4
  export { default as Geometry } from './components/Geometry.svelte';
5
5
  export { default as AxesHelper } from './components/AxesHelper.svelte';
6
- // Draw
7
- export { Snapshot } from './draw/v1/snapshot_pb';
6
+ // Snapshot component (uses context, requires MotionTools parent)
7
+ export { default as Snapshot } from './components/Snapshot.svelte';
8
+ export { Snapshot as SnapshotProto } from './draw/v1/snapshot_pb';
8
9
  // Classes
9
10
  export { BatchedArrow } from './three/BatchedArrow';
10
11
  export { CapsuleGeometry } from './three/CapsuleGeometry';
@@ -0,0 +1,7 @@
1
+ import type { World, Entity } from 'koota';
2
+ import type { Snapshot } from './draw/v1/snapshot_pb';
3
+ import { type SceneMetadata } from './draw/v1/scene_pb';
4
+ import type { Settings } from './hooks/useSettings.svelte';
5
+ export declare const applySceneMetadata: (settings: Settings, metadata: SceneMetadata) => Settings;
6
+ export declare const spawnSnapshotEntities: (world: World, snapshot: Snapshot) => Entity[];
7
+ export declare const destroyEntities: (entities: Entity[]) => void;
@@ -0,0 +1,255 @@
1
+ import { Color, Vector3, Vector4 } from 'three';
2
+ import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
3
+ import { RenderArmModels } from './draw/v1/scene_pb';
4
+ import {} from './draw/v1/drawing_pb';
5
+ import { traits } from './ecs';
6
+ import { Geometry } from '@viamrobotics/sdk';
7
+ import { parseMetadata } from './WorldObject.svelte';
8
+ import { rgbaBytesToFloat32, rgbaToHex } from './color';
9
+ import { asFloat32Array, STRIDE } from './buffer';
10
+ import { createPose } from './transform';
11
+ const vec3 = new Vector3();
12
+ const origin = new Vector3();
13
+ const direction = new Vector3();
14
+ const color = new Color();
15
+ const pose = createPose();
16
+ export const applySceneMetadata = (settings, metadata) => {
17
+ const next = { ...settings };
18
+ if (metadata.grid !== undefined) {
19
+ next.grid = metadata.grid;
20
+ }
21
+ if (metadata.gridCellSize !== undefined) {
22
+ next.gridCellSize = metadata.gridCellSize / 1000;
23
+ }
24
+ if (metadata.gridSectionSize !== undefined) {
25
+ next.gridSectionSize = metadata.gridSectionSize / 1000;
26
+ }
27
+ if (metadata.gridFadeDistance !== undefined) {
28
+ next.gridFadeDistance = metadata.gridFadeDistance / 1000;
29
+ }
30
+ if (metadata.pointSize !== undefined) {
31
+ next.pointSize = metadata.pointSize / 1000;
32
+ }
33
+ if (metadata.pointColor !== undefined) {
34
+ next.pointColor = rgbaToHex(metadata.pointColor);
35
+ }
36
+ if (metadata.lineWidth !== undefined) {
37
+ next.lineWidth = metadata.lineWidth / 1000;
38
+ }
39
+ if (metadata.linePointSize !== undefined) {
40
+ next.lineDotSize = metadata.linePointSize / 1000;
41
+ }
42
+ if (metadata.renderArmModels !== undefined) {
43
+ next.renderArmModels = getRenderArmModels(metadata.renderArmModels);
44
+ }
45
+ if (metadata.sceneCamera?.cameraType.case === 'orthographicCamera') {
46
+ next.cameraMode = 'orthographic';
47
+ }
48
+ else if (metadata.sceneCamera?.cameraType.case === 'perspectiveCamera') {
49
+ next.cameraMode = 'perspective';
50
+ }
51
+ return next;
52
+ };
53
+ export const spawnSnapshotEntities = (world, snapshot) => {
54
+ const entities = [];
55
+ for (const transform of snapshot.transforms) {
56
+ entities.push(spawnTransformEntity(world, transform));
57
+ }
58
+ for (const drawing of snapshot.drawings) {
59
+ entities.push(...spawnEntitiesFromDrawing(world, drawing));
60
+ }
61
+ return entities;
62
+ };
63
+ export const destroyEntities = (entities) => {
64
+ for (const entity of entities) {
65
+ entity.destroy();
66
+ }
67
+ };
68
+ const getRenderArmModels = (renderArmModels) => {
69
+ switch (renderArmModels) {
70
+ case RenderArmModels.COLLIDERS:
71
+ return 'colliders';
72
+ case RenderArmModels.UNSPECIFIED:
73
+ case RenderArmModels.COLLIDERS_AND_MODEL:
74
+ return 'colliders+model';
75
+ case RenderArmModels.MODEL:
76
+ return 'model';
77
+ }
78
+ };
79
+ const spawnTransformEntity = (world, transform) => {
80
+ const entityTraits = [
81
+ traits.Name(transform.referenceFrame),
82
+ traits.Geometry(transform.physicalObject ?? Geometry.fromJson({})),
83
+ traits.Center(transform.physicalObject?.center),
84
+ traits.SnapshotAPI,
85
+ ];
86
+ const poseInFrame = transform.poseInObserverFrame;
87
+ entityTraits.push(traits.Pose(poseInFrame?.pose));
88
+ entityTraits.push(traits.Parent(poseInFrame?.referenceFrame));
89
+ if (transform.metadata) {
90
+ const metadata = parseMetadata(transform.metadata.fields);
91
+ if (metadata.color) {
92
+ entityTraits.push(traits.Color(metadata.color));
93
+ }
94
+ if (metadata.opacity !== undefined) {
95
+ entityTraits.push(traits.Opacity(metadata.opacity));
96
+ }
97
+ }
98
+ return world.spawn(...entityTraits);
99
+ };
100
+ const spawnEntitiesFromDrawing = (world, drawing) => {
101
+ const entities = [];
102
+ const poseInFrame = drawing.poseInObserverFrame;
103
+ const parent = poseInFrame?.referenceFrame;
104
+ const { geometryType } = drawing.physicalObject ?? {};
105
+ if (geometryType?.case === 'arrows') {
106
+ const rootEntityTraits = [
107
+ traits.Name(drawing.referenceFrame),
108
+ traits.Pose(poseInFrame?.pose),
109
+ traits.ReferenceFrame,
110
+ ];
111
+ if (parent) {
112
+ rootEntityTraits.push(traits.Parent(parent));
113
+ }
114
+ const rootEntity = world.spawn(...rootEntityTraits, traits.SnapshotAPI);
115
+ entities.push(rootEntity);
116
+ const poses = asFloat32Array(geometryType.value.poses);
117
+ const colors = drawing.metadata?.colors
118
+ ? asFloat32Array(drawing.metadata.colors)
119
+ : [];
120
+ for (let i = 0, j = 0, k = 0, l = poses.length; i < l; i += STRIDE.ARROWS, j += 1, k += 4) {
121
+ const entityTraits = [
122
+ traits.Name(`pose ${j}`),
123
+ traits.Parent(drawing.referenceFrame),
124
+ ];
125
+ origin.set(poses[i + 0], poses[i + 1], poses[i + 2]);
126
+ direction.set(poses[i + 3], poses[i + 4], poses[i + 5]);
127
+ // Compute the base position so the arrow ends at the origin
128
+ origin.sub(vec3.copy(direction).multiplyScalar(/** arrow length */ 100));
129
+ pose.x = origin.x;
130
+ pose.y = origin.y;
131
+ pose.z = origin.z;
132
+ pose.oX = direction.x;
133
+ pose.oY = direction.y;
134
+ pose.oZ = direction.z;
135
+ entityTraits.push(traits.Pose(pose));
136
+ if (colors[k + 0] && colors[k + 1] && colors[k + 2]) {
137
+ color.r = colors[k + 0];
138
+ color.g = colors[k + 1];
139
+ color.b = colors[k + 2];
140
+ entityTraits.push(traits.Color(color));
141
+ }
142
+ if (colors[k + 3]) {
143
+ entityTraits.push(traits.Opacity(colors[k + 3]));
144
+ }
145
+ const entity = world.spawn(...entityTraits, traits.Arrow, traits.SnapshotAPI);
146
+ entities.push(entity);
147
+ }
148
+ }
149
+ else if (geometryType?.case === 'model') {
150
+ const rootEntityTraits = [
151
+ traits.Name(drawing.referenceFrame),
152
+ traits.Pose(poseInFrame?.pose),
153
+ traits.ReferenceFrame,
154
+ ];
155
+ if (parent) {
156
+ rootEntityTraits.push(traits.Parent(parent));
157
+ }
158
+ const rootEntity = world.spawn(...rootEntityTraits, traits.SnapshotAPI);
159
+ entities.push(rootEntity);
160
+ let i = 1;
161
+ for (const asset of geometryType.value.assets) {
162
+ const entityTraits = [
163
+ traits.Name(`${drawing.referenceFrame} model ${i++}`),
164
+ traits.Parent(drawing.referenceFrame),
165
+ ];
166
+ if (geometryType.value.scale) {
167
+ entityTraits.push(traits.Scale(geometryType.value.scale));
168
+ }
169
+ if (asset.content.case === 'url') {
170
+ entityTraits.push(traits.GLTF({
171
+ source: { url: asset.content.value },
172
+ animationName: geometryType.value.animationName ?? '',
173
+ }));
174
+ }
175
+ else if (asset.content.value) {
176
+ entityTraits.push(traits.GLTF({
177
+ source: { glb: asset.content.value },
178
+ animationName: geometryType.value.animationName ?? '',
179
+ }));
180
+ }
181
+ const entity = world.spawn(...entityTraits, traits.SnapshotAPI);
182
+ entities.push(entity);
183
+ }
184
+ }
185
+ else {
186
+ const entityTraits = [
187
+ traits.Name(drawing.referenceFrame),
188
+ traits.Pose(poseInFrame?.pose),
189
+ ];
190
+ if (parent && parent !== 'world') {
191
+ entityTraits.push(traits.Parent);
192
+ }
193
+ if (drawing.metadata?.colors) {
194
+ const colors = rgbaBytesToFloat32(drawing.metadata.colors);
195
+ if (colors.length === 4) {
196
+ entityTraits.push(traits.Color({ r: colors[0], g: colors[1], b: colors[2] }), traits.Opacity(colors[3]));
197
+ }
198
+ else {
199
+ entityTraits.push(traits.VertexColors(colors));
200
+ }
201
+ }
202
+ if (drawing.physicalObject?.center) {
203
+ entityTraits.push(traits.Center(drawing.physicalObject.center));
204
+ }
205
+ if (geometryType?.case === 'line') {
206
+ const positions = asFloat32Array(geometryType.value.positions);
207
+ for (let i = 0, l = positions.length; i < l; i += 1) {
208
+ positions[i] *= 0.001;
209
+ }
210
+ entityTraits.push(traits.LinePositions(positions), traits.LineWidth(geometryType.value.lineWidth), traits.PointSize(geometryType.value.pointSize));
211
+ if (geometryType.value.pointSize) {
212
+ entityTraits.push(traits.PointSize(geometryType.value.pointSize * 0.001));
213
+ }
214
+ }
215
+ else if (geometryType?.case === 'points') {
216
+ const positions = asFloat32Array(geometryType.value.positions);
217
+ for (let i = 0, l = positions.length; i < l; i += 1) {
218
+ positions[i] *= 0.001;
219
+ }
220
+ entityTraits.push(traits.PointsPositions(positions));
221
+ if (geometryType.value.pointSize) {
222
+ entityTraits.push(traits.PointSize(geometryType.value.pointSize * 0.001));
223
+ }
224
+ }
225
+ else if (geometryType?.case === 'nurbs') {
226
+ const { degree = 3, knots: knotsBuffer, weights: weightsBuffer, controlPoints: controlPointsBuffer, } = geometryType.value;
227
+ const knots = [...asFloat32Array(knotsBuffer)];
228
+ const weights = weightsBuffer
229
+ ? [...asFloat32Array(weightsBuffer)]
230
+ : [];
231
+ const controlPointsArray = [...asFloat32Array(controlPointsBuffer)];
232
+ const controlPoints = [];
233
+ for (let i = 0, j = 0, l = controlPointsArray.length / STRIDE.NURBS_CONTROL_POINTS; i < l; i += STRIDE.NURBS_CONTROL_POINTS, j += 1) {
234
+ vec3
235
+ .set(controlPointsArray[0], controlPointsArray[1], controlPointsArray[2])
236
+ .multiplyScalar(0.001);
237
+ controlPoints.push(new Vector4(vec3.x, vec3.y, vec3.z, weights[j] ?? 0));
238
+ }
239
+ const curve = new NURBSCurve(degree, knots, controlPoints);
240
+ const numPoints = 600;
241
+ const points = new Float32Array(numPoints * 3);
242
+ const l = numPoints * 3;
243
+ for (let i = 0; i < l; i += 3) {
244
+ curve.getPointAt(i / (l - 1), vec3);
245
+ points[i + 0] = vec3.x;
246
+ points[i + 1] = vec3.y;
247
+ points[i + 2] = vec3.z;
248
+ }
249
+ entityTraits.push(traits.LinePositions(points));
250
+ }
251
+ const entity = world.spawn(...entityTraits, traits.SnapshotAPI);
252
+ entities.push(entity);
253
+ }
254
+ return entities;
255
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viamrobotics/motion-tools",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "Motion visualization with Viam",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,9 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { Entity } from 'koota';
3
- interface Props {
4
- entity: Entity;
5
- children?: Snippet;
6
- }
7
- declare const Pointcloud: import("svelte").Component<Props, {}, "">;
8
- type Pointcloud = ReturnType<typeof Pointcloud>;
9
- export default Pointcloud;