@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.
- package/dist/WorldObject.svelte.js +23 -0
- package/dist/buffer.d.ts +50 -0
- package/dist/buffer.js +69 -0
- package/dist/color.d.ts +2 -0
- package/dist/color.js +20 -3
- package/dist/components/BatchedArrows.svelte +2 -2
- package/dist/components/BatchedGeometry.svelte +0 -0
- package/dist/components/BatchedGeometry.svelte.d.ts +26 -0
- package/dist/components/Entities.svelte +52 -37
- package/dist/components/FileDrop/FileDrop.svelte +18 -38
- package/dist/components/Frame.svelte +29 -12
- package/dist/components/GLTF.svelte +76 -15
- package/dist/components/GLTF.svelte.d.ts +1 -1
- package/dist/components/Geometry2.svelte +95 -94
- package/dist/components/Geometry2.svelte.d.ts +2 -1
- package/dist/components/Line.svelte +27 -28
- package/dist/components/LineDots.svelte +45 -0
- package/dist/components/LineDots.svelte.d.ts +9 -0
- package/dist/components/{Pointcloud.svelte → Points.svelte} +41 -6
- package/dist/components/Points.svelte.d.ts +10 -0
- package/dist/components/Scene.svelte +0 -1
- package/dist/components/Snapshot.svelte +60 -0
- package/dist/components/Snapshot.svelte.d.ts +21 -0
- package/dist/ecs/traits.d.ts +30 -12
- package/dist/ecs/traits.js +22 -13
- package/dist/hooks/useDrawAPI.svelte.js +23 -11
- package/dist/hooks/usePointclouds.svelte.js +2 -2
- package/dist/hooks/useSettings.svelte.d.ts +1 -1
- package/dist/hooks/useSettings.svelte.js +3 -0
- package/dist/hooks/useWorldState.svelte.js +9 -2
- package/dist/lib.d.ts +2 -1
- package/dist/lib.js +3 -2
- package/dist/snapshot.d.ts +7 -0
- package/dist/snapshot.js +255 -0
- package/package.json +1 -1
- package/dist/components/Pointcloud.svelte.d.ts +0 -9
package/dist/ecs/traits.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { trait } from 'koota';
|
|
2
|
-
import {
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
57
|
+
* Point size, in mm
|
|
53
58
|
*/
|
|
54
|
-
export const
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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())
|
|
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 */
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
@@ -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
|
-
|
|
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 './
|
|
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
|
-
//
|
|
7
|
-
export { Snapshot } from './
|
|
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;
|
package/dist/snapshot.js
ADDED
|
@@ -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,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;
|