@viamrobotics/motion-tools 1.13.1 → 1.14.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.js +10 -2
- package/dist/buffer.d.ts +56 -7
- package/dist/buffer.js +70 -12
- package/dist/components/Entities/Entities.svelte +3 -3
- package/dist/components/Entities/Frame.svelte +42 -45
- package/dist/components/Entities/Frame.svelte.d.ts +1 -0
- package/dist/components/Entities/Geometry.svelte +43 -174
- package/dist/components/Entities/Geometry.svelte.d.ts +5 -14
- package/dist/components/Entities/Line.svelte +64 -17
- package/dist/components/Entities/Mesh.svelte +130 -0
- package/dist/components/Entities/Mesh.svelte.d.ts +4 -0
- package/dist/components/Selected.svelte +2 -0
- package/dist/components/overlay/left-pane/buildTree.js +15 -0
- package/dist/ecs/traits.d.ts +2 -19
- package/dist/ecs/traits.js +33 -6
- package/dist/hooks/use3DModels.svelte.js +1 -3
- package/dist/hooks/useFrames.svelte.js +12 -13
- package/dist/hooks/useGeometries.svelte.js +59 -36
- package/dist/hooks/usePointcloudObjects.svelte.js +103 -58
- package/dist/hooks/usePointclouds.svelte.js +48 -28
- package/dist/hooks/useWorldState.svelte.js +25 -25
- package/dist/metadata.d.ts +22 -0
- package/dist/metadata.js +66 -0
- package/dist/snapshot.d.ts +20 -0
- package/dist/snapshot.js +65 -23
- package/dist/three/OBBHelper.d.ts +3 -2
- package/dist/three/OBBHelper.js +17 -5
- package/package.json +1 -1
- package/dist/WorldObject.svelte.d.ts +0 -27
- package/dist/WorldObject.svelte.js +0 -127
package/dist/attribute.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { BufferGeometry, BufferAttribute } from 'three';
|
|
2
|
+
import { STRIDE } from './buffer';
|
|
3
|
+
const colorStride = (colors, positions) => {
|
|
4
|
+
const numVertices = positions.length / STRIDE.POSITIONS;
|
|
5
|
+
const stride = colors.length / numVertices;
|
|
6
|
+
return stride === STRIDE.COLORS_RGBA ? STRIDE.COLORS_RGBA : STRIDE.COLORS_RGB;
|
|
7
|
+
};
|
|
2
8
|
export const createBufferGeometry = (positions, colors) => {
|
|
3
9
|
const geometry = new BufferGeometry();
|
|
4
10
|
geometry.setAttribute('position', new BufferAttribute(positions, 3));
|
|
5
11
|
if (colors) {
|
|
6
|
-
|
|
12
|
+
const stride = colorStride(colors, positions);
|
|
13
|
+
geometry.setAttribute('color', new BufferAttribute(colors, stride, true));
|
|
7
14
|
}
|
|
8
15
|
return geometry;
|
|
9
16
|
};
|
|
@@ -24,7 +31,8 @@ export const updateBufferGeometry = (geometry, positions, colors) => {
|
|
|
24
31
|
colorAttr.needsUpdate = true;
|
|
25
32
|
}
|
|
26
33
|
else {
|
|
27
|
-
|
|
34
|
+
const stride = colorStride(colors, positions);
|
|
35
|
+
geometry.setAttribute('color', new BufferAttribute(colors, stride, true));
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
};
|
package/dist/buffer.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Proto messages pack float32 data as `Uint8Array` (bytes fields). These utilities
|
|
5
5
|
* provide efficient conversion to `Float32Array` for Three.js BufferAttributes.
|
|
6
6
|
*/
|
|
7
|
+
import { Color } from 'three';
|
|
7
8
|
/**
|
|
8
9
|
* Stride constants for proto binary data formats.
|
|
9
10
|
* Each value represents the number of float32 elements per item.
|
|
@@ -37,16 +38,64 @@ export declare const STRIDE: {
|
|
|
37
38
|
*/
|
|
38
39
|
export declare const asFloat32Array: (bytes: Uint8Array<ArrayBuffer>) => Float32Array<ArrayBuffer>;
|
|
39
40
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
41
|
+
* Sets a Three.js Color from 3 bytes of a uint8 color array starting at `offset`.
|
|
42
|
+
* Mutates and returns `target` — pass a pre-allocated Color to avoid allocations
|
|
43
|
+
* in hot paths.
|
|
42
44
|
*
|
|
43
|
-
* @param
|
|
44
|
-
* @
|
|
45
|
+
* @param bytes - Uint8Array with at least `offset + 3` elements [r, g, b, ...]
|
|
46
|
+
* @param target - Color instance to write into
|
|
47
|
+
* @param offset - Byte offset to start reading from (default 0)
|
|
48
|
+
* @returns The mutated `target`, or black if the array has fewer than `offset + 3` elements
|
|
45
49
|
*
|
|
46
50
|
* @example
|
|
47
51
|
* ```ts
|
|
48
|
-
*
|
|
49
|
-
*
|
|
52
|
+
* asColor(colors.current, material.color)
|
|
53
|
+
* asColor(colors.current, pointColorUtil, stride) // read second color
|
|
50
54
|
* ```
|
|
51
55
|
*/
|
|
52
|
-
export declare const
|
|
56
|
+
export declare const asColor: (bytes: Uint8Array<ArrayBuffer>, target: Color, offset?: number) => Color;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a Uint8Array from a Three.js Color.
|
|
59
|
+
*
|
|
60
|
+
* @param color - The Three.js Color to convert
|
|
61
|
+
* @returns A Uint8Array with the RGBA values
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const color = fromColor(new Color(0, 1, 0))
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare const fromColor: (color: Color) => Uint8Array<ArrayBuffer>;
|
|
69
|
+
/**
|
|
70
|
+
* Reads a byte from a uint8 color array at `offset` and normalizes it to 0-1.
|
|
71
|
+
* Returns `fallback` when the array has fewer than `offset + 1` elements.
|
|
72
|
+
*
|
|
73
|
+
* @param bytes - ArrayLike of uint8 color values
|
|
74
|
+
* @param fallback - Value to return when no alpha byte is present (default 1)
|
|
75
|
+
* @param offset - Byte index to read from (default 3, the alpha channel of the first color)
|
|
76
|
+
* @returns Normalized opacity in 0-1 range, or the fallback value
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* material.opacity = asOpacity(colors.current)
|
|
81
|
+
* material.opacity = asOpacity(colors.current, 1, stride + 3) // alpha of second color
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare const asOpacity: (bytes: Uint8Array<ArrayBuffer>, fallback?: number, offset?: number) => number;
|
|
85
|
+
/**
|
|
86
|
+
* Returns true when `colors` contains exactly one color entry per point (RGB or RGBA).
|
|
87
|
+
* Use this to distinguish per-vertex color buffers from a single uniform color.
|
|
88
|
+
*
|
|
89
|
+
* @param colors - Uint8Array of packed color bytes
|
|
90
|
+
* @param numVertex - Number of points/vertices the color buffer should cover
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* if (isPerVertexColors(colors, positions.length / STRIDE.POSITIONS)) {
|
|
95
|
+
* // treat as per-vertex
|
|
96
|
+
* } else {
|
|
97
|
+
* addColorTraits(entityTraits, colors)
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare const isPerVertexColors: (colors: Uint8Array<ArrayBuffer>, numVertex: number) => boolean;
|
package/dist/buffer.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Proto messages pack float32 data as `Uint8Array` (bytes fields). These utilities
|
|
5
5
|
* provide efficient conversion to `Float32Array` for Three.js BufferAttributes.
|
|
6
6
|
*/
|
|
7
|
+
import { Color } from 'three';
|
|
7
8
|
/**
|
|
8
9
|
* Stride constants for proto binary data formats.
|
|
9
10
|
* Each value represents the number of float32 elements per item.
|
|
@@ -50,22 +51,79 @@ export const asFloat32Array = (bytes) => {
|
|
|
50
51
|
return aligned;
|
|
51
52
|
};
|
|
52
53
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
54
|
+
* Sets a Three.js Color from 3 bytes of a uint8 color array starting at `offset`.
|
|
55
|
+
* Mutates and returns `target` — pass a pre-allocated Color to avoid allocations
|
|
56
|
+
* in hot paths.
|
|
55
57
|
*
|
|
56
|
-
* @param
|
|
57
|
-
* @
|
|
58
|
+
* @param bytes - Uint8Array with at least `offset + 3` elements [r, g, b, ...]
|
|
59
|
+
* @param target - Color instance to write into
|
|
60
|
+
* @param offset - Byte offset to start reading from (default 0)
|
|
61
|
+
* @returns The mutated `target`, or black if the array has fewer than `offset + 3` elements
|
|
58
62
|
*
|
|
59
63
|
* @example
|
|
60
64
|
* ```ts
|
|
61
|
-
*
|
|
62
|
-
*
|
|
65
|
+
* asColor(colors.current, material.color)
|
|
66
|
+
* asColor(colors.current, pointColorUtil, stride) // read second color
|
|
63
67
|
* ```
|
|
64
68
|
*/
|
|
65
|
-
export const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
export const asColor = (bytes, target, offset = 0) => {
|
|
70
|
+
if (bytes.length < offset + 3)
|
|
71
|
+
return target.setRGB(0, 0, 0);
|
|
72
|
+
return target.setRGB(bytes[offset] / 255, bytes[offset + 1] / 255, bytes[offset + 2] / 255);
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Creates a Uint8Array from a Three.js Color.
|
|
76
|
+
*
|
|
77
|
+
* @param color - The Three.js Color to convert
|
|
78
|
+
* @returns A Uint8Array with the RGBA values
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const color = fromColor(new Color(0, 1, 0))
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export const fromColor = (color) => {
|
|
86
|
+
return new Uint8Array([
|
|
87
|
+
Math.round(color.r * 255),
|
|
88
|
+
Math.round(color.g * 255),
|
|
89
|
+
Math.round(color.b * 255),
|
|
90
|
+
]);
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Reads a byte from a uint8 color array at `offset` and normalizes it to 0-1.
|
|
94
|
+
* Returns `fallback` when the array has fewer than `offset + 1` elements.
|
|
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
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* material.opacity = asOpacity(colors.current)
|
|
104
|
+
* material.opacity = asOpacity(colors.current, 1, stride + 3) // alpha of second color
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export const asOpacity = (bytes, fallback = 1, offset = 3) => {
|
|
108
|
+
if (bytes.length < offset + 1)
|
|
109
|
+
return fallback;
|
|
110
|
+
return bytes[offset] / 255;
|
|
71
111
|
};
|
|
112
|
+
/**
|
|
113
|
+
* Returns true when `colors` contains exactly one color entry per point (RGB or RGBA).
|
|
114
|
+
* Use this to distinguish per-vertex color buffers from a single uniform color.
|
|
115
|
+
*
|
|
116
|
+
* @param colors - Uint8Array of packed color bytes
|
|
117
|
+
* @param numVertex - Number of points/vertices the color buffer should cover
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* if (isPerVertexColors(colors, positions.length / STRIDE.POSITIONS)) {
|
|
122
|
+
* // treat as per-vertex
|
|
123
|
+
* } else {
|
|
124
|
+
* addColorTraits(entityTraits, colors)
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export const isPerVertexColors = (colors, numVertex) => colors.length === numVertex * STRIDE.COLORS_RGB ||
|
|
129
|
+
colors.length === numVertex * STRIDE.COLORS_RGBA;
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
import Line from './Line.svelte'
|
|
7
7
|
import Points from './Points.svelte'
|
|
8
8
|
import Arrows from './Arrows/ArrowGroups.svelte'
|
|
9
|
-
|
|
10
9
|
import { traits, useQuery } from '../../ecs'
|
|
11
10
|
import { Not, Or } from 'koota'
|
|
11
|
+
import Geometry from './Geometry.svelte'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Frames from a live machine are bucketed into their own query
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
{/each}
|
|
63
63
|
|
|
64
64
|
{#each resourceGeometriesEntities.current as entity (entity)}
|
|
65
|
-
<
|
|
65
|
+
<Geometry {entity}>
|
|
66
66
|
<Label text={entity.get(traits.Name)} />
|
|
67
|
-
</
|
|
67
|
+
</Geometry>
|
|
68
68
|
{/each}
|
|
69
69
|
|
|
70
70
|
{#each worldStateEntities.current as entity (entity)}
|
|
@@ -1,17 +1,27 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
|
|
4
|
+
Renders a Viam Frame object
|
|
5
|
+
-->
|
|
6
|
+
<script module>
|
|
7
|
+
import { Color } from 'three'
|
|
8
|
+
|
|
9
|
+
const colorUtil = new Color()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
1
12
|
<script lang="ts">
|
|
2
13
|
import type { Snippet } from 'svelte'
|
|
14
|
+
import { Group, type Object3D } from 'three'
|
|
15
|
+
import { T, useThrelte } from '@threlte/core'
|
|
16
|
+
import { Portal, PortalTarget } from '@threlte/extras'
|
|
3
17
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
7
|
-
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
8
|
-
import { use3DModels } from '../../hooks/use3DModels.svelte'
|
|
9
|
-
import { colors, darkenColor, resourceColors } from '../../color'
|
|
18
|
+
import Mesh from './Mesh.svelte'
|
|
19
|
+
import { colors, resourceColors } from '../../color'
|
|
10
20
|
import type { Entity } from 'koota'
|
|
11
21
|
import { traits, useTrait } from '../../ecs'
|
|
12
22
|
import type { Pose } from '@viamrobotics/sdk'
|
|
13
23
|
import { useResourceByName } from '../../hooks/useResourceByName.svelte'
|
|
14
|
-
import {
|
|
24
|
+
import { poseToObject3d } from '../../transform'
|
|
15
25
|
|
|
16
26
|
interface Props {
|
|
17
27
|
entity: Entity
|
|
@@ -21,69 +31,56 @@
|
|
|
21
31
|
|
|
22
32
|
let { entity, pose, children }: Props = $props()
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const colorUtil = new Color()
|
|
27
|
-
|
|
28
|
-
const settings = useSettings()
|
|
29
|
-
const componentModels = use3DModels()
|
|
30
|
-
const selectedEntity = useSelectedEntity()
|
|
34
|
+
const { invalidate } = useThrelte()
|
|
31
35
|
const resourceByName = useResourceByName()
|
|
32
36
|
|
|
33
37
|
const name = useTrait(() => entity, traits.Name)
|
|
34
38
|
const parent = useTrait(() => entity, traits.Parent)
|
|
35
39
|
const entityColor = useTrait(() => entity, traits.Color)
|
|
40
|
+
const entityPose = useTrait(() => entity, traits.Pose)
|
|
41
|
+
const center = useTrait(() => entity, traits.Center)
|
|
36
42
|
|
|
37
43
|
const events = useEntityEvents(() => entity)
|
|
38
|
-
const resourceColor = $derived.by(() => {
|
|
39
|
-
if (!name.current) {
|
|
40
|
-
return undefined
|
|
41
|
-
}
|
|
42
|
-
const subtype = resourceByName.current[name.current]?.subtype
|
|
43
|
-
return resourceColors[subtype as keyof typeof resourceColors]
|
|
44
|
-
})
|
|
45
44
|
|
|
46
45
|
const color = $derived.by(() => {
|
|
47
46
|
if (entityColor.current) {
|
|
48
|
-
return colorUtil.set(entityColor.current.r, entityColor.current.g, entityColor.current.b)
|
|
47
|
+
return `#${colorUtil.set(entityColor.current.r, entityColor.current.g, entityColor.current.b).getHexString()}`
|
|
49
48
|
}
|
|
49
|
+
|
|
50
|
+
const subtype = resourceByName.current[name.current ?? '']?.subtype
|
|
51
|
+
const resourceColor = resourceColors[subtype as keyof typeof resourceColors]
|
|
52
|
+
|
|
50
53
|
if (resourceColor) {
|
|
51
54
|
return resourceColor
|
|
52
55
|
}
|
|
56
|
+
|
|
53
57
|
return colors.default
|
|
54
58
|
})
|
|
55
59
|
|
|
56
|
-
const
|
|
57
|
-
if (!name.current) {
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
+
const group = new Group()
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
const resolvedPose = $derived(pose ?? entityPose.current)
|
|
63
|
+
$effect.pre(() => {
|
|
64
|
+
if (resolvedPose) {
|
|
65
|
+
poseToObject3d(resolvedPose, group)
|
|
66
|
+
invalidate()
|
|
64
67
|
}
|
|
65
|
-
return componentModels.current?.[componentName]?.[id].clone()
|
|
66
68
|
})
|
|
67
69
|
</script>
|
|
68
70
|
|
|
69
71
|
<Portal id={parent.current}>
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
: `#${colorUtil.set(color).getHexString()}`}
|
|
79
|
-
{...events}
|
|
80
|
-
>
|
|
72
|
+
<T is={group}>
|
|
73
|
+
<Mesh
|
|
74
|
+
{entity}
|
|
75
|
+
{color}
|
|
76
|
+
{...events}
|
|
77
|
+
center={center.current}
|
|
78
|
+
/>
|
|
79
|
+
|
|
81
80
|
{#if name.current}
|
|
82
81
|
<PortalTarget id={name.current} />
|
|
83
82
|
{/if}
|
|
84
83
|
|
|
85
|
-
{
|
|
86
|
-
|
|
87
|
-
{/if}
|
|
88
|
-
</Geometry>
|
|
84
|
+
{@render children?.({ ref: group })}
|
|
85
|
+
</T>
|
|
89
86
|
</Portal>
|
|
@@ -1,206 +1,75 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
|
|
4
|
+
Renders a Viam Geometry object
|
|
5
|
+
-->
|
|
1
6
|
<script lang="ts">
|
|
2
|
-
import { T, useThrelte
|
|
3
|
-
import { type Snippet } from 'svelte'
|
|
4
|
-
import { meshBounds } from '@threlte/extras'
|
|
5
|
-
import { BufferGeometry, Color, DoubleSide, FrontSide, Group, Mesh } from 'three'
|
|
6
|
-
import { Line2, LineMaterial } from 'three/examples/jsm/Addons.js'
|
|
7
|
-
import { CapsuleGeometry } from '../../three/CapsuleGeometry'
|
|
8
|
-
import { colors, darkenColor } from '../../color'
|
|
9
|
-
import AxesHelper from '../AxesHelper.svelte'
|
|
10
|
-
import type { Entity } from 'koota'
|
|
7
|
+
import { T, useThrelte } from '@threlte/core'
|
|
11
8
|
import { traits, useTrait } from '../../ecs'
|
|
9
|
+
import { use3DModels } from '../../hooks/use3DModels.svelte'
|
|
10
|
+
import { Portal } from '@threlte/extras'
|
|
12
11
|
import { poseToObject3d } from '../../transform'
|
|
13
|
-
import
|
|
14
|
-
import
|
|
12
|
+
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
13
|
+
import Mesh from './Mesh.svelte'
|
|
14
|
+
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
15
|
+
import type { Entity } from 'koota'
|
|
16
|
+
import type { Snippet } from 'svelte'
|
|
15
17
|
|
|
16
|
-
interface Props
|
|
18
|
+
interface Props {
|
|
17
19
|
entity: Entity
|
|
18
|
-
|
|
19
|
-
model?: Group
|
|
20
|
-
pose?: Pose
|
|
21
|
-
renderMode?: 'model' | 'colliders' | 'colliders+model'
|
|
22
|
-
ref?: Group
|
|
23
|
-
children?: Snippet<[{ ref: Group }]>
|
|
20
|
+
children?: Snippet
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
entity,
|
|
28
|
-
color: overrideColor,
|
|
29
|
-
model,
|
|
30
|
-
renderMode = 'colliders',
|
|
31
|
-
pose,
|
|
32
|
-
ref = $bindable(),
|
|
33
|
-
children,
|
|
34
|
-
...rest
|
|
35
|
-
}: Props = $props()
|
|
23
|
+
const { entity, children }: Props = $props()
|
|
36
24
|
|
|
37
|
-
const
|
|
25
|
+
const settings = useSettings()
|
|
38
26
|
|
|
39
27
|
const { invalidate } = useThrelte()
|
|
28
|
+
const models = use3DModels()
|
|
29
|
+
|
|
40
30
|
const name = useTrait(() => entity, traits.Name)
|
|
41
|
-
const
|
|
42
|
-
const opacity = useTrait(() => entity, traits.Opacity)
|
|
43
|
-
const box = useTrait(() => entity, traits.Box)
|
|
44
|
-
const capsule = useTrait(() => entity, traits.Capsule)
|
|
45
|
-
const sphere = useTrait(() => entity, traits.Sphere)
|
|
46
|
-
const bufferGeometry = useTrait(() => entity, traits.BufferGeometry)
|
|
47
|
-
const linePositions = useTrait(() => entity, traits.LinePositions)
|
|
48
|
-
const lineWidth = useTrait(() => entity, traits.LineWidth)
|
|
31
|
+
const parent = useTrait(() => entity, traits.Parent)
|
|
49
32
|
const center = useTrait(() => entity, traits.Center)
|
|
50
|
-
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
51
|
-
const materialProps = useTrait(() => entity, traits.Material)
|
|
52
|
-
const renderOrder = useTrait(() => entity, traits.RenderOrder)
|
|
53
33
|
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
if (sphere.current) return 'sphere'
|
|
58
|
-
if (bufferGeometry.current) return 'buffer'
|
|
59
|
-
if (linePositions.current) return 'line'
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
const color = $derived.by(() => {
|
|
63
|
-
if (overrideColor) {
|
|
64
|
-
return overrideColor
|
|
65
|
-
}
|
|
66
|
-
if (entityColor.current) {
|
|
67
|
-
return colorUtil
|
|
68
|
-
.setRGB(entityColor.current.r, entityColor.current.g, entityColor.current.b)
|
|
69
|
-
.getHexString()
|
|
34
|
+
const model = $derived.by(() => {
|
|
35
|
+
if (!settings.current.renderArmModels.includes('model')) {
|
|
36
|
+
return
|
|
70
37
|
}
|
|
71
|
-
return colors.default
|
|
72
|
-
})
|
|
73
38
|
|
|
74
|
-
|
|
75
|
-
ref = group
|
|
76
|
-
|
|
77
|
-
const mesh = $derived.by(() => {
|
|
78
|
-
if (geometryType === undefined) {
|
|
39
|
+
if (!name.current) {
|
|
79
40
|
return
|
|
80
41
|
}
|
|
81
42
|
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
result.raycast = meshBounds
|
|
43
|
+
const [componentName, id] = name.current.split(':')
|
|
44
|
+
if (!componentName || !id) {
|
|
45
|
+
return
|
|
86
46
|
}
|
|
87
47
|
|
|
88
|
-
return
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
$effect.pre(() => {
|
|
92
|
-
if (mesh && center.current) {
|
|
93
|
-
poseToObject3d(center.current, mesh)
|
|
94
|
-
invalidate()
|
|
95
|
-
}
|
|
48
|
+
return models.current[componentName]?.[id].clone()
|
|
96
49
|
})
|
|
97
50
|
|
|
98
|
-
const entityPose = useTrait(() => entity, traits.Pose)
|
|
99
|
-
const resolvedPose = $derived(pose ?? entityPose.current)
|
|
100
51
|
$effect.pre(() => {
|
|
101
|
-
if (
|
|
102
|
-
poseToObject3d(
|
|
52
|
+
if (model && center.current) {
|
|
53
|
+
poseToObject3d(center.current, model)
|
|
103
54
|
invalidate()
|
|
104
55
|
}
|
|
105
56
|
})
|
|
106
57
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const oncreate = (bufferGeometry: BufferGeometry) => {
|
|
110
|
-
geo = bufferGeometry
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
$effect.pre(() => {
|
|
114
|
-
if (mesh && bufferGeometry.current) {
|
|
115
|
-
mesh.geometry = bufferGeometry.current
|
|
116
|
-
oncreate(bufferGeometry.current)
|
|
117
|
-
|
|
118
|
-
return () => {
|
|
119
|
-
geo = undefined
|
|
120
|
-
mesh?.geometry?.dispose()
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
})
|
|
58
|
+
const events = useEntityEvents(() => entity)
|
|
124
59
|
</script>
|
|
125
60
|
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
>
|
|
130
|
-
{#if geometryType}
|
|
131
|
-
{#if model && renderMode.includes('model')}
|
|
132
|
-
<T is={model} />
|
|
133
|
-
{/if}
|
|
134
|
-
|
|
135
|
-
{#if !model || renderMode.includes('colliders')}
|
|
136
|
-
<T
|
|
137
|
-
is={mesh}
|
|
138
|
-
name={entity}
|
|
139
|
-
userData.name={name}
|
|
140
|
-
renderOrder={renderOrder.current}
|
|
141
|
-
>
|
|
142
|
-
{#if linePositions.current}
|
|
143
|
-
<LineGeometry positions={linePositions.current} />
|
|
144
|
-
{:else if box.current}
|
|
145
|
-
{@const { x, y, z } = box.current ?? { x: 0, y: 0, z: 0 }}
|
|
146
|
-
<T.BoxGeometry
|
|
147
|
-
args={[x * 0.001, y * 0.001, z * 0.001]}
|
|
148
|
-
{oncreate}
|
|
149
|
-
/>
|
|
150
|
-
{:else if sphere.current}
|
|
151
|
-
{@const { r } = sphere.current ?? { r: 0 }}
|
|
152
|
-
<T.SphereGeometry
|
|
153
|
-
args={[r * 0.001]}
|
|
154
|
-
{oncreate}
|
|
155
|
-
/>
|
|
156
|
-
{:else if capsule.current}
|
|
157
|
-
{@const { r, l } = capsule.current ?? { r: 0, l: 0 }}
|
|
158
|
-
<T
|
|
159
|
-
is={CapsuleGeometry}
|
|
160
|
-
args={[r * 0.001, l * 0.001]}
|
|
161
|
-
{oncreate}
|
|
162
|
-
/>
|
|
163
|
-
{/if}
|
|
164
|
-
|
|
165
|
-
{#if linePositions.current}
|
|
166
|
-
<T
|
|
167
|
-
is={LineMaterial}
|
|
168
|
-
{color}
|
|
169
|
-
width={lineWidth.current ? lineWidth.current * 0.001 : 0.5}
|
|
170
|
-
depthTest={materialProps.current?.depthTest ?? true}
|
|
171
|
-
/>
|
|
172
|
-
{:else}
|
|
173
|
-
{@const currentOpacity = opacity.current ?? 0.7}
|
|
174
|
-
<T.MeshToonMaterial
|
|
175
|
-
{color}
|
|
176
|
-
side={geometryType === 'buffer' ? DoubleSide : FrontSide}
|
|
177
|
-
transparent={currentOpacity < 1}
|
|
178
|
-
depthWrite={currentOpacity === 1}
|
|
179
|
-
opacity={currentOpacity}
|
|
180
|
-
depthTest={materialProps.current?.depthTest ?? true}
|
|
181
|
-
/>
|
|
182
|
-
|
|
183
|
-
{#if geo && (renderMode.includes('colliders') || !model)}
|
|
184
|
-
<T.LineSegments
|
|
185
|
-
raycast={() => null}
|
|
186
|
-
bvh={{ enabled: false }}
|
|
187
|
-
>
|
|
188
|
-
<T.EdgesGeometry args={[geo, 0]} />
|
|
189
|
-
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
190
|
-
</T.LineSegments>
|
|
191
|
-
{/if}
|
|
192
|
-
{/if}
|
|
193
|
-
</T>
|
|
194
|
-
{/if}
|
|
61
|
+
<Portal id={parent.current}>
|
|
62
|
+
{#if model}
|
|
63
|
+
<T is={model} />
|
|
195
64
|
{/if}
|
|
196
65
|
|
|
197
|
-
{#if
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
66
|
+
{#if settings.current.renderArmModels.includes('colliders') || !model}
|
|
67
|
+
<Mesh
|
|
68
|
+
{entity}
|
|
69
|
+
center={center.current}
|
|
70
|
+
{...events}
|
|
71
|
+
>
|
|
72
|
+
{@render children?.()}
|
|
73
|
+
</Mesh>
|
|
203
74
|
{/if}
|
|
204
|
-
|
|
205
|
-
{@render children?.({ ref: group })}
|
|
206
|
-
</T>
|
|
75
|
+
</Portal>
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import { type Props as ThrelteProps } from '@threlte/core';
|
|
2
|
-
import { type Snippet } from 'svelte';
|
|
3
|
-
import { Group } from 'three';
|
|
4
1
|
import type { Entity } from 'koota';
|
|
5
|
-
import type {
|
|
6
|
-
interface Props
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
interface Props {
|
|
7
4
|
entity: Entity;
|
|
8
|
-
|
|
9
|
-
model?: Group;
|
|
10
|
-
pose?: Pose;
|
|
11
|
-
renderMode?: 'model' | 'colliders' | 'colliders+model';
|
|
12
|
-
ref?: Group;
|
|
13
|
-
children?: Snippet<[{
|
|
14
|
-
ref: Group;
|
|
15
|
-
}]>;
|
|
5
|
+
children?: Snippet;
|
|
16
6
|
}
|
|
17
|
-
|
|
7
|
+
/** Renders a Viam Geometry object */
|
|
8
|
+
declare const Geometry: import("svelte").Component<Props, {}, "">;
|
|
18
9
|
type Geometry = ReturnType<typeof Geometry>;
|
|
19
10
|
export default Geometry;
|