@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/buffer.js
CHANGED
|
@@ -1,57 +1,61 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Zero-copy buffer utilities for converting protobuf bytes to Three.js typed arrays.
|
|
3
|
-
*
|
|
4
|
-
* Proto messages pack float32 data as `Uint8Array` (bytes fields). These utilities
|
|
5
|
-
* provide efficient conversion to `Float32Array` for Three.js BufferAttributes.
|
|
6
|
-
*/
|
|
7
1
|
import { Color } from 'three';
|
|
8
|
-
|
|
9
|
-
* Stride constants for proto binary data formats.
|
|
10
|
-
* Each value represents the number of float32 elements per item.
|
|
11
|
-
*/
|
|
2
|
+
import { ColorFormat } from './buf/draw/v1/metadata_pb';
|
|
12
3
|
export const STRIDE = {
|
|
13
|
-
/** Arrows: [x, y, z, ox, oy, oz]
|
|
4
|
+
/** Arrows: [x, y, z, ox, oy, oz, ...] */
|
|
14
5
|
ARROWS: 6,
|
|
15
|
-
/** Line/Points: [x, y, z]
|
|
6
|
+
/** Line/Points: [x, y, z, ...] */
|
|
16
7
|
POSITIONS: 3,
|
|
17
|
-
/** Nurbs control points: [x, y, z, ox, oy, oz, theta]
|
|
8
|
+
/** Nurbs control points: [x, y, z, ox, oy, oz, theta, ...] */
|
|
18
9
|
NURBS_CONTROL_POINTS: 7,
|
|
19
|
-
/** Nurbs knots/weights:
|
|
10
|
+
/** Nurbs knots/weights: [w, ...] */
|
|
20
11
|
NURBS_KNOTS: 1,
|
|
21
|
-
/** Colors: [r, g, b,
|
|
22
|
-
COLORS_RGBA: 4,
|
|
23
|
-
/** Colors: [r, g, b] */
|
|
12
|
+
/** Colors: [r, g, b, ...] */
|
|
24
13
|
COLORS_RGB: 3,
|
|
25
14
|
};
|
|
26
15
|
/**
|
|
27
16
|
* Creates a Float32Array view over a Uint8Array without copying data.
|
|
28
17
|
* Falls back to a copy if the buffer is not 4-byte aligned (rare with protobuf).
|
|
29
18
|
*
|
|
19
|
+
* An optional `transform` applies a per-element function during conversion.
|
|
20
|
+
*
|
|
30
21
|
* @param bytes - The raw bytes from a protobuf bytes field
|
|
22
|
+
* @param transform - Optional function applied to every float element
|
|
31
23
|
* @returns A Float32Array view or copy of the data
|
|
32
24
|
*
|
|
33
25
|
* @example
|
|
34
26
|
* ```ts
|
|
35
27
|
* const positions = asFloat32Array(line.positions)
|
|
36
|
-
*
|
|
28
|
+
* const meterPositions = asFloat32Array(line.positions, inMeters)
|
|
37
29
|
* ```
|
|
38
30
|
*/
|
|
39
|
-
export const asFloat32Array = (bytes) => {
|
|
31
|
+
export const asFloat32Array = (bytes, transform) => {
|
|
40
32
|
if (bytes.length === 0) {
|
|
41
33
|
return new Float32Array(0);
|
|
42
34
|
}
|
|
43
35
|
if (bytes.byteOffset % 4 === 0 && bytes.byteLength % 4 === 0) {
|
|
44
|
-
|
|
36
|
+
const view = new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
|
|
37
|
+
if (transform) {
|
|
38
|
+
for (let i = 0; i < view.length; i++)
|
|
39
|
+
view[i] = transform(view[i]);
|
|
40
|
+
}
|
|
41
|
+
return view;
|
|
45
42
|
}
|
|
46
43
|
const aligned = new Float32Array(bytes.byteLength / 4);
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
45
|
+
if (transform) {
|
|
46
|
+
for (let i = 0; i < aligned.length; i++) {
|
|
47
|
+
aligned[i] = transform(dataView.getFloat32(i * 4, true));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
for (let i = 0; i < aligned.length; i++) {
|
|
52
|
+
aligned[i] = dataView.getFloat32(i * 4, true);
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
return aligned;
|
|
52
56
|
};
|
|
53
57
|
/**
|
|
54
|
-
* Sets a Three.js Color from 3 bytes of a uint8 color array starting at `offset`.
|
|
58
|
+
* Sets a Three.js Color from 3 bytes of a uint8 RGB color array starting at `offset`.
|
|
55
59
|
* Mutates and returns `target` — pass a pre-allocated Color to avoid allocations
|
|
56
60
|
* in hot paths.
|
|
57
61
|
*
|
|
@@ -63,7 +67,7 @@ export const asFloat32Array = (bytes) => {
|
|
|
63
67
|
* @example
|
|
64
68
|
* ```ts
|
|
65
69
|
* asColor(colors.current, material.color)
|
|
66
|
-
* asColor(colors.current, pointColorUtil,
|
|
70
|
+
* asColor(colors.current, pointColorUtil, STRIDE.COLORS_RGB) // read second color
|
|
67
71
|
* ```
|
|
68
72
|
*/
|
|
69
73
|
export const asColor = (bytes, target, offset = 0) => {
|
|
@@ -71,59 +75,89 @@ export const asColor = (bytes, target, offset = 0) => {
|
|
|
71
75
|
return target.setRGB(0, 0, 0);
|
|
72
76
|
return target.setRGB(bytes[offset] / 255, bytes[offset + 1] / 255, bytes[offset + 2] / 255);
|
|
73
77
|
};
|
|
78
|
+
export const asRGB = (bytes, target, offset = 0) => {
|
|
79
|
+
target.r = (bytes[offset] ?? 0) / 255;
|
|
80
|
+
target.g = (bytes[offset + 1] ?? 0) / 255;
|
|
81
|
+
target.b = (bytes[offset + 2] ?? 0) / 255;
|
|
82
|
+
return target;
|
|
83
|
+
};
|
|
74
84
|
/**
|
|
75
|
-
*
|
|
85
|
+
* Reads a byte from a uint8 opacities array at `index` and normalizes it to 0-1.
|
|
86
|
+
* Returns `fallback` when the array is absent or shorter than `index + 1`.
|
|
76
87
|
*
|
|
77
|
-
* @param
|
|
78
|
-
* @
|
|
88
|
+
* @param opacities - Uint8Array of opacity values (0-255). Length 1 = uniform. Length N = per-vertex.
|
|
89
|
+
* @param fallback - Value to return when no opacity byte is available (default 1)
|
|
90
|
+
* @param index - Index into the opacities array (default 0)
|
|
91
|
+
* @returns Normalized opacity in 0-1 range, or the fallback value
|
|
79
92
|
*
|
|
80
93
|
* @example
|
|
81
94
|
* ```ts
|
|
82
|
-
*
|
|
95
|
+
* material.opacity = asOpacity(metadata.opacities)
|
|
83
96
|
* ```
|
|
84
97
|
*/
|
|
85
|
-
export const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
export const asOpacity = (opacities, fallback = 1, index = 0) => {
|
|
99
|
+
if (!opacities || opacities.length === 0)
|
|
100
|
+
return fallback;
|
|
101
|
+
// If only one opacity byte, it is the uniform opacity regardless of index
|
|
102
|
+
const i = opacities.length === 1 ? 0 : index;
|
|
103
|
+
if (opacities.length <= i)
|
|
104
|
+
return fallback;
|
|
105
|
+
return opacities[i] / 255;
|
|
91
106
|
};
|
|
92
107
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* @param bytes - ArrayLike of uint8 color values
|
|
97
|
-
* @param fallback - Value to return when no alpha byte is present (default 1)
|
|
98
|
-
* @param offset - Byte index to read from (default 3, the alpha channel of the first color)
|
|
99
|
-
* @returns Normalized opacity in 0-1 range, or the fallback value
|
|
108
|
+
* Returns true when `colors` contains exactly one color (RGB or RGBA),
|
|
109
|
+
* as opposed to a per-vertex color array.
|
|
100
110
|
*
|
|
101
111
|
* @example
|
|
102
112
|
* ```ts
|
|
103
|
-
*
|
|
104
|
-
*
|
|
113
|
+
* if (isSingleColor(colors)) {
|
|
114
|
+
* material.color = asColor(colors, colorUtil)
|
|
115
|
+
* }
|
|
105
116
|
* ```
|
|
106
117
|
*/
|
|
107
|
-
export const
|
|
108
|
-
if (
|
|
109
|
-
return
|
|
110
|
-
return
|
|
118
|
+
export const isSingleColor = (colors) => {
|
|
119
|
+
if (!colors)
|
|
120
|
+
return false;
|
|
121
|
+
return colors.length === STRIDE.COLORS_RGB;
|
|
111
122
|
};
|
|
112
123
|
/**
|
|
113
|
-
* Returns true when `colors` contains
|
|
114
|
-
*
|
|
124
|
+
* Returns true when `colors` contains per-vertex color data rather than a
|
|
125
|
+
* single uniform color.
|
|
115
126
|
*
|
|
116
|
-
* @param colors - Uint8Array of packed
|
|
117
|
-
* @param numVertex - Number of points/vertices the color buffer should cover
|
|
127
|
+
* @param colors - Uint8Array of packed RGB bytes (stride of 3)
|
|
118
128
|
*
|
|
119
129
|
* @example
|
|
120
130
|
* ```ts
|
|
121
|
-
* if (
|
|
131
|
+
* if (isVertexColors(colors, positions.length / 3)) {
|
|
122
132
|
* // treat as per-vertex
|
|
123
|
-
* } else {
|
|
124
|
-
* addColorTraits(entityTraits, colors)
|
|
125
133
|
* }
|
|
126
134
|
* ```
|
|
127
135
|
*/
|
|
128
|
-
export const
|
|
129
|
-
colors.length ===
|
|
136
|
+
export const isVertexColors = (colors) => {
|
|
137
|
+
if (!colors || colors.length === 0)
|
|
138
|
+
return false;
|
|
139
|
+
if (isSingleColor(colors))
|
|
140
|
+
return false;
|
|
141
|
+
return colors.length % STRIDE.COLORS_RGB === 0;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Per-element transform that converts a millimeter value to meters.
|
|
145
|
+
* Pass to {@link asFloat32Array} to fuse the conversion into a single pass.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* const positions = asFloat32Array(line.positions, inMeters)
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export const inMeters = (v) => v * 0.001;
|
|
153
|
+
/** Returns the byte stride for a given color format. */
|
|
154
|
+
export const colorStride = (format) => {
|
|
155
|
+
switch (format) {
|
|
156
|
+
case ColorFormat.RGB: {
|
|
157
|
+
return STRIDE.COLORS_RGB;
|
|
158
|
+
}
|
|
159
|
+
default: {
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
package/dist/color.d.ts
CHANGED
|
@@ -34,5 +34,4 @@ export declare const parseColor: (color: unknown, defaultColor?: ColorRepresenta
|
|
|
34
34
|
export declare const isRGB: (color: unknown) => color is RGB;
|
|
35
35
|
export declare const parseRGB: (color: unknown, defaultColor?: RGB) => Color;
|
|
36
36
|
export declare const parseOpacity: (opacity: unknown, defaultOpacity?: number) => number;
|
|
37
|
-
export declare const
|
|
38
|
-
export declare const rgbaBytesToFloat32: (bytes: Uint8Array<ArrayBuffer>) => Float32Array<ArrayBuffer>;
|
|
37
|
+
export declare const rgbToHex: (rgb: Uint8Array) => string;
|
package/dist/color.js
CHANGED
|
@@ -141,18 +141,11 @@ const isColorHex = (color) => {
|
|
|
141
141
|
}
|
|
142
142
|
return false;
|
|
143
143
|
};
|
|
144
|
-
export const
|
|
145
|
-
if (
|
|
144
|
+
export const rgbToHex = (rgb) => {
|
|
145
|
+
if (rgb.length < 3)
|
|
146
146
|
return '#333333';
|
|
147
|
-
const r =
|
|
148
|
-
const g =
|
|
149
|
-
const b =
|
|
147
|
+
const r = rgb[0].toString(16).padStart(2, '0');
|
|
148
|
+
const g = rgb[1].toString(16).padStart(2, '0');
|
|
149
|
+
const b = rgb[2].toString(16).padStart(2, '0');
|
|
150
150
|
return `#${r}${g}${b}`;
|
|
151
151
|
};
|
|
152
|
-
export const rgbaBytesToFloat32 = (bytes) => {
|
|
153
|
-
const out = new Float32Array(bytes.length);
|
|
154
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
155
|
-
out[i] = bytes[i] / 255;
|
|
156
|
-
}
|
|
157
|
-
return out;
|
|
158
|
-
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Struct } from '@viamrobotics/sdk'
|
|
3
|
+
import type { Entity } from 'koota'
|
|
3
4
|
import type { Snippet } from 'svelte'
|
|
4
5
|
|
|
5
6
|
import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
|
|
@@ -47,11 +48,24 @@
|
|
|
47
48
|
interface Props {
|
|
48
49
|
partID?: string
|
|
49
50
|
enableKeybindings?: boolean
|
|
50
|
-
children?: Snippet
|
|
51
|
-
dashboard?: Snippet
|
|
52
51
|
localConfigProps?: LocalConfigProps
|
|
53
52
|
drawConnectionConfig?: DrawConnectionConfig
|
|
54
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Snippet for THREE objects
|
|
56
|
+
*/
|
|
57
|
+
children?: Snippet
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Snippet to inject items in the top middle dashboard
|
|
61
|
+
*/
|
|
62
|
+
dashboard?: Snippet
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Snippet to inject items into the details panel
|
|
66
|
+
*/
|
|
67
|
+
details?: Snippet<[{ entity: Entity }]>
|
|
68
|
+
|
|
55
69
|
/**
|
|
56
70
|
* Allows setting the initial camera pose
|
|
57
71
|
*/
|
|
@@ -66,6 +80,7 @@
|
|
|
66
80
|
drawConnectionConfig,
|
|
67
81
|
children: appChildren,
|
|
68
82
|
dashboard,
|
|
83
|
+
details,
|
|
69
84
|
}: Props = $props()
|
|
70
85
|
|
|
71
86
|
provideWorld()
|
|
@@ -121,7 +136,7 @@
|
|
|
121
136
|
<div {@attach domPortal(root)}>
|
|
122
137
|
<FileDrop />
|
|
123
138
|
<Dashboard {dashboard} />
|
|
124
|
-
<Details />
|
|
139
|
+
<Details {details} />
|
|
125
140
|
|
|
126
141
|
{#if environment.current.isStandalone}
|
|
127
142
|
<LiveUpdatesBanner />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Struct } from '@viamrobotics/sdk';
|
|
2
|
+
import type { Entity } from 'koota';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import type { CameraPose } from '../hooks/useControls.svelte';
|
|
4
5
|
import { type DrawConnectionConfig } from '../hooks/useDrawConnectionConfig.svelte';
|
|
@@ -11,10 +12,22 @@ interface LocalConfigProps {
|
|
|
11
12
|
interface Props {
|
|
12
13
|
partID?: string;
|
|
13
14
|
enableKeybindings?: boolean;
|
|
14
|
-
children?: Snippet;
|
|
15
|
-
dashboard?: Snippet;
|
|
16
15
|
localConfigProps?: LocalConfigProps;
|
|
17
16
|
drawConnectionConfig?: DrawConnectionConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Snippet for THREE objects
|
|
19
|
+
*/
|
|
20
|
+
children?: Snippet;
|
|
21
|
+
/**
|
|
22
|
+
* Snippet to inject items in the top middle dashboard
|
|
23
|
+
*/
|
|
24
|
+
dashboard?: Snippet;
|
|
25
|
+
/**
|
|
26
|
+
* Snippet to inject items into the details panel
|
|
27
|
+
*/
|
|
28
|
+
details?: Snippet<[{
|
|
29
|
+
entity: Entity;
|
|
30
|
+
}]>;
|
|
18
31
|
/**
|
|
19
32
|
* Allows setting the initial camera pose
|
|
20
33
|
*/
|
|
@@ -14,21 +14,20 @@
|
|
|
14
14
|
|
|
15
15
|
const map = new SvelteMap<Entity, InstancedArrows>()
|
|
16
16
|
|
|
17
|
+
const colorUtil = new Color()
|
|
18
|
+
|
|
17
19
|
const onAdd = (entity: Entity) => {
|
|
18
20
|
const poses = entity.get(traits.Positions)
|
|
21
|
+
const color = entity.get(traits.Color)
|
|
19
22
|
const colors = entity.get(traits.Colors)
|
|
20
23
|
const { headAtPose } = entity.get(traits.Arrows) ?? {}
|
|
21
24
|
|
|
22
25
|
if (!poses) return
|
|
23
26
|
|
|
24
27
|
const total = poses.length / STRIDE.ARROWS
|
|
25
|
-
const
|
|
26
|
-
const uniformColor =
|
|
27
|
-
colors && (colors.length === 3 || colors.length === 4)
|
|
28
|
-
? new Color(colors[0], colors[1], colors[2])
|
|
29
|
-
: undefined
|
|
28
|
+
const uniformColor = color ? colorUtil.setRGB(color.r, color.g, color.b) : undefined
|
|
30
29
|
|
|
31
|
-
const arrows = new InstancedArrows({ count: total,
|
|
30
|
+
const arrows = new InstancedArrows({ count: total, uniformColor })
|
|
32
31
|
map.set(entity, arrows)
|
|
33
32
|
arrows.update({ poses, colors, headAtPose })
|
|
34
33
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import type { InstancedArrows } from '../../../three/InstancedArrows/InstancedArrows'
|
|
8
8
|
|
|
9
|
+
import AxesHelper from '../../AxesHelper.svelte'
|
|
9
10
|
import { useEntityEvents } from '../hooks/useEntityEvents.svelte'
|
|
10
11
|
import { traits, useTrait } from '../../../ecs'
|
|
11
12
|
import { useFocusedEntity, useSelectedEntity } from '../../../hooks/useSelection.svelte'
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
|
|
21
22
|
const parent = useTrait(() => entity, traits.Parent)
|
|
22
23
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
24
|
+
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
23
25
|
|
|
24
26
|
const events = useEntityEvents(() => entity)
|
|
25
27
|
const selectedEntity = useSelectedEntity()
|
|
@@ -53,5 +55,12 @@
|
|
|
53
55
|
bvh={{ enabled: false }}
|
|
54
56
|
raycast={() => null}
|
|
55
57
|
/>
|
|
58
|
+
{#if showAxesHelper.current}
|
|
59
|
+
<AxesHelper
|
|
60
|
+
name={entity}
|
|
61
|
+
width={3}
|
|
62
|
+
length={0.1}
|
|
63
|
+
/>
|
|
64
|
+
{/if}
|
|
56
65
|
</T>
|
|
57
66
|
</Portal>
|
|
@@ -27,13 +27,23 @@
|
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Geometries from the world state API are bucketed into their own query
|
|
30
|
-
* to avoid thrashing other query results due to them being
|
|
30
|
+
* to avoid thrashing other query results due to them being streamed.
|
|
31
31
|
*/
|
|
32
32
|
const worldStateEntities = useQuery(
|
|
33
33
|
traits.WorldStateStoreAPI,
|
|
34
34
|
Or(traits.Box, traits.Capsule, traits.Sphere, traits.BufferGeometry, traits.ReferenceFrame)
|
|
35
35
|
)
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Entities from the draw service API are bucketed into their own query
|
|
39
|
+
* to avoid thrashing other query results due to them being streamed.
|
|
40
|
+
*/
|
|
41
|
+
const drawServiceEntities = useQuery(
|
|
42
|
+
traits.DrawServiceAPI,
|
|
43
|
+
Not(traits.Points, traits.LinePositions, traits.GLTF),
|
|
44
|
+
Or(traits.Box, traits.Capsule, traits.Sphere, traits.BufferGeometry, traits.ReferenceFrame)
|
|
45
|
+
)
|
|
46
|
+
|
|
37
47
|
/**
|
|
38
48
|
* All remaining meshes can be bucketed into a query due to lower frequency updates.
|
|
39
49
|
*/
|
|
@@ -41,6 +51,7 @@
|
|
|
41
51
|
Not(traits.FramesAPI),
|
|
42
52
|
Not(traits.GeometriesAPI),
|
|
43
53
|
Not(traits.WorldStateStoreAPI),
|
|
54
|
+
Not(traits.DrawServiceAPI),
|
|
44
55
|
Not(traits.Points),
|
|
45
56
|
Or(traits.Box, traits.Capsule, traits.Sphere, traits.BufferGeometry, traits.ReferenceFrame)
|
|
46
57
|
)
|
|
@@ -75,6 +86,12 @@
|
|
|
75
86
|
</Frame>
|
|
76
87
|
{/each}
|
|
77
88
|
|
|
89
|
+
{#each drawServiceEntities.current as entity (entity)}
|
|
90
|
+
<Frame {entity}>
|
|
91
|
+
<Label text={entity.get(traits.Name)} />
|
|
92
|
+
</Frame>
|
|
93
|
+
{/each}
|
|
94
|
+
|
|
78
95
|
{#each meshEntities.current as entity (entity)}
|
|
79
96
|
<Frame {entity}>
|
|
80
97
|
<Label text={entity.get(traits.Name)} />
|
|
@@ -18,6 +18,7 @@ Renders a Viam Frame object
|
|
|
18
18
|
import { Portal, PortalTarget } from '@threlte/extras'
|
|
19
19
|
import { Group, type Object3D } from 'three'
|
|
20
20
|
|
|
21
|
+
import { asColor } from '../../buffer'
|
|
21
22
|
import { colors, resourceColors } from '../../color'
|
|
22
23
|
import { traits, useTrait } from '../../ecs'
|
|
23
24
|
import { useResourceByName } from '../../hooks/useResourceByName.svelte'
|
|
@@ -39,6 +40,7 @@ Renders a Viam Frame object
|
|
|
39
40
|
|
|
40
41
|
const name = useTrait(() => entity, traits.Name)
|
|
41
42
|
const parent = useTrait(() => entity, traits.Parent)
|
|
43
|
+
const entityColors = useTrait(() => entity, traits.Colors)
|
|
42
44
|
const entityColor = useTrait(() => entity, traits.Color)
|
|
43
45
|
const entityPose = useTrait(() => entity, traits.Pose)
|
|
44
46
|
const center = useTrait(() => entity, traits.Center)
|
|
@@ -47,8 +49,12 @@ Renders a Viam Frame object
|
|
|
47
49
|
const events = useEntityEvents(() => entity)
|
|
48
50
|
|
|
49
51
|
const color = $derived.by(() => {
|
|
52
|
+
if (entityColors.current) {
|
|
53
|
+
return `#${asColor(entityColors.current, colorUtil).getHexString()}`
|
|
54
|
+
}
|
|
55
|
+
|
|
50
56
|
if (entityColor.current) {
|
|
51
|
-
return `#${colorUtil.
|
|
57
|
+
return `#${colorUtil.setRGB(entityColor.current.r, entityColor.current.g, entityColor.current.b).getHexString()}`
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
const subtype = resourceByName.current[name.current ?? '']?.subtype
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { traits, useTrait } from '../../ecs'
|
|
23
23
|
import { poseToObject3d } from '../../transform'
|
|
24
24
|
|
|
25
|
+
import AxesHelper from '../AxesHelper.svelte'
|
|
25
26
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
26
27
|
|
|
27
28
|
interface Props extends ThrelteProps<Object3D> {
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
const gltfTrait = useTrait(() => entity, traits.GLTF)
|
|
40
41
|
const scale = useTrait(() => entity, traits.Scale)
|
|
41
42
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
43
|
+
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
42
44
|
const events = useEntityEvents(() => entity)
|
|
43
45
|
|
|
44
46
|
const animationName = $derived(gltfTrait.current?.animationName)
|
|
@@ -65,7 +67,7 @@
|
|
|
65
67
|
const buffer = source.glb.buffer.slice(
|
|
66
68
|
source.glb.byteOffset,
|
|
67
69
|
source.glb.byteOffset + source.glb.byteLength
|
|
68
|
-
)
|
|
70
|
+
) as ArrayBuffer
|
|
69
71
|
$gltf = (await gltfLoader.parseAsync(buffer, '')) as ThrelteGltf
|
|
70
72
|
} else if ('gltf' in source) {
|
|
71
73
|
$gltf = source.gltf as ThrelteGltf
|
|
@@ -84,6 +86,13 @@
|
|
|
84
86
|
|
|
85
87
|
<Portal id={parent.current}>
|
|
86
88
|
<T is={group}>
|
|
89
|
+
{#if showAxesHelper.current}
|
|
90
|
+
<AxesHelper
|
|
91
|
+
name={entity}
|
|
92
|
+
width={3}
|
|
93
|
+
length={0.1}
|
|
94
|
+
/>
|
|
95
|
+
{/if}
|
|
87
96
|
{#if $gltf}
|
|
88
97
|
<T
|
|
89
98
|
is={$gltf.scene as Object3D}
|
|
@@ -95,7 +104,9 @@
|
|
|
95
104
|
>
|
|
96
105
|
{@render children?.()}
|
|
97
106
|
|
|
98
|
-
|
|
107
|
+
{#if name.current}
|
|
108
|
+
<PortalTarget id={name.current} />
|
|
109
|
+
{/if}
|
|
99
110
|
</T>
|
|
100
111
|
{/if}
|
|
101
112
|
</T>
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
import { Color } from 'three'
|
|
3
|
-
|
|
4
|
-
const colorUtil = new Color()
|
|
5
|
-
</script>
|
|
6
|
-
|
|
7
1
|
<script lang="ts">
|
|
8
2
|
import type { Entity } from 'koota'
|
|
9
3
|
import type { Snippet } from 'svelte'
|
|
@@ -12,10 +6,11 @@
|
|
|
12
6
|
import { meshBounds, Portal, PortalTarget } from '@threlte/extras'
|
|
13
7
|
import { Line2, LineMaterial } from 'three/examples/jsm/Addons.js'
|
|
14
8
|
|
|
15
|
-
import {
|
|
9
|
+
import { isVertexColors, STRIDE } from '../../buffer'
|
|
16
10
|
import { traits, useTrait } from '../../ecs'
|
|
17
11
|
import { poseToObject3d } from '../../transform'
|
|
18
12
|
|
|
13
|
+
import AxesHelper from '../AxesHelper.svelte'
|
|
19
14
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
20
15
|
import LineDots from './LineDots.svelte'
|
|
21
16
|
import LineGeometry from './LineGeometry.svelte'
|
|
@@ -32,16 +27,39 @@
|
|
|
32
27
|
const parent = useTrait(() => entity, traits.Parent)
|
|
33
28
|
const pose = useTrait(() => entity, traits.Pose)
|
|
34
29
|
const color = useTrait(() => entity, traits.Color)
|
|
35
|
-
const
|
|
30
|
+
const colors = useTrait(() => entity, traits.Colors)
|
|
31
|
+
const dotColors = useTrait(() => entity, traits.DotColors)
|
|
32
|
+
const dotSize = useTrait(() => entity, traits.DotSize)
|
|
36
33
|
const linePositions = useTrait(() => entity, traits.LinePositions)
|
|
37
34
|
const lineWidth = useTrait(() => entity, traits.LineWidth)
|
|
38
|
-
const opacity = useTrait(() => entity, traits.Opacity)
|
|
39
35
|
const materialProps = useTrait(() => entity, traits.Material)
|
|
40
36
|
const renderOrder = useTrait(() => entity, traits.RenderOrder)
|
|
37
|
+
const opacity = useTrait(() => entity, traits.Opacity)
|
|
38
|
+
const screenSpace = useTrait(() => entity, traits.ScreenSpace)
|
|
41
39
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
40
|
+
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
42
41
|
|
|
43
42
|
const events = useEntityEvents(() => entity)
|
|
44
43
|
|
|
44
|
+
const hasVertexColors = $derived(isVertexColors(colors.current))
|
|
45
|
+
|
|
46
|
+
const lineColor = $derived.by<[number, number, number]>(() => {
|
|
47
|
+
if (color.current) return [color.current.r, color.current.g, color.current.b]
|
|
48
|
+
return [0, 0, 1]
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const lineColors = $derived.by<Float32Array | undefined>(() => {
|
|
52
|
+
if (!colors.current) return undefined
|
|
53
|
+
const numColors = colors.current.length / STRIDE.COLORS_RGB
|
|
54
|
+
const rgb = new Float32Array(numColors * 3)
|
|
55
|
+
for (let i = 0; i < numColors; i++) {
|
|
56
|
+
rgb[i * 3] = colors.current[i * STRIDE.COLORS_RGB]! / 255
|
|
57
|
+
rgb[i * 3 + 1] = colors.current[i * STRIDE.COLORS_RGB + 1]! / 255
|
|
58
|
+
rgb[i * 3 + 2] = colors.current[i * STRIDE.COLORS_RGB + 2]! / 255
|
|
59
|
+
}
|
|
60
|
+
return rgb
|
|
61
|
+
})
|
|
62
|
+
|
|
45
63
|
const currentOpacity = $derived(opacity.current ?? 0.7)
|
|
46
64
|
|
|
47
65
|
const mesh = new Line2()
|
|
@@ -64,26 +82,36 @@
|
|
|
64
82
|
visible={invisible.current !== true}
|
|
65
83
|
{...events}
|
|
66
84
|
>
|
|
67
|
-
<LineGeometry
|
|
85
|
+
<LineGeometry
|
|
86
|
+
positions={linePositions.current}
|
|
87
|
+
colors={lineColors}
|
|
88
|
+
/>
|
|
68
89
|
<T
|
|
69
90
|
is={LineMaterial}
|
|
70
|
-
color={
|
|
91
|
+
color={hasVertexColors ? [1, 1, 1] : lineColor}
|
|
92
|
+
vertexColors={hasVertexColors}
|
|
71
93
|
transparent={currentOpacity < 1}
|
|
72
94
|
depthWrite={currentOpacity === 1}
|
|
73
95
|
opacity={currentOpacity}
|
|
74
|
-
|
|
96
|
+
worldUnits={!screenSpace.current}
|
|
97
|
+
linewidth={(lineWidth.current ?? 5) * (screenSpace.current ? 1 : 0.001)}
|
|
75
98
|
depthTest={materialProps.current?.depthTest ?? true}
|
|
76
99
|
/>
|
|
100
|
+
{#if showAxesHelper.current}
|
|
101
|
+
<AxesHelper
|
|
102
|
+
name={entity}
|
|
103
|
+
width={3}
|
|
104
|
+
length={0.1}
|
|
105
|
+
/>
|
|
106
|
+
{/if}
|
|
77
107
|
</T>
|
|
78
108
|
|
|
79
|
-
{#if linePositions.current &&
|
|
109
|
+
{#if linePositions.current && dotSize.current}
|
|
80
110
|
<LineDots
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
10
|
|
84
|
-
)}
|
|
111
|
+
colors={dotColors.current ?? new Uint8Array()}
|
|
112
|
+
opacity={currentOpacity}
|
|
85
113
|
positions={linePositions.current}
|
|
86
|
-
scale={
|
|
114
|
+
scale={dotSize.current * 0.001}
|
|
87
115
|
/>
|
|
88
116
|
{/if}
|
|
89
117
|
|