@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.
- package/dist/attribute.d.ts +3 -2
- package/dist/attribute.js +24 -16
- package/dist/buf/draw/v1/drawing_pb.d.ts +33 -16
- package/dist/buf/draw/v1/drawing_pb.js +35 -17
- package/dist/buf/draw/v1/metadata_pb.d.ts +44 -3
- package/dist/buf/draw/v1/metadata_pb.js +54 -3
- package/dist/buf/draw/v1/scene_pb.d.ts +6 -6
- package/dist/buf/draw/v1/scene_pb.js +7 -7
- package/dist/buffer.d.ts +54 -45
- package/dist/buffer.js +91 -57
- package/dist/color.d.ts +1 -2
- package/dist/color.js +5 -12
- package/dist/components/App.svelte +18 -3
- package/dist/components/App.svelte.d.ts +15 -2
- package/dist/components/Entities/Arrows/ArrowGroups.svelte +5 -6
- package/dist/components/Entities/Arrows/Arrows.svelte +9 -0
- package/dist/components/Entities/Entities.svelte +18 -1
- package/dist/components/Entities/Frame.svelte +7 -1
- package/dist/components/Entities/GLTF.svelte +13 -2
- package/dist/components/Entities/Line.svelte +46 -18
- package/dist/components/Entities/LineDots.svelte +38 -8
- package/dist/components/Entities/LineDots.svelte.d.ts +2 -2
- package/dist/components/Entities/LineGeometry.svelte +2 -1
- package/dist/components/Entities/LineGeometry.svelte.d.ts +2 -0
- package/dist/components/Entities/Mesh.svelte +8 -1
- package/dist/components/Entities/Points.svelte +22 -11
- package/dist/components/Entities/hooks/useEntityEvents.svelte.js +6 -2
- package/dist/components/FileDrop/FileDrop.svelte +5 -1
- package/dist/components/KeyboardControls.svelte +2 -10
- package/dist/components/PCD.svelte +11 -4
- package/dist/components/PCD.svelte.d.ts +3 -1
- package/dist/components/SceneProviders.svelte +2 -0
- package/dist/components/Selected.svelte +2 -12
- package/dist/components/{Lasso → Selection}/Debug.svelte +8 -8
- package/dist/components/{Lasso → Selection}/Debug.svelte.d.ts +2 -2
- package/dist/components/Selection/Ellipse.svelte +294 -0
- package/dist/components/Selection/Ellipse.svelte.d.ts +7 -0
- package/dist/components/{Lasso → Selection}/Lasso.svelte +33 -61
- package/dist/components/{Lasso → Selection}/Lasso.svelte.d.ts +1 -0
- package/dist/components/Selection/Tool.svelte +94 -0
- package/dist/components/{Lasso → Selection}/Tool.svelte.d.ts +2 -2
- package/dist/components/{Lasso → Selection}/traits.d.ts +11 -2
- package/dist/components/{Lasso → Selection}/traits.js +7 -2
- package/dist/components/Selection/useSelectionPlugin.svelte.d.ts +8 -0
- package/dist/components/Selection/useSelectionPlugin.svelte.js +24 -0
- package/dist/components/Selection/utils.d.ts +5 -0
- package/dist/components/Selection/utils.js +38 -0
- package/dist/components/Snapshot.svelte +4 -2
- package/dist/components/overlay/AddRelationship.svelte +1 -2
- package/dist/components/overlay/AddRelationship.svelte.d.ts +1 -1
- package/dist/components/overlay/Details.svelte +12 -12
- package/dist/components/overlay/Details.svelte.d.ts +8 -1
- package/dist/components/overlay/settings/Settings.svelte +8 -1
- package/dist/components/xr/OriginMarker.svelte +94 -17
- package/dist/components/xr/XR.svelte +1 -1
- package/dist/draw.d.ts +13 -0
- package/dist/draw.js +428 -0
- package/dist/ecs/traits.d.ts +31 -13
- package/dist/ecs/traits.js +25 -8
- package/dist/geometry.js +3 -0
- package/dist/hooks/useDrawAPI.svelte.js +61 -24
- package/dist/hooks/useDrawService.svelte.d.ts +12 -0
- package/dist/hooks/useDrawService.svelte.js +240 -0
- package/dist/hooks/usePointcloudObjects.svelte.js +7 -2
- package/dist/hooks/usePointclouds.svelte.js +7 -2
- package/dist/hooks/useSettings.svelte.d.ts +3 -2
- package/dist/hooks/useSettings.svelte.js +2 -2
- package/dist/hooks/useWorldState.svelte.js +5 -52
- package/dist/index.d.ts +9 -1
- package/dist/index.js +10 -1
- package/dist/lib.d.ts +2 -0
- package/dist/lib.js +2 -0
- package/dist/loaders/pcd/index.d.ts +1 -1
- package/dist/loaders/pcd/messages.d.ts +2 -2
- package/dist/loaders/pcd/worker.inline.d.ts +1 -1
- package/dist/loaders/pcd/worker.inline.js +229 -187
- package/dist/loaders/pcd/worker.js +2 -2
- package/dist/metadata.d.ts +9 -15
- package/dist/metadata.js +45 -9
- package/dist/plugins/bvh.svelte.js +6 -2
- package/dist/snapshot.d.ts +3 -9
- package/dist/snapshot.js +11 -204
- package/dist/three/InstancedArrows/InstancedArrows.js +3 -2
- package/package.json +14 -11
- package/dist/components/Lasso/Tool.svelte +0 -108
- package/dist/components/xr/Hands.svelte +0 -23
- 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
|
+
};
|
package/dist/ecs/traits.d.ts
CHANGED
|
@@ -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<
|
|
84
|
-
|
|
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
|
|
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
|
|
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
|
*/
|
package/dist/ecs/traits.js
CHANGED
|
@@ -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
|
-
|
|
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(() =>
|
|
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
|
*/
|