@viamrobotics/motion-tools 0.5.3 → 0.5.5
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.d.ts +3 -2
- package/dist/components/App.svelte +1 -1
- package/dist/components/Details.svelte +0 -1
- package/dist/components/Focus.svelte +3 -1
- package/dist/components/KeyboardControls.svelte +11 -1
- package/dist/components/Pointcloud.svelte +13 -10
- package/dist/components/Scene.svelte +2 -0
- package/dist/components/SceneProviders.svelte +0 -1
- package/dist/components/dashboard/Button.svelte +5 -4
- package/dist/hooks/useFrames.svelte.js +3 -3
- package/dist/hooks/useSelection.svelte.d.ts +7 -8
- package/dist/hooks/useShapes.svelte.js +117 -47
- package/dist/three/BatchedArrow.d.ts +2 -2
- package/dist/three/BatchedArrow.js +2 -1
- package/package.json +38 -37
package/dist/WorldObject.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Geometry, Pose } from '@viamrobotics/sdk';
|
|
2
|
-
import { BatchedMesh, Box3, Object3D, Vector3 } from 'three';
|
|
2
|
+
import { BatchedMesh, Box3, Object3D, Vector3, type ColorRepresentation } from 'three';
|
|
3
3
|
export type PointsGeometry = {
|
|
4
4
|
case: 'points';
|
|
5
5
|
value: Float32Array<ArrayBuffer>;
|
|
@@ -11,11 +11,12 @@ export type LinesGeometry = {
|
|
|
11
11
|
export type Geometries = Geometry['geometryType'] | PointsGeometry | LinesGeometry;
|
|
12
12
|
export type Metadata = {
|
|
13
13
|
colors?: Float32Array;
|
|
14
|
-
color?:
|
|
14
|
+
color?: ColorRepresentation;
|
|
15
15
|
gltf?: {
|
|
16
16
|
scene: Object3D;
|
|
17
17
|
};
|
|
18
18
|
points?: Vector3[];
|
|
19
|
+
pointSize?: number;
|
|
19
20
|
batched?: {
|
|
20
21
|
id: number;
|
|
21
22
|
object: BatchedMesh;
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
|
|
22
22
|
const object = $derived(focusedObject.current ?? selectedObject.current)
|
|
23
23
|
const object3d = $derived(focusedObject3d.current ?? selectedObject3d.current)
|
|
24
|
-
|
|
25
24
|
const worldPosition = $derived(object3d?.getWorldPosition(new Vector3()))
|
|
26
25
|
const worldQuaternion = $derived(object3d?.getWorldQuaternion(new Quaternion()))
|
|
27
26
|
const worldOrientation = $derived(
|
|
@@ -12,16 +12,18 @@
|
|
|
12
12
|
const vec = new Vector3()
|
|
13
13
|
|
|
14
14
|
let center = $state.raw<[number, number, number]>([0, 0, 0])
|
|
15
|
+
let size = $state.raw<[number, number, number]>([0, 0, 0])
|
|
15
16
|
|
|
16
17
|
$effect(() => {
|
|
17
18
|
if (object3d) {
|
|
18
19
|
box.setFromObject(object3d)
|
|
20
|
+
size = box.getSize(vec).toArray()
|
|
19
21
|
center = box.getCenter(vec).toArray()
|
|
20
22
|
}
|
|
21
23
|
})
|
|
22
24
|
</script>
|
|
23
25
|
|
|
24
|
-
<Camera position={[
|
|
26
|
+
<Camera position={[size[0], 0, 0]}>
|
|
25
27
|
<TrackballControls target={center}>
|
|
26
28
|
<Gizmo />
|
|
27
29
|
</TrackballControls>
|
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
const s = $derived(keys.has('s'))
|
|
21
21
|
const a = $derived(keys.has('a'))
|
|
22
22
|
const d = $derived(keys.has('d'))
|
|
23
|
+
const r = $derived(keys.has('r'))
|
|
24
|
+
const f = $derived(keys.has('f'))
|
|
23
25
|
const up = $derived(keys.has('arrowup'))
|
|
24
26
|
const left = $derived(keys.has('arrowleft'))
|
|
25
27
|
const down = $derived(keys.has('arrowdown'))
|
|
26
28
|
const right = $derived(keys.has('arrowright'))
|
|
27
|
-
const any = $derived(w || s || a || d || up || left || down || right)
|
|
29
|
+
const any = $derived(w || s || a || d || r || f || up || left || down || right)
|
|
28
30
|
|
|
29
31
|
const { start, stop } = useTask(
|
|
30
32
|
(delta) => {
|
|
@@ -46,6 +48,14 @@
|
|
|
46
48
|
cameraControls.forward(-0.01 * dt, true)
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
if (r) {
|
|
52
|
+
cameraControls.dolly(0.01 * dt, true)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (f) {
|
|
56
|
+
cameraControls.dolly(-0.01 * dt, true)
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
if (left) {
|
|
50
60
|
cameraControls.rotate(-0.1 * MathUtils.DEG2RAD * dt, 0, true)
|
|
51
61
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { Points, BufferAttribute, BufferGeometry, PointsMaterial } from 'three'
|
|
3
|
+
|
|
2
4
|
import { T } from '@threlte/core'
|
|
3
|
-
import { Points, BufferAttribute, BufferGeometry, Color, PointsMaterial } from 'three'
|
|
4
5
|
import type { WorldObject } from '../WorldObject'
|
|
5
6
|
import { useObjectEvents } from '../hooks/useObjectEvents.svelte'
|
|
6
7
|
import { meshBounds } from '@threlte/extras'
|
|
@@ -12,18 +13,15 @@
|
|
|
12
13
|
|
|
13
14
|
let { object }: Props = $props()
|
|
14
15
|
|
|
15
|
-
const points = new Points()
|
|
16
|
-
const geometry = new BufferGeometry()
|
|
17
|
-
const material = new PointsMaterial({
|
|
18
|
-
size: 0.01,
|
|
19
|
-
color: new Color('#888888'),
|
|
20
|
-
})
|
|
21
|
-
|
|
22
16
|
const colors = $derived(object.metadata.colors)
|
|
23
17
|
const positions = $derived(object.geometry?.value ?? new Float32Array())
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
const points = new Points()
|
|
20
|
+
const geometry = new BufferGeometry()
|
|
21
|
+
const material = new PointsMaterial()
|
|
22
|
+
|
|
23
|
+
$effect.pre(() => {
|
|
24
|
+
material.size = object.metadata.pointSize ?? 0.01
|
|
27
25
|
})
|
|
28
26
|
|
|
29
27
|
$effect.pre(() => {
|
|
@@ -31,8 +29,13 @@
|
|
|
31
29
|
})
|
|
32
30
|
|
|
33
31
|
$effect.pre(() => {
|
|
32
|
+
material.vertexColors = colors !== undefined
|
|
33
|
+
material.color.set(colors ? 0xffffff : (object.metadata.color ?? '#888888'))
|
|
34
|
+
|
|
35
|
+
material.toneMapped = false
|
|
34
36
|
if (colors) {
|
|
35
37
|
geometry.setAttribute('color', new BufferAttribute(colors, 3))
|
|
38
|
+
geometry.attributes.color.needsUpdate = true
|
|
36
39
|
}
|
|
37
40
|
})
|
|
38
41
|
|
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
class: className = '',
|
|
19
19
|
onclick,
|
|
20
20
|
}: Props = $props()
|
|
21
|
-
|
|
22
|
-
const activeClasses = 'z-10 border-gray-5 bg-white text-gray-8'
|
|
23
|
-
const inactiveClasses = 'bg-light border-medium text-disabled'
|
|
24
21
|
</script>
|
|
25
22
|
|
|
26
23
|
<Tooltip
|
|
@@ -28,7 +25,11 @@
|
|
|
28
25
|
location="bottom"
|
|
29
26
|
>
|
|
30
27
|
<label
|
|
31
|
-
class={[
|
|
28
|
+
class={[
|
|
29
|
+
className,
|
|
30
|
+
'relative block border',
|
|
31
|
+
active ? 'border-gray-5 text-gray-8 z-10 bg-white' : 'bg-light border-medium text-disabled',
|
|
32
|
+
]}
|
|
32
33
|
aria-describedby={tooltipID}
|
|
33
34
|
>
|
|
34
35
|
<button
|
|
@@ -6,14 +6,14 @@ import { observe } from '@threlte/core';
|
|
|
6
6
|
import { useLogs } from './useLogs.svelte';
|
|
7
7
|
const key = Symbol('frames-context');
|
|
8
8
|
export const provideFrames = (partID) => {
|
|
9
|
+
const client = useRobotClient(partID);
|
|
10
|
+
const machineStatus = useMachineStatus(partID);
|
|
11
|
+
const logs = useLogs();
|
|
9
12
|
const refreshRates = useRefreshRates();
|
|
10
13
|
if (!refreshRates.has('Frames')) {
|
|
11
14
|
refreshRates.set('Frames', 1);
|
|
12
15
|
}
|
|
13
|
-
const logs = useLogs();
|
|
14
|
-
const client = useRobotClient(partID);
|
|
15
16
|
const query = createRobotQuery(client, 'frameSystemConfig');
|
|
16
|
-
const machineStatus = useMachineStatus(partID);
|
|
17
17
|
const revision = $derived(machineStatus.current?.config.revision);
|
|
18
18
|
const shouldFetch = $derived(refreshRates.get('Frames') === 1);
|
|
19
19
|
observe.pre(() => [revision], () => {
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
import { Object3D } from 'three';
|
|
2
2
|
import type { WorldObject } from '../WorldObject';
|
|
3
|
-
type UUID = string;
|
|
4
3
|
interface SelectionContext {
|
|
5
|
-
readonly current:
|
|
6
|
-
set(value?:
|
|
4
|
+
readonly current: string | undefined;
|
|
5
|
+
set(value?: string): void;
|
|
7
6
|
}
|
|
8
7
|
interface FocusContext {
|
|
9
|
-
readonly current:
|
|
10
|
-
set(value?:
|
|
8
|
+
readonly current: string | undefined;
|
|
9
|
+
set(value?: string): void;
|
|
11
10
|
}
|
|
12
11
|
export declare const provideSelection: () => {
|
|
13
12
|
selection: {
|
|
14
13
|
readonly current: string | undefined;
|
|
15
|
-
set(value?:
|
|
14
|
+
set(value?: string): void;
|
|
16
15
|
};
|
|
17
16
|
focus: {
|
|
18
17
|
readonly current: string | undefined;
|
|
19
|
-
set(value?:
|
|
18
|
+
set(value?: string): void;
|
|
20
19
|
};
|
|
21
20
|
hover: {
|
|
22
21
|
readonly current: string | undefined;
|
|
23
|
-
set(value?:
|
|
22
|
+
set(value?: string): void;
|
|
24
23
|
};
|
|
25
24
|
};
|
|
26
25
|
export declare const useSelected: () => SelectionContext;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getContext, setContext } from 'svelte';
|
|
2
|
-
import { Vector3, Vector4 } from 'three';
|
|
2
|
+
import { Color, Vector3, Vector4 } from 'three';
|
|
3
3
|
import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
|
|
4
4
|
import { parsePcdInWorker } from '../loaders/pcd';
|
|
5
5
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
@@ -15,6 +15,22 @@ const tryParse = (json) => {
|
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
+
class Float32Reader {
|
|
19
|
+
littleEndian = true;
|
|
20
|
+
offset = 0;
|
|
21
|
+
buffer = new ArrayBuffer();
|
|
22
|
+
view = new DataView(this.buffer);
|
|
23
|
+
async init(data) {
|
|
24
|
+
this.buffer = await data.arrayBuffer();
|
|
25
|
+
this.view = new DataView(this.buffer);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
read() {
|
|
29
|
+
const result = this.view.getFloat32(this.offset, this.littleEndian);
|
|
30
|
+
this.offset += 4;
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
18
34
|
export const provideShapes = () => {
|
|
19
35
|
let pointsIndex = 0;
|
|
20
36
|
let geometryIndex = 0;
|
|
@@ -28,9 +44,12 @@ export const provideShapes = () => {
|
|
|
28
44
|
const nurbs = $state([]);
|
|
29
45
|
const models = $state([]);
|
|
30
46
|
let connectionStatus = $state('connecting');
|
|
47
|
+
const color = new Color();
|
|
48
|
+
const direction = new Vector3();
|
|
49
|
+
const origin = new Vector3();
|
|
50
|
+
const vec3 = new Vector3();
|
|
31
51
|
const loader = new GLTFLoader();
|
|
32
|
-
const
|
|
33
|
-
const buffer = await data.arrayBuffer();
|
|
52
|
+
const addPCD = async (buffer) => {
|
|
34
53
|
const { positions, colors } = await parsePcdInWorker(new Uint8Array(buffer));
|
|
35
54
|
points.push(new WorldObject(`points ${++pointsIndex}`, undefined, undefined, {
|
|
36
55
|
case: 'points',
|
|
@@ -70,23 +89,33 @@ export const provideShapes = () => {
|
|
|
70
89
|
const object = new WorldObject(data.name, data.pose, data.parent, { case: 'line', value: new Float32Array() }, { color, points: curve.getPoints(200) });
|
|
71
90
|
nurbs.push(object);
|
|
72
91
|
};
|
|
73
|
-
const direction = new Vector3();
|
|
74
|
-
const origin = new Vector3();
|
|
75
|
-
const vec3 = new Vector3();
|
|
76
92
|
const batchedArrow = new BatchedArrow();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
const addPoses = async (reader) => {
|
|
94
|
+
// Read counts
|
|
95
|
+
const nPoints = reader.read();
|
|
96
|
+
const nColors = reader.read();
|
|
97
|
+
const arrowHeadAtPose = reader.read();
|
|
98
|
+
// Read positions
|
|
99
|
+
const nextPoses = new Float32Array(nPoints * 6);
|
|
100
|
+
for (let i = 0; i < nPoints * 6; i++) {
|
|
101
|
+
nextPoses[i] = reader.read();
|
|
102
|
+
}
|
|
103
|
+
// Read raw colors
|
|
104
|
+
const colors = new Float32Array(nColors * 3);
|
|
105
|
+
for (let i = 0; i < nColors * 3; i++) {
|
|
106
|
+
colors[i] = reader.read();
|
|
107
|
+
}
|
|
108
|
+
const length = 0.1;
|
|
109
|
+
for (let i = 0, j = 0, l = nextPoses.length; i < l; i += 6, j += 3) {
|
|
110
|
+
origin.set(nextPoses[i], nextPoses[i + 1], nextPoses[i + 2]).multiplyScalar(0.001);
|
|
111
|
+
direction.set(nextPoses[i + 3], nextPoses[i + 4], nextPoses[i + 5]);
|
|
112
|
+
if (arrowHeadAtPose === 1) {
|
|
85
113
|
// Compute the base position so the arrow ends at the origin
|
|
86
114
|
origin.sub(vec3.copy(direction).multiplyScalar(length));
|
|
87
115
|
}
|
|
88
|
-
|
|
89
|
-
|
|
116
|
+
color.set(colors[j], colors[j + 1], colors[j + 2]);
|
|
117
|
+
const arrowId = batchedArrow.addArrow(direction, origin, length, color);
|
|
118
|
+
poses.push(new WorldObject(`pose ${++poseIndex}`, undefined, undefined, undefined, {
|
|
90
119
|
getBoundingBoxAt(box3) {
|
|
91
120
|
return batchedArrow.getBoundingBoxAt(arrowId, box3);
|
|
92
121
|
},
|
|
@@ -97,6 +126,58 @@ export const provideShapes = () => {
|
|
|
97
126
|
}));
|
|
98
127
|
}
|
|
99
128
|
};
|
|
129
|
+
const addPoints = async (reader) => {
|
|
130
|
+
// Read label length
|
|
131
|
+
const labelLen = reader.read();
|
|
132
|
+
let label = '';
|
|
133
|
+
for (let i = 0; i < labelLen; i++) {
|
|
134
|
+
label += String.fromCharCode(reader.read());
|
|
135
|
+
}
|
|
136
|
+
// Read counts
|
|
137
|
+
const nPoints = reader.read();
|
|
138
|
+
const nColors = reader.read();
|
|
139
|
+
// Read default color
|
|
140
|
+
const r = reader.read();
|
|
141
|
+
const g = reader.read();
|
|
142
|
+
const b = reader.read();
|
|
143
|
+
// Read positions
|
|
144
|
+
const positions = new Float32Array(nPoints * 3);
|
|
145
|
+
for (let i = 0; i < nPoints * 3; i++) {
|
|
146
|
+
positions[i] = reader.read();
|
|
147
|
+
}
|
|
148
|
+
const getColors = () => {
|
|
149
|
+
// Read raw colors
|
|
150
|
+
const rawColors = new Float32Array(nColors * 3);
|
|
151
|
+
for (let i = 0; i < nColors * 3; i++) {
|
|
152
|
+
rawColors[i] = reader.read();
|
|
153
|
+
}
|
|
154
|
+
const colors = new Float32Array(nPoints * 3);
|
|
155
|
+
colors.set(rawColors);
|
|
156
|
+
// Cover the gap for any points not colored
|
|
157
|
+
for (let i = nColors; i < nPoints; i++) {
|
|
158
|
+
const offset = i * 3;
|
|
159
|
+
colors[offset] = r;
|
|
160
|
+
colors[offset + 1] = g;
|
|
161
|
+
colors[offset + 2] = b;
|
|
162
|
+
}
|
|
163
|
+
return colors;
|
|
164
|
+
};
|
|
165
|
+
const pointSize = 0.01;
|
|
166
|
+
const metadata = nColors > 0
|
|
167
|
+
? {
|
|
168
|
+
colors: getColors(),
|
|
169
|
+
color: new Color(r, g, b).convertLinearToSRGB(),
|
|
170
|
+
pointSize,
|
|
171
|
+
}
|
|
172
|
+
: {
|
|
173
|
+
color: new Color(r, g, b).convertLinearToSRGB(),
|
|
174
|
+
pointSize,
|
|
175
|
+
};
|
|
176
|
+
points.push(new WorldObject(label ?? `points ${++pointsIndex}`, undefined, undefined, {
|
|
177
|
+
case: 'points',
|
|
178
|
+
value: positions,
|
|
179
|
+
}, metadata));
|
|
180
|
+
};
|
|
100
181
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
101
182
|
const addGeometries = (geometries, colors, parent) => {
|
|
102
183
|
let i = 0;
|
|
@@ -105,6 +186,13 @@ export const provideShapes = () => {
|
|
|
105
186
|
i += 1;
|
|
106
187
|
}
|
|
107
188
|
};
|
|
189
|
+
const addGLTF = async (buffer) => {
|
|
190
|
+
const blob = new Blob([buffer], { type: 'model/gltf-binary' });
|
|
191
|
+
const url = URL.createObjectURL(blob);
|
|
192
|
+
const gltf = await loader.loadAsync(url);
|
|
193
|
+
models.push(new WorldObject(gltf.scene.name, undefined, undefined, undefined, { gltf }));
|
|
194
|
+
URL.revokeObjectURL(url);
|
|
195
|
+
};
|
|
108
196
|
const remove = (names) => {
|
|
109
197
|
let index = -1;
|
|
110
198
|
for (const name of names) {
|
|
@@ -150,23 +238,6 @@ export const provideShapes = () => {
|
|
|
150
238
|
geometryIndex = 0;
|
|
151
239
|
poseIndex = 0;
|
|
152
240
|
};
|
|
153
|
-
let metadata = undefined;
|
|
154
|
-
const handleMetadata = (data) => {
|
|
155
|
-
const json = tryParse(data);
|
|
156
|
-
if ('ext' in json) {
|
|
157
|
-
metadata = json;
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
return false;
|
|
161
|
-
};
|
|
162
|
-
const loadGLTF = async (data) => {
|
|
163
|
-
const buffer = await data.arrayBuffer();
|
|
164
|
-
const blob = new Blob([buffer], { type: 'model/gltf-binary' });
|
|
165
|
-
const url = URL.createObjectURL(blob);
|
|
166
|
-
const gltf = await loader.loadAsync(url);
|
|
167
|
-
models.push(new WorldObject(gltf.scene.name, undefined, undefined, undefined, { gltf }));
|
|
168
|
-
URL.revokeObjectURL(url);
|
|
169
|
-
};
|
|
170
241
|
const { BACKEND_IP, BUN_SERVER_PORT } = globalThis;
|
|
171
242
|
const scheduleReconnect = () => {
|
|
172
243
|
setTimeout(() => {
|
|
@@ -189,20 +260,22 @@ export const provideShapes = () => {
|
|
|
189
260
|
console.log('Websocket error', JSON.stringify(event));
|
|
190
261
|
ws.close();
|
|
191
262
|
};
|
|
192
|
-
const onMessage = (event) => {
|
|
193
|
-
if (typeof event.data === 'string') {
|
|
194
|
-
if (handleMetadata(event.data)) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
263
|
+
const onMessage = async (event) => {
|
|
198
264
|
if (typeof event.data === 'object' && 'arrayBuffer' in event.data) {
|
|
199
|
-
|
|
200
|
-
|
|
265
|
+
const reader = await new Float32Reader().init(event.data);
|
|
266
|
+
const type = reader.read();
|
|
267
|
+
if (type === 0) {
|
|
268
|
+
return addPoints(reader);
|
|
201
269
|
}
|
|
202
|
-
else if (
|
|
203
|
-
|
|
270
|
+
else if (type === 1) {
|
|
271
|
+
return addPoses(reader);
|
|
272
|
+
}
|
|
273
|
+
else if (type === 2) {
|
|
274
|
+
return addPCD(reader.buffer);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
return addGLTF(reader.buffer);
|
|
204
278
|
}
|
|
205
|
-
return;
|
|
206
279
|
}
|
|
207
280
|
const data = tryParse(event.data);
|
|
208
281
|
if (!data)
|
|
@@ -219,9 +292,6 @@ export const provideShapes = () => {
|
|
|
219
292
|
if ('Knots' in data) {
|
|
220
293
|
return addNurbs(data, data.Color);
|
|
221
294
|
}
|
|
222
|
-
if ('poses' in data) {
|
|
223
|
-
return addPoses(data.poses, data.colors, data.arrowHeadAtPose);
|
|
224
|
-
}
|
|
225
295
|
if ('geometry' in data) {
|
|
226
296
|
addGeometry(data.geometry, data.color);
|
|
227
297
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BatchedMesh, MeshBasicMaterial, Object3D, Vector3, Box3, Matrix4 } from 'three';
|
|
1
|
+
import { BatchedMesh, MeshBasicMaterial, Object3D, Vector3, Box3, Matrix4, type ColorRepresentation } from 'three';
|
|
2
2
|
interface Arrow {
|
|
3
3
|
shaftId: number;
|
|
4
4
|
headId: number;
|
|
@@ -17,7 +17,7 @@ export declare class BatchedArrow {
|
|
|
17
17
|
shaftWidth?: number | undefined;
|
|
18
18
|
material?: MeshBasicMaterial | undefined;
|
|
19
19
|
});
|
|
20
|
-
addArrow(dir: Vector3, origin: Vector3, length?: number, color?:
|
|
20
|
+
addArrow(dir: Vector3, origin: Vector3, length?: number, color?: ColorRepresentation): number;
|
|
21
21
|
getArrowId(instanceId: number): number | undefined;
|
|
22
22
|
getBoundingBoxAt(arrowId: number, target: Box3): Box3 | undefined;
|
|
23
23
|
removeArrow(arrowId: number): void;
|
|
@@ -6,6 +6,7 @@ const box1 = new Box3();
|
|
|
6
6
|
const box2 = new Box3();
|
|
7
7
|
const mat4_1 = new Matrix4();
|
|
8
8
|
const mat4_2 = new Matrix4();
|
|
9
|
+
const col = new Color();
|
|
9
10
|
let index = 0;
|
|
10
11
|
export class BatchedArrow {
|
|
11
12
|
batchedMesh;
|
|
@@ -57,7 +58,7 @@ export class BatchedArrow {
|
|
|
57
58
|
const coneMatrix = this._computeTransform(coneOrigin, dir, headLength, headWidth * 4);
|
|
58
59
|
this.batchedMesh.setMatrixAt(headId, coneMatrix);
|
|
59
60
|
if (color) {
|
|
60
|
-
|
|
61
|
+
col.set(color);
|
|
61
62
|
this.batchedMesh.setColorAt(shaftId, col);
|
|
62
63
|
this.batchedMesh.setColorAt(headId, col);
|
|
63
64
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viamrobotics/motion-tools",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Motion visualization with Viam",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -8,65 +8,66 @@
|
|
|
8
8
|
"@ag-grid-community/client-side-row-model": "32.3.5",
|
|
9
9
|
"@ag-grid-community/core": "32.3.5",
|
|
10
10
|
"@ag-grid-community/styles": "32.3.5",
|
|
11
|
-
"@changesets/cli": "2.29.
|
|
11
|
+
"@changesets/cli": "2.29.5",
|
|
12
12
|
"@dimforge/rapier3d-compat": "0.17.3",
|
|
13
|
-
"@eslint/compat": "1.3.
|
|
14
|
-
"@eslint/js": "9.
|
|
15
|
-
"@playwright/test": "1.53.
|
|
13
|
+
"@eslint/compat": "1.3.1",
|
|
14
|
+
"@eslint/js": "9.30.1",
|
|
15
|
+
"@playwright/test": "1.53.2",
|
|
16
|
+
"@sentry/sveltekit": "9.34.0",
|
|
16
17
|
"@skeletonlabs/skeleton": "3.1.3",
|
|
17
18
|
"@skeletonlabs/skeleton-svelte": "1.2.3",
|
|
18
19
|
"@sveltejs/adapter-static": "3.0.8",
|
|
19
|
-
"@sveltejs/kit": "2.
|
|
20
|
-
"@sveltejs/package": "2.3.
|
|
20
|
+
"@sveltejs/kit": "2.22.2",
|
|
21
|
+
"@sveltejs/package": "2.3.12",
|
|
21
22
|
"@sveltejs/vite-plugin-svelte": "5.1.0",
|
|
22
23
|
"@tailwindcss/forms": "0.5.10",
|
|
23
|
-
"@tailwindcss/vite": "4.1.
|
|
24
|
-
"@tanstack/svelte-query": "5.
|
|
25
|
-
"@tanstack/svelte-query-devtools": "5.
|
|
24
|
+
"@tailwindcss/vite": "4.1.11",
|
|
25
|
+
"@tanstack/svelte-query": "5.81.5",
|
|
26
|
+
"@tanstack/svelte-query-devtools": "5.81.5",
|
|
26
27
|
"@testing-library/jest-dom": "6.6.3",
|
|
27
28
|
"@testing-library/svelte": "5.2.8",
|
|
28
|
-
"@threlte/core": "8.0.
|
|
29
|
+
"@threlte/core": "8.0.5",
|
|
29
30
|
"@threlte/extras": "9.4.0",
|
|
30
31
|
"@threlte/rapier": "3.1.4",
|
|
31
|
-
"@threlte/xr": "1.0.
|
|
32
|
-
"@types/bun": "1.2.
|
|
32
|
+
"@threlte/xr": "1.0.8",
|
|
33
|
+
"@types/bun": "1.2.17",
|
|
33
34
|
"@types/lodash-es": "4.17.12",
|
|
34
|
-
"@types/three": "0.
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
36
|
-
"@typescript-eslint/parser": "8.
|
|
35
|
+
"@types/three": "0.178.0",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "8.35.1",
|
|
37
|
+
"@typescript-eslint/parser": "8.35.1",
|
|
37
38
|
"@viamrobotics/prime-core": "0.1.5",
|
|
38
|
-
"@viamrobotics/sdk": "0.
|
|
39
|
-
"@viamrobotics/svelte-sdk": "0.
|
|
40
|
-
"@vitejs/plugin-basic-ssl": "2.
|
|
41
|
-
"@zag-js/svelte": "1.
|
|
42
|
-
"@zag-js/tree-view": "1.
|
|
39
|
+
"@viamrobotics/sdk": "0.45.0",
|
|
40
|
+
"@viamrobotics/svelte-sdk": "0.4.1",
|
|
41
|
+
"@vitejs/plugin-basic-ssl": "2.1.0",
|
|
42
|
+
"@zag-js/svelte": "1.18.1",
|
|
43
|
+
"@zag-js/tree-view": "1.18.1",
|
|
43
44
|
"camera-controls": "2.10.1",
|
|
44
|
-
"eslint": "9.
|
|
45
|
+
"eslint": "9.30.1",
|
|
45
46
|
"eslint-config-prettier": "10.1.5",
|
|
46
|
-
"eslint-plugin-svelte": "3.
|
|
47
|
-
"globals": "16.
|
|
47
|
+
"eslint-plugin-svelte": "3.10.1",
|
|
48
|
+
"globals": "16.3.0",
|
|
48
49
|
"idb-keyval": "6.2.2",
|
|
49
50
|
"jsdom": "26.1.0",
|
|
50
51
|
"lodash-es": "4.17.21",
|
|
51
|
-
"lucide-svelte": "0.
|
|
52
|
-
"prettier": "3.
|
|
52
|
+
"lucide-svelte": "0.525.0",
|
|
53
|
+
"prettier": "3.6.2",
|
|
53
54
|
"prettier-plugin-svelte": "3.4.0",
|
|
54
|
-
"prettier-plugin-tailwindcss": "0.6.
|
|
55
|
+
"prettier-plugin-tailwindcss": "0.6.13",
|
|
55
56
|
"publint": "0.3.12",
|
|
56
|
-
"runed": "0.
|
|
57
|
-
"svelte": "5.
|
|
58
|
-
"svelte-check": "4.2.
|
|
57
|
+
"runed": "0.29.1",
|
|
58
|
+
"svelte": "5.34.8",
|
|
59
|
+
"svelte-check": "4.2.2",
|
|
59
60
|
"svelte-virtuallists": "1.4.2",
|
|
60
|
-
"tailwindcss": "4.1.
|
|
61
|
-
"three": "0.
|
|
62
|
-
"threlte-uikit": "1.
|
|
63
|
-
"tsx": "4.20.
|
|
61
|
+
"tailwindcss": "4.1.11",
|
|
62
|
+
"three": "0.178.0",
|
|
63
|
+
"threlte-uikit": "1.2.0",
|
|
64
|
+
"tsx": "4.20.3",
|
|
64
65
|
"typescript": "5.8.3",
|
|
65
|
-
"typescript-eslint": "8.
|
|
66
|
+
"typescript-eslint": "8.35.1",
|
|
66
67
|
"vite": "6.3.5",
|
|
67
|
-
"vite-plugin-devtools-json": "0.2.
|
|
68
|
+
"vite-plugin-devtools-json": "0.2.1",
|
|
68
69
|
"vite-plugin-mkcert": "1.17.8",
|
|
69
|
-
"vitest": "3.2.
|
|
70
|
+
"vitest": "3.2.4"
|
|
70
71
|
},
|
|
71
72
|
"peerDependencies": {
|
|
72
73
|
"@dimforge/rapier3d-compat": ">=0.17",
|