@viamrobotics/motion-tools 1.15.7 → 1.16.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/buf/common/v1/common_pb.d.ts +38 -0
- package/dist/buf/common/v1/common_pb.js +64 -0
- package/dist/buf/draw/v1/scene_pb.d.ts +6 -2
- package/dist/buf/draw/v1/scene_pb.js +9 -3
- package/dist/components/Entities/Geometry.svelte +1 -1
- package/dist/components/PCD.svelte +4 -1
- package/dist/components/PCD.svelte.d.ts +1 -0
- package/dist/components/SceneProviders.svelte +0 -2
- 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 +293 -0
- package/dist/components/Selection/Ellipse.svelte.d.ts +7 -0
- package/dist/components/{Lasso → Selection}/Lasso.svelte +31 -61
- package/dist/components/{Lasso → Selection}/Lasso.svelte.d.ts +1 -0
- package/dist/components/{Lasso → Selection}/Tool.svelte +50 -15
- package/dist/components/{Lasso → Selection}/traits.d.ts +11 -2
- package/dist/components/{Lasso → Selection}/traits.js +7 -2
- package/dist/components/Selection/utils.d.ts +5 -0
- package/dist/components/Selection/utils.js +38 -0
- package/dist/components/Snapshot.svelte +8 -0
- package/dist/components/overlay/RefreshRate.svelte +7 -6
- package/dist/components/overlay/RefreshRate.svelte.d.ts +1 -1
- package/dist/components/overlay/settings/Settings.svelte +16 -8
- package/dist/components/xr/OriginMarker.svelte +94 -17
- package/dist/hooks/useControls.svelte.d.ts +1 -0
- package/dist/hooks/useControls.svelte.js +4 -0
- package/dist/hooks/useGeometries.svelte.js +7 -9
- package/dist/hooks/usePointcloudObjects.svelte.js +7 -6
- package/dist/hooks/usePointclouds.svelte.js +7 -6
- package/dist/hooks/usePose.svelte.js +3 -3
- package/dist/hooks/useSettings.svelte.d.ts +13 -1
- package/dist/hooks/useSettings.svelte.js +13 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/hooks/useMachineSettings.svelte.d.ts +0 -13
- package/dist/hooks/useMachineSettings.svelte.js +0 -58
- /package/dist/components/{Lasso → Selection}/Tool.svelte.d.ts +0 -0
|
@@ -4,20 +4,22 @@
|
|
|
4
4
|
import { useThrelte } from '@threlte/core'
|
|
5
5
|
import earcut from 'earcut'
|
|
6
6
|
import { Not } from 'koota'
|
|
7
|
-
import { Box3,
|
|
7
|
+
import { Box3, Triangle, Vector3 } from 'three'
|
|
8
8
|
|
|
9
9
|
import { createBufferGeometry } from '../../attribute'
|
|
10
10
|
import { traits, useQuery, useWorld } from '../../ecs'
|
|
11
11
|
import { useCameraControls } from '../../hooks/useControls.svelte'
|
|
12
12
|
|
|
13
13
|
import Debug from './Debug.svelte'
|
|
14
|
-
import * as
|
|
14
|
+
import * as selectionTraits from './traits'
|
|
15
|
+
import { getTriangleBoxesFromIndices, getTriangleFromIndex, raycast } from './utils'
|
|
15
16
|
|
|
16
17
|
interface Props {
|
|
18
|
+
active?: boolean
|
|
17
19
|
debug?: boolean
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
let { debug = false }: Props = $props()
|
|
22
|
+
let { active = false, debug = false }: Props = $props()
|
|
21
23
|
|
|
22
24
|
const world = useWorld()
|
|
23
25
|
const controls = useCameraControls()
|
|
@@ -29,33 +31,14 @@
|
|
|
29
31
|
|
|
30
32
|
const triangle = new Triangle()
|
|
31
33
|
const triangleBox = new Box3()
|
|
32
|
-
const a = new Vector3()
|
|
33
|
-
const b = new Vector3()
|
|
34
|
-
const c = new Vector3()
|
|
35
34
|
|
|
36
35
|
let frameScheduled = false
|
|
37
36
|
let drawing = false
|
|
38
37
|
|
|
39
|
-
const raycaster = new Raycaster()
|
|
40
|
-
const mouse = new Vector2()
|
|
41
|
-
const plane = new Plane(new Vector3(0, 0, 1), 0)
|
|
42
|
-
const point = new Vector3()
|
|
43
|
-
|
|
44
|
-
const raycast = (event: PointerEvent) => {
|
|
45
|
-
const element = event.target as HTMLElement
|
|
46
|
-
const rect = element.getBoundingClientRect()
|
|
47
|
-
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
|
|
48
|
-
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
|
|
49
|
-
|
|
50
|
-
raycaster.setFromCamera(mouse, camera.current)
|
|
51
|
-
raycaster.ray.intersectPlane(plane, point)
|
|
52
|
-
return point
|
|
53
|
-
}
|
|
54
|
-
|
|
55
38
|
const onpointerdown = (event: PointerEvent) => {
|
|
56
|
-
if (!event.shiftKey) return
|
|
39
|
+
if (!event.shiftKey || !active) return
|
|
57
40
|
|
|
58
|
-
const { x, y } = raycast(event)
|
|
41
|
+
const { x, y } = raycast(event, camera.current)
|
|
59
42
|
|
|
60
43
|
drawing = true
|
|
61
44
|
|
|
@@ -65,8 +48,8 @@
|
|
|
65
48
|
traits.RenderOrder(999),
|
|
66
49
|
traits.Material({ depthTest: false }),
|
|
67
50
|
traits.Color({ r: 1, g: 0, b: 0 }),
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
selectionTraits.Box({ minX: x, minY: y, maxX: x, maxY: y }),
|
|
52
|
+
selectionTraits.Lasso
|
|
70
53
|
)
|
|
71
54
|
|
|
72
55
|
if (controls.current) {
|
|
@@ -75,9 +58,9 @@
|
|
|
75
58
|
}
|
|
76
59
|
|
|
77
60
|
const onpointermove = (event: PointerEvent) => {
|
|
78
|
-
if (!drawing) return
|
|
61
|
+
if (!drawing || !active) return
|
|
79
62
|
|
|
80
|
-
let lasso = world.query(
|
|
63
|
+
let lasso = world.query(selectionTraits.Lasso).at(-1)
|
|
81
64
|
|
|
82
65
|
if (!lasso) return
|
|
83
66
|
|
|
@@ -92,9 +75,9 @@
|
|
|
92
75
|
requestAnimationFrame(() => {
|
|
93
76
|
frameScheduled = false
|
|
94
77
|
|
|
95
|
-
const { x, y } = raycast(event)
|
|
78
|
+
const { x, y } = raycast(event, camera.current)
|
|
96
79
|
const positions = lasso.get(traits.LinePositions)
|
|
97
|
-
const box = lasso.get(
|
|
80
|
+
const box = lasso.get(selectionTraits.Box)
|
|
98
81
|
|
|
99
82
|
if (!positions || !box) return
|
|
100
83
|
|
|
@@ -110,22 +93,22 @@
|
|
|
110
93
|
if (y < box.minY) box.minY = y
|
|
111
94
|
else if (y > box.maxY) box.maxY = y
|
|
112
95
|
|
|
113
|
-
lasso.set(
|
|
96
|
+
lasso.set(selectionTraits.Box, box)
|
|
114
97
|
})
|
|
115
98
|
}
|
|
116
99
|
|
|
117
100
|
const onpointerleave = () => {
|
|
118
|
-
if (!drawing) return
|
|
101
|
+
if (!drawing || !active) return
|
|
119
102
|
|
|
120
103
|
onpointerup()
|
|
121
104
|
}
|
|
122
105
|
|
|
123
106
|
const onpointerup = () => {
|
|
124
|
-
if (!drawing) return
|
|
107
|
+
if (!drawing || !active) return
|
|
125
108
|
|
|
126
109
|
drawing = false
|
|
127
110
|
|
|
128
|
-
let lasso = world.query(
|
|
111
|
+
let lasso = world.query(selectionTraits.Lasso).at(-1)
|
|
129
112
|
|
|
130
113
|
if (!lasso) return
|
|
131
114
|
|
|
@@ -149,31 +132,15 @@
|
|
|
149
132
|
|
|
150
133
|
const indices = earcut(positions, undefined, 3)
|
|
151
134
|
if (debug) {
|
|
152
|
-
lasso.add(
|
|
135
|
+
lasso.add(selectionTraits.Indices(new Uint16Array(indices)))
|
|
153
136
|
}
|
|
154
137
|
|
|
155
|
-
const
|
|
156
|
-
const stride = 3
|
|
157
|
-
const ia = indices[i + 0] * stride
|
|
158
|
-
const ib = indices[i + 1] * stride
|
|
159
|
-
const ic = indices[i + 2] * stride
|
|
160
|
-
a.set(positions[ia + 0], positions[ia + 1], positions[ia + 2])
|
|
161
|
-
b.set(positions[ib + 0], positions[ib + 1], positions[ib + 2])
|
|
162
|
-
c.set(positions[ic + 0], positions[ic + 1], positions[ic + 2])
|
|
163
|
-
triangle.set(a, b, c)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const boxes: lassoTraits.AABB[] = []
|
|
167
|
-
for (let i = 0, l = indices.length; i < l; i += 3) {
|
|
168
|
-
getTriangleFromIndex(i, triangle)
|
|
169
|
-
box3.setFromPoints([triangle.a, triangle.b, triangle.c])
|
|
170
|
-
boxes.push({ minX: box3.min.x, minY: box3.min.y, maxX: box3.max.x, maxY: box3.max.y })
|
|
171
|
-
}
|
|
138
|
+
const boxes: selectionTraits.AABB[] = getTriangleBoxesFromIndices(indices, positions)
|
|
172
139
|
if (debug) {
|
|
173
|
-
lasso.add(
|
|
140
|
+
lasso.add(selectionTraits.Boxes(boxes))
|
|
174
141
|
}
|
|
175
142
|
|
|
176
|
-
const lassoBox = lasso.get(
|
|
143
|
+
const lassoBox = lasso.get(selectionTraits.Box)
|
|
177
144
|
|
|
178
145
|
if (!lassoBox) return
|
|
179
146
|
|
|
@@ -183,7 +150,10 @@
|
|
|
183
150
|
|
|
184
151
|
const enclosedPoints: number[] = []
|
|
185
152
|
|
|
186
|
-
for (const pointsEntity of world.query(
|
|
153
|
+
for (const pointsEntity of world.query(
|
|
154
|
+
traits.Points,
|
|
155
|
+
Not(selectionTraits.SelectionEnclosedPoints)
|
|
156
|
+
)) {
|
|
187
157
|
const geometry = pointsEntity.get(traits.BufferGeometry)
|
|
188
158
|
|
|
189
159
|
if (!geometry) return
|
|
@@ -208,7 +178,7 @@
|
|
|
208
178
|
triangleBox.set(min, max)
|
|
209
179
|
|
|
210
180
|
if (triangleBox.containsPoint(point)) {
|
|
211
|
-
getTriangleFromIndex(i, triangle)
|
|
181
|
+
getTriangleFromIndex(i, indices, positions, triangle)
|
|
212
182
|
|
|
213
183
|
if (triangle.containsPoint(point)) {
|
|
214
184
|
enclosedPoints.push(point.x, point.y, point.z)
|
|
@@ -230,8 +200,8 @@
|
|
|
230
200
|
traits.Material({ depthTest: false }),
|
|
231
201
|
traits.Points,
|
|
232
202
|
traits.Removable,
|
|
233
|
-
|
|
234
|
-
|
|
203
|
+
selectionTraits.SelectionEnclosedPoints,
|
|
204
|
+
selectionTraits.PointsCapturedBy(lasso)
|
|
235
205
|
)
|
|
236
206
|
}
|
|
237
207
|
|
|
@@ -265,7 +235,7 @@
|
|
|
265
235
|
}
|
|
266
236
|
})
|
|
267
237
|
|
|
268
|
-
const lassos = useQuery(
|
|
238
|
+
const lassos = useQuery(selectionTraits.Lasso)
|
|
269
239
|
|
|
270
240
|
$effect(() => {
|
|
271
241
|
if (!controls.current) return
|
|
@@ -288,7 +258,7 @@
|
|
|
288
258
|
// On unmount, destroy all lasso related entities
|
|
289
259
|
$effect(() => {
|
|
290
260
|
return () => {
|
|
291
|
-
for (const entity of world.query(
|
|
261
|
+
for (const entity of world.query(selectionTraits.SelectionEnclosedPoints)) {
|
|
292
262
|
if (world.has(entity)) {
|
|
293
263
|
entity.destroy()
|
|
294
264
|
}
|
|
@@ -299,6 +269,6 @@
|
|
|
299
269
|
|
|
300
270
|
{#if debug}
|
|
301
271
|
{#each lassos.current as lasso (lasso)}
|
|
302
|
-
<Debug {lasso} />
|
|
272
|
+
<Debug selection={lasso} />
|
|
303
273
|
{/each}
|
|
304
274
|
{/if}
|
|
@@ -13,8 +13,11 @@
|
|
|
13
13
|
import { createBinaryPCD } from '../../pcd'
|
|
14
14
|
|
|
15
15
|
import FloatingPanel from '../overlay/FloatingPanel.svelte'
|
|
16
|
+
import Popover from '../overlay/Popover.svelte'
|
|
17
|
+
import ToggleGroup from '../overlay/ToggleGroup.svelte'
|
|
18
|
+
import Ellipse from './Ellipse.svelte'
|
|
16
19
|
import Lasso from './Lasso.svelte'
|
|
17
|
-
import * as
|
|
20
|
+
import * as selectionTraits from './traits'
|
|
18
21
|
|
|
19
22
|
interface Props {
|
|
20
23
|
/** Whether to auto-enable lasso mode when the component mounts */
|
|
@@ -24,15 +27,18 @@
|
|
|
24
27
|
onSelection: (pcd: Blob) => void
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
type SelectionType = 'lasso' | 'ellipse'
|
|
31
|
+
|
|
27
32
|
let { enabled = false, onSelection }: Props = $props()
|
|
28
33
|
|
|
29
34
|
const { dom } = useThrelte()
|
|
30
35
|
const world = useWorld()
|
|
31
36
|
const settings = useSettings()
|
|
32
|
-
const
|
|
37
|
+
const isSelectionMode = $derived(settings.current.interactionMode === 'select')
|
|
38
|
+
let selectionType = $state<SelectionType>('lasso')
|
|
33
39
|
|
|
34
40
|
const onCommitClick = () => {
|
|
35
|
-
const entities = world.query(
|
|
41
|
+
const entities = world.query(selectionTraits.SelectionEnclosedPoints)
|
|
36
42
|
|
|
37
43
|
const geometries: BufferGeometry[] = []
|
|
38
44
|
for (const entity of entities) {
|
|
@@ -58,14 +64,14 @@
|
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
$effect(() => {
|
|
61
|
-
if (
|
|
67
|
+
if (isSelectionMode) {
|
|
62
68
|
settings.current.cameraMode = 'orthographic'
|
|
63
69
|
}
|
|
64
70
|
})
|
|
65
71
|
|
|
66
72
|
$effect(() => {
|
|
67
73
|
if (enabled) {
|
|
68
|
-
settings.current.interactionMode = '
|
|
74
|
+
settings.current.interactionMode = 'select'
|
|
69
75
|
}
|
|
70
76
|
})
|
|
71
77
|
|
|
@@ -74,19 +80,48 @@
|
|
|
74
80
|
|
|
75
81
|
<Portal id="dashboard">
|
|
76
82
|
<fieldset>
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
<div class="flex">
|
|
84
|
+
<DashboardButton
|
|
85
|
+
active={isSelectionMode}
|
|
86
|
+
icon="selection-drag"
|
|
87
|
+
description="{isSelectionMode ? 'Disable' : 'Enable'} selection"
|
|
88
|
+
onclick={() => {
|
|
89
|
+
settings.current.interactionMode = isSelectionMode ? 'navigate' : 'select'
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
<Popover>
|
|
93
|
+
{#snippet trigger(triggerProps)}
|
|
94
|
+
<DashboardButton
|
|
95
|
+
{...triggerProps}
|
|
96
|
+
active={isSelectionMode}
|
|
97
|
+
class="border-l-0"
|
|
98
|
+
icon="filter-sliders"
|
|
99
|
+
description="Selection settings"
|
|
100
|
+
/>
|
|
101
|
+
{/snippet}
|
|
102
|
+
|
|
103
|
+
<div class="border-medium m-2 border bg-white p-2 text-xs">
|
|
104
|
+
<div class="flex items-center gap-2">
|
|
105
|
+
Selection type
|
|
106
|
+
<ToggleGroup
|
|
107
|
+
options={[
|
|
108
|
+
{ label: 'Lasso', selected: selectionType === 'lasso' },
|
|
109
|
+
{ label: 'Ellipse', selected: selectionType === 'ellipse' },
|
|
110
|
+
]}
|
|
111
|
+
onSelect={(details) => {
|
|
112
|
+
selectionType = details.includes('Lasso') ? 'lasso' : 'ellipse'
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</Popover>
|
|
118
|
+
</div>
|
|
85
119
|
</fieldset>
|
|
86
120
|
</Portal>
|
|
87
121
|
|
|
88
|
-
{#if
|
|
89
|
-
<
|
|
122
|
+
{#if isSelectionMode && rect.height > 0 && rect.width > 0}
|
|
123
|
+
<Ellipse active={selectionType === 'ellipse'} />
|
|
124
|
+
<Lasso active={selectionType === 'lasso'} />
|
|
90
125
|
|
|
91
126
|
<Portal id="dom">
|
|
92
127
|
<FloatingPanel
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export declare const Lasso: import("koota").Trait<() => boolean>;
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const Ellipse: import("koota").Trait<() => boolean>;
|
|
3
|
+
export declare const SelectionEnclosedPoints: import("koota").Trait<() => boolean>;
|
|
3
4
|
/**
|
|
4
5
|
* Captured points are removable, so we want to also destroy
|
|
5
|
-
* the source
|
|
6
|
+
* the source selection every time a user deletes one.
|
|
6
7
|
*/
|
|
7
8
|
export declare const PointsCapturedBy: import("koota").Relation<import("koota").Trait<Record<string, never>>>;
|
|
8
9
|
export interface AABB {
|
|
@@ -11,11 +12,19 @@ export interface AABB {
|
|
|
11
12
|
maxX: number;
|
|
12
13
|
maxY: number;
|
|
13
14
|
}
|
|
15
|
+
export interface Point {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
}
|
|
14
19
|
export declare const Box: import("koota").Trait<{
|
|
15
20
|
minX: number;
|
|
16
21
|
minY: number;
|
|
17
22
|
maxX: number;
|
|
18
23
|
maxY: number;
|
|
19
24
|
}>;
|
|
25
|
+
export declare const StartPoint: import("koota").Trait<{
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
}>;
|
|
20
29
|
export declare const Indices: import("koota").Trait<() => Uint16Array<ArrayBuffer>>;
|
|
21
30
|
export declare const Boxes: import("koota").Trait<() => AABB[]>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { relation, trait } from 'koota';
|
|
2
2
|
export const Lasso = trait(() => true);
|
|
3
|
-
export const
|
|
3
|
+
export const Ellipse = trait(() => true);
|
|
4
|
+
export const SelectionEnclosedPoints = trait(() => true);
|
|
4
5
|
/**
|
|
5
6
|
* Captured points are removable, so we want to also destroy
|
|
6
|
-
* the source
|
|
7
|
+
* the source selection every time a user deletes one.
|
|
7
8
|
*/
|
|
8
9
|
export const PointsCapturedBy = relation({ autoDestroy: 'target' });
|
|
9
10
|
export const Box = trait({
|
|
@@ -12,5 +13,9 @@ export const Box = trait({
|
|
|
12
13
|
maxX: 0,
|
|
13
14
|
maxY: 0,
|
|
14
15
|
});
|
|
16
|
+
export const StartPoint = trait({
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0,
|
|
19
|
+
});
|
|
15
20
|
export const Indices = trait(() => new Uint16Array());
|
|
16
21
|
export const Boxes = trait(() => []);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Camera, Triangle, Vector3 } from 'three';
|
|
2
|
+
import type * as selectionTraits from './traits';
|
|
3
|
+
export declare const raycast: (event: PointerEvent, camera: Camera) => Vector3;
|
|
4
|
+
export declare const getTriangleFromIndex: (i: number, indices: number[], positions: Float32Array, outTriangle: Triangle) => void;
|
|
5
|
+
export declare const getTriangleBoxesFromIndices: (indices: number[], positions: Float32Array) => selectionTraits.AABB[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Box3, Camera, Plane, Raycaster, Triangle, Vector2, Vector3 } from 'three';
|
|
2
|
+
const raycaster = new Raycaster();
|
|
3
|
+
const mouse = new Vector2();
|
|
4
|
+
const plane = new Plane(new Vector3(0, 0, 1), 0);
|
|
5
|
+
const point = new Vector3();
|
|
6
|
+
const triangle = new Triangle();
|
|
7
|
+
const box3 = new Box3();
|
|
8
|
+
const a = new Vector3();
|
|
9
|
+
const b = new Vector3();
|
|
10
|
+
const c = new Vector3();
|
|
11
|
+
export const raycast = (event, camera) => {
|
|
12
|
+
const element = event.target;
|
|
13
|
+
const rect = element.getBoundingClientRect();
|
|
14
|
+
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
|
15
|
+
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
|
16
|
+
raycaster.setFromCamera(mouse, camera);
|
|
17
|
+
raycaster.ray.intersectPlane(plane, point);
|
|
18
|
+
return point;
|
|
19
|
+
};
|
|
20
|
+
export const getTriangleFromIndex = (i, indices, positions, outTriangle) => {
|
|
21
|
+
const stride = 3;
|
|
22
|
+
const ia = indices[i + 0] * stride;
|
|
23
|
+
const ib = indices[i + 1] * stride;
|
|
24
|
+
const ic = indices[i + 2] * stride;
|
|
25
|
+
a.set(positions[ia + 0], positions[ia + 1], positions[ia + 2]);
|
|
26
|
+
b.set(positions[ib + 0], positions[ib + 1], positions[ib + 2]);
|
|
27
|
+
c.set(positions[ic + 0], positions[ic + 1], positions[ic + 2]);
|
|
28
|
+
outTriangle.set(a, b, c);
|
|
29
|
+
};
|
|
30
|
+
export const getTriangleBoxesFromIndices = (indices, positions) => {
|
|
31
|
+
const boxes = [];
|
|
32
|
+
for (let i = 0, l = indices.length; i < l; i += 3) {
|
|
33
|
+
getTriangleFromIndex(i, indices, positions, triangle);
|
|
34
|
+
box3.setFromPoints([triangle.a, triangle.b, triangle.c]);
|
|
35
|
+
boxes.push({ minX: box3.min.x, minY: box3.min.y, maxX: box3.max.x, maxY: box3.max.y });
|
|
36
|
+
}
|
|
37
|
+
return boxes;
|
|
38
|
+
};
|
|
@@ -66,6 +66,14 @@ Renders a Snapshot protobuf by spawning its transforms and drawings as entities
|
|
|
66
66
|
position: [x * 0.001, y * 0.001, z * 0.001],
|
|
67
67
|
lookAt: [lx * 0.001, ly * 0.001, lz * 0.001],
|
|
68
68
|
})
|
|
69
|
+
|
|
70
|
+
if (sceneCamera.cameraType.case === 'orthographicCamera') {
|
|
71
|
+
const orthographicCamera = sceneCamera.cameraType.value as { zoom?: number }
|
|
72
|
+
const zoom = orthographicCamera.zoom
|
|
73
|
+
if (zoom !== undefined) {
|
|
74
|
+
cameraControls.setZoom(zoom)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
69
77
|
}
|
|
70
78
|
})
|
|
71
79
|
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
|
|
21
21
|
import { IconButton, Select } from '@viamrobotics/prime-core'
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
24
24
|
|
|
25
25
|
interface Props {
|
|
26
|
-
id:
|
|
26
|
+
id: 'poses' | 'pointclouds' | 'vision'
|
|
27
27
|
label: string
|
|
28
28
|
allowLive?: boolean
|
|
29
29
|
onManualRefetch: () => void
|
|
@@ -32,8 +32,9 @@
|
|
|
32
32
|
|
|
33
33
|
let { id, label, allowLive = false, onManualRefetch, children }: Props = $props()
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
const
|
|
35
|
+
const settings = useSettings()
|
|
36
|
+
const { refreshRates } = $derived(settings.current)
|
|
37
|
+
const rate = $derived(refreshRates[id] ?? RefetchRates.MANUAL)
|
|
37
38
|
</script>
|
|
38
39
|
|
|
39
40
|
<label class="flex flex-col gap-1">
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
onchange={(event: InputEvent) => {
|
|
49
50
|
if (event.target instanceof HTMLSelectElement) {
|
|
50
51
|
const { value } = event.target
|
|
51
|
-
refreshRates
|
|
52
|
+
refreshRates[id] = Number.parseInt(value, 10)
|
|
52
53
|
}
|
|
53
54
|
}}
|
|
54
55
|
value={String(rate)}
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
variant="secondary"
|
|
88
89
|
cx="border-light border"
|
|
89
90
|
onclick={() => {
|
|
90
|
-
refreshRates
|
|
91
|
+
refreshRates[id] = RefetchRates.MANUAL
|
|
91
92
|
}}
|
|
92
93
|
/>
|
|
93
94
|
{/if}
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
import DashboardButton from '../dashboard/Button.svelte'
|
|
10
10
|
import XRControllerSettings from '../../xr/XRControllerSettings.svelte'
|
|
11
11
|
import { useGeometries } from '../../../hooks/useGeometries.svelte'
|
|
12
|
-
import { RefreshRates, useMachineSettings } from '../../../hooks/useMachineSettings.svelte'
|
|
13
12
|
import { usePartID } from '../../../hooks/usePartID.svelte'
|
|
13
|
+
import { usePointcloudObjects } from '../../../hooks/usePointcloudObjects.svelte'
|
|
14
14
|
import { usePointClouds } from '../../../hooks/usePointclouds.svelte'
|
|
15
15
|
import { useRefetchPoses } from '../../../hooks/useRefetchPoses'
|
|
16
|
-
import { useSettings } from '../../../hooks/useSettings.svelte'
|
|
16
|
+
import { RefreshRates, useSettings } from '../../../hooks/useSettings.svelte'
|
|
17
17
|
import { useWeblabs, WEBLABS_EXPERIMENTS } from '../../../hooks/useWeblabs.svelte'
|
|
18
18
|
|
|
19
19
|
import FloatingPanel from '../FloatingPanel.svelte'
|
|
@@ -26,9 +26,10 @@
|
|
|
26
26
|
const cameras = useResourceNames(() => partID.current, 'camera')
|
|
27
27
|
const visionServices = useResourceNames(() => partID.current, 'vision')
|
|
28
28
|
const settings = useSettings()
|
|
29
|
-
const { disabledCameras, disabledVisionServices } =
|
|
29
|
+
const { disabledCameras, disabledVisionServices } = $derived(settings.current)
|
|
30
30
|
const geometries = useGeometries()
|
|
31
31
|
const pointclouds = usePointClouds()
|
|
32
|
+
const pointcloudObjects = usePointcloudObjects()
|
|
32
33
|
const { refetchPoses } = useRefetchPoses()
|
|
33
34
|
const weblabs = useWeblabs()
|
|
34
35
|
const knownWeblabs = Object.keys(WEBLABS_EXPERIMENTS)
|
|
@@ -87,11 +88,18 @@
|
|
|
87
88
|
/>
|
|
88
89
|
<RefreshRate
|
|
89
90
|
id={RefreshRates.pointclouds}
|
|
90
|
-
label="Pointclouds"
|
|
91
|
+
label="Pointclouds from cameras"
|
|
91
92
|
onManualRefetch={() => {
|
|
92
93
|
pointclouds.refetch()
|
|
93
94
|
}}
|
|
94
95
|
/>
|
|
96
|
+
<RefreshRate
|
|
97
|
+
id={RefreshRates.vision}
|
|
98
|
+
label="Vision service pointcloud segments and objects"
|
|
99
|
+
onManualRefetch={() => {
|
|
100
|
+
pointcloudObjects.refetch()
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
95
103
|
</div>
|
|
96
104
|
{/snippet}
|
|
97
105
|
|
|
@@ -126,9 +134,9 @@
|
|
|
126
134
|
<div class="flex items-center justify-between py-0.5 text-xs">
|
|
127
135
|
{camera.name}
|
|
128
136
|
<Switch
|
|
129
|
-
on={disabledCameras
|
|
137
|
+
on={disabledCameras[camera.name] !== true}
|
|
130
138
|
on:change={(event) => {
|
|
131
|
-
disabledCameras
|
|
139
|
+
disabledCameras[camera.name] = !event.detail
|
|
132
140
|
}}
|
|
133
141
|
/>
|
|
134
142
|
</div>
|
|
@@ -146,9 +154,9 @@
|
|
|
146
154
|
<div class="flex items-center justify-between py-0.5">
|
|
147
155
|
{visionService.name}
|
|
148
156
|
<Switch
|
|
149
|
-
on={disabledVisionServices
|
|
157
|
+
on={disabledVisionServices[visionService.name] !== true}
|
|
150
158
|
on:change={(event) => {
|
|
151
|
-
disabledVisionServices
|
|
159
|
+
disabledVisionServices[visionService.name] = !event.detail
|
|
152
160
|
}}
|
|
153
161
|
/>
|
|
154
162
|
</div>
|