u-space 0.0.0-alpha.1 → 0.0.0-alpha.2
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/README.md +2 -0
- package/docs/api-animations.md +78 -0
- package/docs/api-effects.md +118 -0
- package/docs/api-interactions.md +50 -5
- package/docs/api-managers.md +53 -2
- package/docs/api-objects.md +254 -8
- package/docs/api-plugins.md +238 -33
- package/docs/api-viewer.md +41 -6
- package/docs/getting-started.md +6 -1
- package/docs/index.md +50 -0
- package/package.json +15 -9
package/README.md
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Animations API
|
|
2
|
+
|
|
3
|
+
`u-space` provides a `Tween` class and a `tweenAnimation` helper for animating arbitrary numeric properties. Both are thin wrappers over [`@tweenjs/tween.js`](https://github.com/tweenjs/tween.js) that integrate automatically with the `Viewer` render loop.
|
|
4
|
+
|
|
5
|
+
## `tweenAnimation`
|
|
6
|
+
|
|
7
|
+
The simplest way to animate any object's properties. Returns a `Promise` that resolves when the animation completes.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { tweenAnimation } from 'u-space';
|
|
11
|
+
|
|
12
|
+
const source = { x: 0, y: 0, z: 0 };
|
|
13
|
+
|
|
14
|
+
await tweenAnimation(
|
|
15
|
+
viewer,
|
|
16
|
+
source, // mutable start state (mutated each frame)
|
|
17
|
+
{ x: 10, y: 5, z: 10 }, // target state
|
|
18
|
+
{
|
|
19
|
+
duration: 1500, // ms
|
|
20
|
+
delay: 0,
|
|
21
|
+
mode: 'Cubic.InOut',
|
|
22
|
+
repeat: false,
|
|
23
|
+
yoyo: false,
|
|
24
|
+
},
|
|
25
|
+
(current) => {
|
|
26
|
+
// Called every frame with the interpolated values
|
|
27
|
+
myObject.position.set(current.x, current.y, current.z);
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### `AnimationOptions`
|
|
33
|
+
|
|
34
|
+
| Property | Type | Default | Description |
|
|
35
|
+
| :--------- | :-------------------------- | :-------------- | :----------------------------------------------------------- |
|
|
36
|
+
| `duration` | `number` | `1000` | Duration in milliseconds. |
|
|
37
|
+
| `delay` | `number` | `0` | Start delay in milliseconds. |
|
|
38
|
+
| `mode` | `AnimationModeType` | `'Linear.None'` | Easing function. |
|
|
39
|
+
| `repeat` | `number \| boolean` | `false` | Number of extra repeats, or `true` for infinite. |
|
|
40
|
+
| `yoyo` | `boolean` | `false` | Reverse on each repeat cycle. |
|
|
41
|
+
|
|
42
|
+
### `AnimationModeType`
|
|
43
|
+
|
|
44
|
+
All standard easing modes are supported:
|
|
45
|
+
|
|
46
|
+
`Linear.None` · `Quadratic.In/Out/InOut` · `Cubic.In/Out/InOut` · `Quartic.In/Out/InOut` · `Quintic.In/Out/InOut` · `Sinusoidal.In/Out/InOut` · `Exponential.In/Out/InOut` · `Circular.In/Out/InOut` · `Elastic.In/Out/InOut` · `Back.In/Out/InOut` · `Bounce.In/Out/InOut`
|
|
47
|
+
|
|
48
|
+
## `Tween`
|
|
49
|
+
|
|
50
|
+
A lower-level class for full control. Extends the base `Tween` from `tween.js` and hooks into the `Viewer` event loop via `addEventListener('afterControlsUpdate', ...)`.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { Tween } from 'u-space';
|
|
54
|
+
|
|
55
|
+
const source = { opacity: 1 };
|
|
56
|
+
|
|
57
|
+
const tween = new Tween(viewer, source)
|
|
58
|
+
.to({ opacity: 0 }, 800)
|
|
59
|
+
.easingByMode('Sinusoidal.Out')
|
|
60
|
+
.onUpdate((s) => {
|
|
61
|
+
myMaterial.opacity = s.opacity;
|
|
62
|
+
viewer.render();
|
|
63
|
+
})
|
|
64
|
+
.onComplete(() => console.log('done'));
|
|
65
|
+
|
|
66
|
+
tween.start();
|
|
67
|
+
// tween.stop();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Methods
|
|
71
|
+
|
|
72
|
+
| Method | Description |
|
|
73
|
+
| :------------------------ | :------------------------------------------------------------------ |
|
|
74
|
+
| `easingByMode(mode)` | Convenience shorthand for `.easing(...)` using `AnimationModeType`. |
|
|
75
|
+
| `start(time?)` | Starts the tween and registers it with the viewer loop. |
|
|
76
|
+
| `stop()` | Stops the tween and unregisters it from the viewer loop. |
|
|
77
|
+
|
|
78
|
+
All other methods (`to`, `delay`, `repeat`, `yoyo`, `onUpdate`, `onComplete`, `onStop`, `onStart`) are inherited from the base `tween.js` `Tween` class.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Effects API
|
|
2
|
+
|
|
3
|
+
`u-space` provides two static effect utilities built on the Three.js Shading Language (TSL/WebGPU nodes): `MaterialEffects` for applying highlight states to objects, and `TSLEffects` for generating animated color node patterns.
|
|
4
|
+
|
|
5
|
+
## `MaterialEffects`
|
|
6
|
+
|
|
7
|
+
Static utility that applies TSL-based visual effects directly to an object's materials. Works on any `Object3D` — traverses all child meshes automatically.
|
|
8
|
+
|
|
9
|
+
### `MaterialEffects.highlight(object, options?)`
|
|
10
|
+
|
|
11
|
+
Applies a color/opacity highlight to all meshes in an object. Uses `userData` and TSL node graphs so multiple objects can share the same node graph instance with per-mesh state.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { MaterialEffects } from 'u-space';
|
|
15
|
+
|
|
16
|
+
// Highlight an object red with 50% opacity
|
|
17
|
+
MaterialEffects.highlight(myModel, {
|
|
18
|
+
enabled: true,
|
|
19
|
+
color: 0xff0000,
|
|
20
|
+
opacity: 0.5,
|
|
21
|
+
overwrite: false, // false = tint (multiply), true = replace color
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Disable the highlight
|
|
25
|
+
MaterialEffects.highlight(myModel, { enabled: false });
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### `HighlightOptions`
|
|
29
|
+
|
|
30
|
+
| Property | Type | Default | Description |
|
|
31
|
+
| :--------- | :-------------------- | :---------- | :----------------------------------------------------------------------------------- |
|
|
32
|
+
| `enabled` | `boolean` | `true` | Enables or disables the highlight effect. |
|
|
33
|
+
| `color` | `ColorRepresentation` | `0xff0000` | Highlight color. |
|
|
34
|
+
| `opacity` | `number` | `0.5` | Material opacity when highlighted. |
|
|
35
|
+
| `overwrite`| `boolean` | `false` | `false` = multiply with original color (tint); `true` = replace color entirely. |
|
|
36
|
+
|
|
37
|
+
> **Note:** `highlight` sets `material.transparent = true` on all affected meshes and injects `colorNode`/`opacityNode`. This is currently non-reversible without manually resetting those nodes.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## `TSLEffects`
|
|
42
|
+
|
|
43
|
+
Static factory that returns TSL color nodes. Assign the result to `material.colorNode` on a `NodeMaterial` to apply animated shader effects. Requires `viewer.frameloop = 'always'` for continuous animation.
|
|
44
|
+
|
|
45
|
+
### `TSLEffects.flow(parameters?)`
|
|
46
|
+
|
|
47
|
+
A directional light-sweep effect along the mesh UV X-axis — useful for roads, tubes, and flow lines.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { TSLEffects } from 'u-space';
|
|
51
|
+
|
|
52
|
+
myTubeMesh.material.colorNode = TSLEffects.flow({
|
|
53
|
+
baseColor: 0x001133,
|
|
54
|
+
flowColor: 0x00aaff,
|
|
55
|
+
speed: 1.5,
|
|
56
|
+
scale: 4.0,
|
|
57
|
+
intensity: 6.0,
|
|
58
|
+
});
|
|
59
|
+
viewer.frameloop = 'always';
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Parameters:**
|
|
63
|
+
|
|
64
|
+
| Property | Type | Default | Description |
|
|
65
|
+
| :---------- | :-------------------- | :---------- | :------------------------------------------------------ |
|
|
66
|
+
| `baseColor` | `ColorRepresentation` | `0xffffff` | Background/base color. |
|
|
67
|
+
| `flowColor` | `ColorRepresentation` | `0x00ff00` | Sweep highlight color. |
|
|
68
|
+
| `speed` | `number` | `1.0` | Animation speed (higher = faster sweep). |
|
|
69
|
+
| `scale` | `number` | `3.0` | Spatial frequency of the pattern. |
|
|
70
|
+
| `intensity` | `number` | `4.0` | Peak sharpness — higher values create a narrower beam. |
|
|
71
|
+
|
|
72
|
+
### `TSLEffects.breathe(parameters?)`
|
|
73
|
+
|
|
74
|
+
A pulsing glow effect that oscillates between two colors over time — suitable for status indicators and alerts.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
myMesh.material.colorNode = TSLEffects.breathe({
|
|
78
|
+
baseColor: 0x333333,
|
|
79
|
+
breathColor: 0x00ff88,
|
|
80
|
+
speed: 2.0,
|
|
81
|
+
intensity: 3.0,
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Parameters:**
|
|
86
|
+
|
|
87
|
+
| Property | Type | Default | Description |
|
|
88
|
+
| :------------ | :-------------------- | :--------- | :----------------------------------------------- |
|
|
89
|
+
| `baseColor` | `ColorRepresentation` | `0xffffff` | Color at the low/rest state. |
|
|
90
|
+
| `breathColor` | `ColorRepresentation` | `0x00ff00` | Color at peak brightness. |
|
|
91
|
+
| `speed` | `number` | `1.0` | Oscillation speed. |
|
|
92
|
+
| `intensity` | `number` | `2.0` | Controls how sharp the peak is. |
|
|
93
|
+
|
|
94
|
+
### `TSLEffects.fluid(parameters?)`
|
|
95
|
+
|
|
96
|
+
A noise-distorted flow effect — useful for water surfaces, plasma, or organic flowing materials.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
myPlaneMesh.material.colorNode = TSLEffects.fluid({
|
|
100
|
+
baseColor: 0x002244,
|
|
101
|
+
flowColor: 0x0066ff,
|
|
102
|
+
speed: 0.5,
|
|
103
|
+
scale: 2.0,
|
|
104
|
+
intensity: 1.5,
|
|
105
|
+
distortion: 0.3,
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Parameters:**
|
|
110
|
+
|
|
111
|
+
| Property | Type | Default | Description |
|
|
112
|
+
| :----------- | :-------------------- | :--------- | :------------------------------------------------------- |
|
|
113
|
+
| `baseColor` | `ColorRepresentation` | `0xffffff` | Base color. |
|
|
114
|
+
| `flowColor` | `ColorRepresentation` | `0x0000ff` | Fluid highlight color. |
|
|
115
|
+
| `speed` | `number` | `1.0` | Animation speed. |
|
|
116
|
+
| `scale` | `number` | `1.0` | UV scale for the noise pattern. |
|
|
117
|
+
| `intensity` | `number` | `1.0` | Sharpness of the fluid pattern. |
|
|
118
|
+
| `distortion` | `number` | `0.5` | How much the noise distorts the UV before sampling. |
|
package/docs/api-interactions.md
CHANGED
|
@@ -46,19 +46,64 @@ myBox.addEventListener('click', (eventData) => {
|
|
|
46
46
|
|
|
47
47
|
The following event types can be listened to on interactive objects:
|
|
48
48
|
|
|
49
|
-
- `click`: Fired when the pointer clicks on an object.
|
|
49
|
+
- `click`: Fired when the pointer clicks on an object (filtered: ignored after long press or large move).
|
|
50
50
|
- `dblclick`: Fired when the object is double-clicked rapidly.
|
|
51
|
+
- `contextmenu`: Fired on right-click (prevents default browser context menu).
|
|
51
52
|
- `pointerdown`: Fired when a pointer button is depressed over an object.
|
|
52
|
-
- `pointerup`: Fired when a pointer button is released
|
|
53
|
-
- `
|
|
54
|
-
- `
|
|
53
|
+
- `pointerup`: Fired when a pointer button is released over an object.
|
|
54
|
+
- `pointermove`: Fired while the pointer moves over an object. Requires `pointerMoveEventsEnabled = true`.
|
|
55
|
+
- `pointerenter`: Fired when the cursor enters the boundaries of an object. Requires `pointerMoveEventsEnabled = true`.
|
|
56
|
+
- `pointerleave`: Fired when the cursor leaves the boundaries of an object. Requires `pointerMoveEventsEnabled = true`.
|
|
55
57
|
|
|
56
58
|
### Event Propagation
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
Events bubble up the parent chain. To stop an event from continuing, call `stopPropagation()` on the event payload:
|
|
59
61
|
|
|
60
62
|
```typescript
|
|
61
63
|
myObject.addEventListener('click', (e) => {
|
|
62
64
|
e.event.stopPropagation();
|
|
63
65
|
});
|
|
64
66
|
```
|
|
67
|
+
|
|
68
|
+
## `InteractionEvent`
|
|
69
|
+
|
|
70
|
+
The event object passed to all listener callbacks under the `event` key.
|
|
71
|
+
|
|
72
|
+
### Properties
|
|
73
|
+
|
|
74
|
+
| Property | Type | Description |
|
|
75
|
+
| :-------------- | :----------------------------------------- | :---------------------------------------------------------------------------------- |
|
|
76
|
+
| `type` | `InteractionEventType` | The event type string (e.g., `'click'`). |
|
|
77
|
+
| `target` | `Object3D` | The original 3D object that triggered the event (first intersection). |
|
|
78
|
+
| `currentTarget` | `Object3D` | The current object in the bubbling chain. |
|
|
79
|
+
| `intersect` | `Intersection \| null` | Three.js raycaster intersection data: `point`, `face`, `distance`, `uv`, etc. |
|
|
80
|
+
| `originalEvent` | `PointerEvent \| MouseEvent` | The original DOM pointer/mouse event. |
|
|
81
|
+
|
|
82
|
+
### Methods
|
|
83
|
+
|
|
84
|
+
#### `stopPropagation()`
|
|
85
|
+
|
|
86
|
+
Stops the event from bubbling further up the parent hierarchy.
|
|
87
|
+
|
|
88
|
+
## `InteractionManager` API
|
|
89
|
+
|
|
90
|
+
### Properties
|
|
91
|
+
|
|
92
|
+
| Property | Type | Default | Description |
|
|
93
|
+
| :------------------------ | :---------------------------- | :------ | :----------------------------------------------------------------- |
|
|
94
|
+
| `targetObjects` | `Object3D[] \| null` | `null` | Objects to raycast against. `null` means all scene children. |
|
|
95
|
+
| `pointerMoveEventsEnabled`| `boolean` | `false` | Enables `pointermove`, `pointerenter`, `pointerleave` events. |
|
|
96
|
+
|
|
97
|
+
### Methods
|
|
98
|
+
|
|
99
|
+
#### `setCamera(camera)`
|
|
100
|
+
|
|
101
|
+
Updates the camera used for raycasting. Called automatically by `viewer.setCamera()`.
|
|
102
|
+
|
|
103
|
+
#### `dispose()`
|
|
104
|
+
|
|
105
|
+
Removes all DOM event listeners and cleans up internal state.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
viewer.interactionManager.dispose();
|
|
109
|
+
```
|
package/docs/api-managers.md
CHANGED
|
@@ -48,7 +48,58 @@ sedans.forEach((vehicle) => {
|
|
|
48
48
|
});
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
#### `getByType(type: string)`
|
|
52
|
+
|
|
53
|
+
Returns a `Set<Object3D>` of all registered objects whose `object.type` matches `type`.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const models = viewer.objectManager.getByType('Model');
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### `getObjectIds(object: Object3D)`
|
|
60
|
+
|
|
61
|
+
Returns a `Set<string>` of all IDs registered for a given object.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const ids = viewer.objectManager.getObjectIds(myModel);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Removing Objects
|
|
68
|
+
|
|
69
|
+
#### `remove(object: Object3D)`
|
|
70
|
+
|
|
71
|
+
Removes an object and all its associated IDs from all internal maps.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
viewer.objectManager.remove(myModel);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### `removeById(id: string)`
|
|
78
|
+
|
|
79
|
+
Removes the object registered under the given ID.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
viewer.objectManager.removeById('my-unique-car-id');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### `removeByName(name: string)`
|
|
86
|
+
|
|
87
|
+
Removes all objects with the given `.name`.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
viewer.objectManager.removeByName('sedan');
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### `removeByType(type: string)`
|
|
94
|
+
|
|
95
|
+
Removes all objects with the given `.type`.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
viewer.objectManager.removeByType('Model');
|
|
99
|
+
```
|
|
100
|
+
|
|
51
101
|
### Utility Methods
|
|
52
102
|
|
|
53
|
-
- `getAll()`: Returns all tracked objects.
|
|
54
|
-
- `
|
|
103
|
+
- `getAll()`: Returns a `Set<Object3D>` of all tracked objects.
|
|
104
|
+
- `clear()`: Removes all objects from all internal maps.
|
|
105
|
+
- `size`: Returns the total number of unique objects currently tracked by the manager.
|
package/docs/api-objects.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
`u-space` provides several object wrappers that make manipulating and loading 3D assets easier, primarily extending Three.js's basic nodes.
|
|
4
4
|
|
|
5
|
+
## Base Classes
|
|
6
|
+
|
|
7
|
+
### `BaseMesh`
|
|
8
|
+
|
|
9
|
+
Extends `THREE.Mesh`. All primitive mesh classes in `u-space` inherit from this.
|
|
10
|
+
|
|
11
|
+
**Key property:**
|
|
12
|
+
|
|
13
|
+
| Property | Type | Default | Description |
|
|
14
|
+
| :--------------------------- | :-------- | :------ | :------------------------------------------------------------------------------ |
|
|
15
|
+
| `ignoreInvisibleWhenRaycast` | `boolean` | `true` | When `true`, invisible meshes are skipped during raycasting (no hit detection). |
|
|
16
|
+
|
|
17
|
+
### `BaseGroup`
|
|
18
|
+
|
|
19
|
+
Extends `THREE.Group`. `Model` and `Topology` inherit from this.
|
|
20
|
+
|
|
21
|
+
**Key property:**
|
|
22
|
+
|
|
23
|
+
| Property | Type | Default | Description |
|
|
24
|
+
| :--------------------------- | :-------- | :------ | :------------------------------------------------------------------------------- |
|
|
25
|
+
| `ignoreInvisibleWhenRaycast` | `boolean` | `true` | When `true`, invisible groups are skipped during raycasting (no hit detection). |
|
|
26
|
+
|
|
5
27
|
## Models
|
|
6
28
|
|
|
7
29
|
The `Model` class extends `BaseGroup` (which in turn extends `THREE.Group`) and simplifies the process of asynchronously loading external 3D models like `glb` and `gltf` files. It features built-in support for different caching layers.
|
|
@@ -53,13 +75,237 @@ You can manually clear the internal caches using static methods on the `Model` c
|
|
|
53
75
|
|
|
54
76
|
## Meshes
|
|
55
77
|
|
|
56
|
-
`u-space` offers a variety of streamlined Mesh classes extending `BaseMesh`.
|
|
78
|
+
`u-space` offers a variety of streamlined Mesh classes extending `BaseMesh`. All use `MeshStandardNodeMaterial` by default, accept a `{ geometryParameters, materialParameters }` constructor shape, and support interaction event dispatching.
|
|
79
|
+
|
|
80
|
+
### `SphereMesh`
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { SphereMesh } from 'u-space';
|
|
84
|
+
|
|
85
|
+
const sphere = new SphereMesh({
|
|
86
|
+
geometryParameters: { radius: 1, widthSegments: 32, heightSegments: 32 },
|
|
87
|
+
materialParameters: { color: 0x0077ff },
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**`SphereMeshParameters`**
|
|
92
|
+
|
|
93
|
+
| Property | Type | Description |
|
|
94
|
+
| :-------------------- | :---------------------------------- | :--------------------------------------- |
|
|
95
|
+
| `geometryParameters` | `SphereGeometry` constructor params | `radius`, `widthSegments`, `heightSegments`, etc. |
|
|
96
|
+
| `materialParameters` | `MeshStandardNodeMaterialParameters`| Standard material options (color, etc.). |
|
|
97
|
+
|
|
98
|
+
### `PlaneMesh`
|
|
99
|
+
|
|
100
|
+
A flat horizontal plane.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { PlaneMesh } from 'u-space';
|
|
104
|
+
|
|
105
|
+
const plane = new PlaneMesh({
|
|
106
|
+
geometryParameters: { width: 10, height: 10 },
|
|
107
|
+
materialParameters: { color: 0x888888 },
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `CircleMesh`
|
|
112
|
+
|
|
113
|
+
A flat circle.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { CircleMesh } from 'u-space';
|
|
117
|
+
|
|
118
|
+
const circle = new CircleMesh({
|
|
119
|
+
geometryParameters: { radius: 5, segments: 64 },
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `TubeMesh`
|
|
124
|
+
|
|
125
|
+
A tube along a given `Curve<Vector3>`.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { TubeMesh } from 'u-space';
|
|
129
|
+
import { CatmullRomCurve3, Vector3 } from 'three/webgpu';
|
|
130
|
+
|
|
131
|
+
const path = new CatmullRomCurve3([new Vector3(0,0,0), new Vector3(5,2,5)]);
|
|
132
|
+
const tube = new TubeMesh({
|
|
133
|
+
geometryParameters: { path, tubularSegments: 20, radius: 0.2, radialSegments: 8 },
|
|
134
|
+
materialParameters: { color: 0x00ff00 },
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### `ShapeMesh`
|
|
139
|
+
|
|
140
|
+
A flat mesh built from a `THREE.Shape` or from 2D points.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { ShapeMesh } from 'u-space';
|
|
144
|
+
|
|
145
|
+
// From an explicit shape
|
|
146
|
+
const mesh = new ShapeMesh({ geometryParameters: { shape: myShape } });
|
|
147
|
+
|
|
148
|
+
// Static helper: from x/z point array
|
|
149
|
+
const mesh2 = ShapeMesh.createFromPoints([{ x: 0, z: 0 }, { x: 5, z: 0 }, { x: 5, z: 5 }]);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `ExtrudeMesh`
|
|
153
|
+
|
|
154
|
+
An extruded 3D solid from a `THREE.Shape` or from 2D points.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { ExtrudeMesh } from 'u-space';
|
|
158
|
+
|
|
159
|
+
const solid = new ExtrudeMesh({
|
|
160
|
+
geometryParameters: {
|
|
161
|
+
shape: myShape,
|
|
162
|
+
options: { depth: 3, bevelEnabled: false },
|
|
163
|
+
},
|
|
164
|
+
materialParameters: { color: 0xff8800 },
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Static helper
|
|
168
|
+
const solid2 = ExtrudeMesh.createFromPoints(
|
|
169
|
+
[{ x: 0, z: 0 }, { x: 5, z: 0 }, { x: 5, z: 5 }],
|
|
170
|
+
{ geometryParameters: { options: { depth: 2, bevelEnabled: false } } }
|
|
171
|
+
);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Poi
|
|
175
|
+
|
|
176
|
+
`Poi` is a canvas-rendered billboard (sprite) used for placing icons and labels in the 3D scene. It extends `BaseSprite`.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { Poi } from 'u-space';
|
|
180
|
+
|
|
181
|
+
const poi = new Poi({
|
|
182
|
+
img: '/icons/marker.png',
|
|
183
|
+
text: 'My Location',
|
|
184
|
+
fontSize: 28,
|
|
185
|
+
color: '#ffffff',
|
|
186
|
+
backgroundColor: 'rgba(0,0,0,0.6)',
|
|
187
|
+
textPosition: 'right',
|
|
188
|
+
});
|
|
189
|
+
await poi.updateAsync(); // render the canvas texture
|
|
190
|
+
|
|
191
|
+
poi.position.set(10, 5, 10);
|
|
192
|
+
viewer.scene.add(poi);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### `PoiParameters`
|
|
196
|
+
|
|
197
|
+
| Property | Type | Default | Description |
|
|
198
|
+
| :---------------- | :------------------------------------------ | :----------------------- | :------------------------------------------------ |
|
|
199
|
+
| `img` | `string \| CanvasImageSource` | `''` | Icon image URL or element. |
|
|
200
|
+
| `text` | `string` | `''` | Label text. |
|
|
201
|
+
| `fontSize` | `number` | `32` | Font size in pixels. |
|
|
202
|
+
| `fontFamily` | `string` | `'Arial'` | Font family. |
|
|
203
|
+
| `color` | `string` | `'#ffffff'` | Text color. |
|
|
204
|
+
| `iconSize` | `number` | `64` | Icon size in pixels. |
|
|
205
|
+
| `padding` | `number` | `10` | Padding around content. |
|
|
206
|
+
| `backgroundColor` | `string` | `'rgba(0, 0, 0, 0.5)'` | Background fill color. |
|
|
207
|
+
| `borderRadius` | `number` | `8` | Background border radius. |
|
|
208
|
+
| `textPosition` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'right'` | Text position relative to the icon. |
|
|
209
|
+
|
|
210
|
+
### Methods
|
|
211
|
+
|
|
212
|
+
#### `updateAsync(parameters?)`
|
|
213
|
+
|
|
214
|
+
Re-renders the canvas texture with optional parameter overrides.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
await poi.updateAsync({ text: 'Updated label', color: '#ffff00' });
|
|
218
|
+
viewer.render();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### `dispose()`
|
|
222
|
+
|
|
223
|
+
Disposes the canvas texture and material.
|
|
224
|
+
|
|
225
|
+
## Topology
|
|
226
|
+
|
|
227
|
+
`Topology` is a graph data structure with built-in 3D visualization. It stores nodes (positions) and weighted edges, implements Dijkstra's shortest-path algorithm, and renders the graph as spheres and tubes.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { Topology } from 'u-space';
|
|
231
|
+
|
|
232
|
+
const topo = new Topology({
|
|
233
|
+
nodeColor: 0x0000ff,
|
|
234
|
+
nodeRadius: 0.3,
|
|
235
|
+
edgeColor: 0x00ff00,
|
|
236
|
+
edgeRadius: 0.05,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
topo.addNode('A', new Vector3(0, 0, 0));
|
|
240
|
+
topo.addNode('B', new Vector3(5, 0, 0));
|
|
241
|
+
topo.addNode('C', new Vector3(5, 0, 5));
|
|
242
|
+
|
|
243
|
+
topo.addEdge('A', 'B');
|
|
244
|
+
topo.addEdge('B', 'C');
|
|
245
|
+
|
|
246
|
+
topo.renderGraph(); // Creates sphere + tube meshes
|
|
247
|
+
viewer.scene.add(topo);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### `TopologyParameters`
|
|
251
|
+
|
|
252
|
+
| Property | Type | Default | Description |
|
|
253
|
+
| :------------ | :------------------- | :---------- | :------------------------------ |
|
|
254
|
+
| `nodeColor` | `ColorRepresentation`| `0x0000ff` | Color of node spheres. |
|
|
255
|
+
| `nodeRadius` | `number` | `0.5` | Radius of node spheres. |
|
|
256
|
+
| `edgeColor` | `ColorRepresentation`| `0x00ff00` | Color of edge tubes. |
|
|
257
|
+
| `edgeRadius` | `number` | `0.1` | Radius of edge tubes. |
|
|
258
|
+
| `pathColor` | `ColorRepresentation`| `0xff00ff` | Color used for path visualization. |
|
|
259
|
+
| `pathRadius` | `number` | `0.2` | Radius of path tubes. |
|
|
260
|
+
|
|
261
|
+
### Methods
|
|
262
|
+
|
|
263
|
+
#### `addNode(id, position)`
|
|
264
|
+
|
|
265
|
+
Adds a node to the graph.
|
|
266
|
+
|
|
267
|
+
#### `removeNode(id)`
|
|
268
|
+
|
|
269
|
+
Removes a node and its associated edges.
|
|
270
|
+
|
|
271
|
+
#### `addEdge(from, to, weight?, bidirectional?)`
|
|
272
|
+
|
|
273
|
+
Adds an edge between two nodes. `weight` defaults to Euclidean distance. `bidirectional` defaults to `true`.
|
|
274
|
+
|
|
275
|
+
#### `removeEdge(from, to, bidirectional?)`
|
|
276
|
+
|
|
277
|
+
Removes an edge between two nodes.
|
|
278
|
+
|
|
279
|
+
#### `getShortestPath(startId, endId): Vector3[]`
|
|
280
|
+
|
|
281
|
+
Returns the shortest path as an array of world-space positions using Dijkstra's algorithm. Returns `[]` if no path exists.
|
|
282
|
+
|
|
283
|
+
#### `renderGraph()`
|
|
284
|
+
|
|
285
|
+
Builds the sphere/tube scene graph from current nodes and edges. Call this after modifying the graph to refresh the visualization.
|
|
286
|
+
|
|
287
|
+
#### `clearGraph()`
|
|
288
|
+
|
|
289
|
+
Removes and disposes all graph meshes.
|
|
290
|
+
|
|
291
|
+
#### `renderPath(points, color?): TubeMesh`
|
|
292
|
+
|
|
293
|
+
Renders a smoothed path (CatmullRomCurve3) through the given points as a tube mesh.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
const path = topo.getShortestPath('A', 'C');
|
|
297
|
+
topo.renderPath(path, 0xff0000);
|
|
298
|
+
viewer.render();
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
#### `clearPaths()`
|
|
302
|
+
|
|
303
|
+
Removes and disposes all path meshes.
|
|
304
|
+
|
|
305
|
+
#### `getNeighbors(id): Map<string, number> | undefined`
|
|
306
|
+
|
|
307
|
+
Returns the adjacency map for a node (neighbor ID → edge weight).
|
|
57
308
|
|
|
58
|
-
|
|
59
|
-
- `ExtrudeMesh`
|
|
60
|
-
- `PlaneMesh`
|
|
61
|
-
- `ShapeMesh`
|
|
62
|
-
- `SphereMesh`
|
|
63
|
-
- `TubeMesh`
|
|
309
|
+
#### `dispose()`
|
|
64
310
|
|
|
65
|
-
|
|
311
|
+
Clears graph and path meshes.
|
package/docs/api-plugins.md
CHANGED
|
@@ -14,90 +14,295 @@ import { KeyboardControls, ACTION } from 'u-space/plugins/keyboard-controls';
|
|
|
14
14
|
const keyboardControls = new KeyboardControls(viewer);
|
|
15
15
|
|
|
16
16
|
// Optional: Customize movement speeds
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
keyboardControls.moveDistanceDelta = 0.5;
|
|
18
|
+
keyboardControls.rotateAngleDelta = (Math.PI / 180) * 2;
|
|
19
19
|
|
|
20
20
|
// Activate the listeners
|
|
21
21
|
keyboardControls.enable();
|
|
22
|
+
// Later:
|
|
23
|
+
keyboardControls.disable();
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Default key bindings** (`keyboardControls.keys`):
|
|
27
|
+
|
|
28
|
+
| Key | Action |
|
|
29
|
+
| :--------- | :---------------- |
|
|
30
|
+
| `W` | Move forward |
|
|
31
|
+
| `S` | Move backward |
|
|
32
|
+
| `A` | Move left |
|
|
33
|
+
| `D` | Move right |
|
|
34
|
+
| `Q` | Move up |
|
|
35
|
+
| `E` | Move down |
|
|
36
|
+
| `ArrowLeft` | Rotate left |
|
|
37
|
+
| `ArrowRight` | Rotate right |
|
|
38
|
+
| `ArrowUp` | Rotate up |
|
|
39
|
+
| `ArrowDown` | Rotate down |
|
|
40
|
+
|
|
41
|
+
Rebind any key by overwriting the `keys` map with an `ACTION` constant:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { ACTION } from 'u-space/plugins/keyboard-controls';
|
|
45
|
+
keyboardControls.keys['Space'] = ACTION.MOVE_UP;
|
|
22
46
|
```
|
|
23
47
|
|
|
24
48
|
### `minimap`
|
|
25
49
|
|
|
26
|
-
Generates a
|
|
50
|
+
Generates a 2D minimap overlay that tracks a target object within the 3D scene. Renders into an `<canvas>` element injected into `viewer.el`.
|
|
27
51
|
|
|
28
52
|
```typescript
|
|
29
53
|
import { Minimap } from 'u-space/plugins/minimap';
|
|
30
54
|
|
|
31
55
|
const minimap = new Minimap(viewer);
|
|
32
|
-
minimap.target = myCharacterModel;
|
|
33
|
-
minimap.setSize(
|
|
56
|
+
minimap.target = myCharacterModel; // Object3D to track and display
|
|
57
|
+
minimap.setSize(300, 300); // Width and height in pixels
|
|
34
58
|
|
|
35
|
-
//
|
|
36
|
-
minimap.scene.background = new THREE.Color(
|
|
59
|
+
// Optionally style the minimap scene
|
|
60
|
+
minimap.scene.background = new THREE.Color(0x111111);
|
|
37
61
|
|
|
38
62
|
minimap.enable();
|
|
63
|
+
// Later:
|
|
64
|
+
minimap.disable();
|
|
65
|
+
minimap.dispose();
|
|
39
66
|
```
|
|
40
67
|
|
|
68
|
+
**Properties:**
|
|
69
|
+
|
|
70
|
+
| Property | Type | Description |
|
|
71
|
+
| :------------ | :-------------------- | :--------------------------------------------------- |
|
|
72
|
+
| `target` | `Object3D \| null` | The object to center the minimap on. |
|
|
73
|
+
| `scene` | `Scene` | The minimap's internal Three.js scene. |
|
|
74
|
+
| `camera` | `OrthographicCamera` | The orthographic top-down camera. |
|
|
75
|
+
| `marker` | `Object3D` | Arrow mesh showing the main camera position/heading. |
|
|
76
|
+
| `needsUpdate` | `boolean` | Set to `true` to force a minimap re-render. |
|
|
77
|
+
|
|
78
|
+
**Methods:**
|
|
79
|
+
|
|
80
|
+
- `setSize(width, height)` — Resize the minimap canvas and camera frustum.
|
|
81
|
+
- `enable()` — Appends the canvas to `viewer.el` and starts rendering.
|
|
82
|
+
- `disable()` — Removes the canvas and stops rendering.
|
|
83
|
+
- `dispose()` — Disables and cleans up all resources.
|
|
84
|
+
|
|
41
85
|
### `tiles`
|
|
42
86
|
|
|
43
|
-
Provides integration with `3d-tiles-renderer` and geospatial data
|
|
87
|
+
Provides integration with `3d-tiles-renderer` and geospatial data. The main export is `ArcgisTilesRenderer`, which streams ArcGIS Online 3D tiles and re-orients the globe to a specific geographic location.
|
|
44
88
|
|
|
45
89
|
```typescript
|
|
46
90
|
import { ArcgisTilesRenderer } from 'u-space/plugins/tiles';
|
|
47
91
|
|
|
48
92
|
const arcgisTilesRenderer = new ArcgisTilesRenderer(viewer);
|
|
49
93
|
|
|
50
|
-
//
|
|
94
|
+
// Set origin to longitude, latitude, altitude
|
|
51
95
|
arcgisTilesRenderer.invalidate(120.002269, 30.284849, 4);
|
|
96
|
+
|
|
97
|
+
// Tiles stream continuously — use always mode
|
|
98
|
+
viewer.frameloop = 'always';
|
|
99
|
+
|
|
52
100
|
arcgisTilesRenderer.enable();
|
|
53
101
|
```
|
|
54
102
|
|
|
103
|
+
**Methods:**
|
|
104
|
+
|
|
105
|
+
| Method | Description |
|
|
106
|
+
| :----------------------------- | :---------------------------------------------------------------------------------- |
|
|
107
|
+
| `invalidate(lon, lat, alt)` | Sets the tile origin to the given WGS84 coordinates (degrees). Can be called multiple times. Returns an unsubscribe function. |
|
|
108
|
+
| `enable()` | Adds tiles to the scene and starts the update loop. |
|
|
109
|
+
| `disable()` | Removes tiles from the scene and pauses the update loop. |
|
|
110
|
+
| `dispose()` | Disables and fully disposes the tile renderer. |
|
|
111
|
+
|
|
55
112
|
### `u-manager`
|
|
56
113
|
|
|
57
|
-
`u-manager` is a comprehensive suite of
|
|
114
|
+
`u-manager` is a comprehensive suite of loaders and parsers for streaming, decrypting, and displaying structured scene data from a server path. Supports scenes, topologies, animations, properties, and camera viewpoints.
|
|
58
115
|
|
|
59
|
-
|
|
116
|
+
All loaders extend Three.js `Loader` and expose a `setPath(path)` method to configure the base data directory before calling `loadAsync()`.
|
|
60
117
|
|
|
61
|
-
`
|
|
118
|
+
#### `SceneLoader`
|
|
62
119
|
|
|
63
|
-
|
|
64
|
-
import { SceneLoader, TopologiesLoader } from 'u-space/plugins/u-manager';
|
|
120
|
+
Loads the full scene tree (models, groups, shapes, extruded areas) from a server-side scene package. Automatically registers all loaded objects into `viewer.objectManager` by `id` and `sid`.
|
|
65
121
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
topologiesLoader.setPath('./scenes/my-scene');
|
|
69
|
-
const topologies = await topologiesLoader.loadAsync();
|
|
70
|
-
viewer.scene.add(...topologies);
|
|
122
|
+
```typescript
|
|
123
|
+
import { SceneLoader } from 'u-space/plugins/u-manager';
|
|
71
124
|
|
|
72
|
-
// Comprehensive Scene loader
|
|
73
125
|
const sceneLoader = new SceneLoader(viewer);
|
|
74
126
|
sceneLoader.setPath('./scenes/my-scene');
|
|
127
|
+
sceneLoader.setKey('YOUR_LICENSE_KEY'); // required for OFFICIAL authority scenes
|
|
75
128
|
const group = await sceneLoader.loadAsync();
|
|
76
129
|
viewer.scene.add(group);
|
|
77
130
|
```
|
|
78
131
|
|
|
79
|
-
|
|
132
|
+
**Methods:**
|
|
133
|
+
|
|
134
|
+
| Method | Description |
|
|
135
|
+
| :----------------- | :---------------------------------------------------------------------- |
|
|
136
|
+
| `setKey(key)` | Sets the RSA decryption key for licensed scenes. |
|
|
137
|
+
| `loadAsync()` | Loads and parses the scene. Returns a `Group` with the full hierarchy. |
|
|
138
|
+
| `clearCache()` | Removes all IDs registered by this loader from `objectManager`. |
|
|
139
|
+
| `dispose()` | Clears cache and disposes the watermark overlay. |
|
|
80
140
|
|
|
81
|
-
|
|
141
|
+
#### `TopologiesLoader` / `TopologyParser`
|
|
142
|
+
|
|
143
|
+
Loads topology graph data and converts it into `Topology` objects.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { TopologiesLoader } from 'u-space/plugins/u-manager';
|
|
147
|
+
|
|
148
|
+
const loader = new TopologiesLoader();
|
|
149
|
+
loader.setPath('./scenes/my-scene');
|
|
150
|
+
const topologies = await loader.loadAsync(); // Topology[]
|
|
151
|
+
viewer.scene.add(...topologies);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### `VisionsLoader` / `VisionsParser`
|
|
155
|
+
|
|
156
|
+
Loads named camera viewpoints and flies the camera to them.
|
|
82
157
|
|
|
83
158
|
```typescript
|
|
84
159
|
import { VisionsLoader, VisionsParser } from 'u-space/plugins/u-manager';
|
|
85
160
|
|
|
86
|
-
|
|
87
|
-
const visionsLoader = new VisionsLoader(viewer);
|
|
161
|
+
const visionsLoader = new VisionsLoader();
|
|
88
162
|
visionsLoader.setPath('./scenes/my-scene');
|
|
89
|
-
const
|
|
163
|
+
const visionsData = await visionsLoader.loadAsync();
|
|
164
|
+
// visionsData is a Record<string, IVisions[]>
|
|
90
165
|
|
|
91
|
-
// Parse and execute camera movement
|
|
92
166
|
const visionsParser = new VisionsParser(viewer);
|
|
93
|
-
|
|
94
|
-
|
|
167
|
+
|
|
168
|
+
// Fly to a specific viewpoint
|
|
169
|
+
await visionsParser.flyTo(visionsData['HOME'][0]);
|
|
170
|
+
|
|
171
|
+
// Fly to the primary (default) viewpoint
|
|
172
|
+
await visionsParser.flyToPrimary(visionsData['HOME']);
|
|
95
173
|
```
|
|
96
174
|
|
|
97
|
-
|
|
175
|
+
**`IVisions` fields:**
|
|
176
|
+
|
|
177
|
+
| Field | Type | Description |
|
|
178
|
+
| :--------- | :------------ | :----------------------------------------- |
|
|
179
|
+
| `camera` | `'P' \| 'O'` | Camera type: perspective or orthographic. |
|
|
180
|
+
| `position` | `IVector3` | Camera world position. |
|
|
181
|
+
| `target` | `IVector3` | Camera look-at target. |
|
|
182
|
+
| `zoom` | `number` | Camera zoom level. |
|
|
183
|
+
| `primary` | `boolean` | Whether this is the default viewpoint. |
|
|
184
|
+
|
|
185
|
+
#### `AnimationsLoader` / `AnimationsParser`
|
|
186
|
+
|
|
187
|
+
Loads keyframe animation data and drives `Object3D` transforms via `tweenAnimation`.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { AnimationsLoader, AnimationsParser } from 'u-space/plugins/u-manager';
|
|
191
|
+
|
|
192
|
+
const animLoader = new AnimationsLoader();
|
|
193
|
+
animLoader.setPath('./scenes/my-scene');
|
|
194
|
+
const animationsData = await animLoader.loadAsync(); // IAnimations[]
|
|
195
|
+
|
|
196
|
+
// Find the animation for a specific object
|
|
197
|
+
const data = animationsData.find((a) => a.modelId === myModel.userData.id);
|
|
98
198
|
|
|
99
|
-
|
|
199
|
+
const parser = new AnimationsParser(viewer, myModel);
|
|
200
|
+
parser.initTransform(); // save initial position/rotation/scale
|
|
100
201
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
202
|
+
await parser.play(data.keyframes); // plays the sequence
|
|
203
|
+
|
|
204
|
+
// Stop mid-way
|
|
205
|
+
parser.stop();
|
|
206
|
+
|
|
207
|
+
// Reset to initial transform
|
|
208
|
+
parser.reset();
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### `PropertiesLoader`
|
|
212
|
+
|
|
213
|
+
Loads structured property metadata associated with models (e.g., BIM attributes).
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { PropertiesLoader } from 'u-space/plugins/u-manager';
|
|
217
|
+
|
|
218
|
+
const propsLoader = new PropertiesLoader();
|
|
219
|
+
propsLoader.setPath('./scenes/my-scene');
|
|
220
|
+
const properties = await propsLoader.loadAsync(); // IProperties[]
|
|
221
|
+
|
|
222
|
+
// Look up properties for a model
|
|
223
|
+
const modelProps = properties.filter(p => p.modelId === myModel.userData.id);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**`IProperties` fields:**
|
|
227
|
+
|
|
228
|
+
| Field | Type | Description |
|
|
229
|
+
| :-------- | :-------------- | :-------------------------------- |
|
|
230
|
+
| `modelId` | `string` | ID of the associated model. |
|
|
231
|
+
| `group` | `string` | Property group/category name. |
|
|
232
|
+
| `key` | `string` | Property key. |
|
|
233
|
+
| `value` | `string \| null`| Property value. |
|
|
234
|
+
| `label` | `string \| null`| Display label for the property. |
|
|
235
|
+
|
|
236
|
+
### `curve-movement`
|
|
237
|
+
|
|
238
|
+
Animates a camera or object along a spline path. Two concrete subclasses are provided: `CurveMovementCamera` and `CurveMovementObject`.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { CurveMovementObject } from 'u-space/plugins/curve-movement';
|
|
242
|
+
import { Vector3 } from 'three/webgpu';
|
|
243
|
+
|
|
244
|
+
const movement = new CurveMovementObject(viewer, myModel);
|
|
245
|
+
movement.setFromPoints([
|
|
246
|
+
new Vector3(0, 0, 0),
|
|
247
|
+
new Vector3(10, 2, 0),
|
|
248
|
+
new Vector3(20, 0, 10),
|
|
249
|
+
]);
|
|
250
|
+
movement.speed = 0.05; // progress per second
|
|
251
|
+
movement.loop = 'repeat'; // 'once' | 'repeat' | 'pingpong'
|
|
252
|
+
movement.autoLookAt = true;
|
|
253
|
+
|
|
254
|
+
movement.play();
|
|
255
|
+
// movement.pause() / movement.resume() / movement.stop()
|
|
256
|
+
|
|
257
|
+
// Listen for events
|
|
258
|
+
movement.addEventListener('update', ({ progress }) => console.log(progress));
|
|
259
|
+
movement.addEventListener('complete', () => console.log('done'));
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**`CurveMovement` properties:**
|
|
263
|
+
|
|
264
|
+
| Property | Type | Default | Description |
|
|
265
|
+
| :-------------- | :-------------------------------- | :-------- | :------------------------------------------- |
|
|
266
|
+
| `path` | `Curve<Vector3> \| null` | `null` | The spline path. |
|
|
267
|
+
| `progress` | `number` | `0` | Current normalized progress (0–1). |
|
|
268
|
+
| `speed` | `number` | `0.1` | Progress units per second. |
|
|
269
|
+
| `loop` | `'once' \| 'repeat' \| 'pingpong'`| `'once'` | Looping behavior. |
|
|
270
|
+
| `autoLookAt` | `boolean` | `true` | Face the path tangent direction. |
|
|
271
|
+
| `lookAtOffset` | `number` | `0` | Y-axis rotation offset in radians. |
|
|
272
|
+
| `positionOffset`| `Vector3` | `(0,0,0)` | World-space offset added to each position. |
|
|
273
|
+
| `direction` | `1 \| -1` | `1` | Current travel direction. |
|
|
274
|
+
|
|
275
|
+
### `tracking-controls`
|
|
276
|
+
|
|
277
|
+
Makes the camera smoothly follow a moving `Object3D` target.
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
import { TrackingControls } from 'u-space/plugins/tracking-controls';
|
|
281
|
+
|
|
282
|
+
const tracking = new TrackingControls(viewer);
|
|
283
|
+
tracking.target = myMovingObject;
|
|
284
|
+
tracking.type = 'box3'; // 'position' (world origin) or 'box3' (bounding box center)
|
|
285
|
+
tracking.offset.set(0, 5, 0); // camera target offset
|
|
286
|
+
|
|
287
|
+
tracking.enable();
|
|
288
|
+
// tracking.disable();
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Properties:**
|
|
292
|
+
|
|
293
|
+
| Property | Type | Default | Description |
|
|
294
|
+
| :------- | :---------------------- | :----------- | :-------------------------------------------------------------------- |
|
|
295
|
+
| `target` | `Object3D \| null` | `null` | The object to track. |
|
|
296
|
+
| `type` | `'position' \| 'box3'` | `'position'` | Whether to track world position or bounding-box center. |
|
|
297
|
+
| `offset` | `Vector3` | `(0,0,0)` | Offset applied to the tracked position before moving the camera. |
|
|
298
|
+
|
|
299
|
+
### `atmosphere`
|
|
300
|
+
|
|
301
|
+
Sky and atmosphere rendering plugin. Currently a placeholder — `enable()` / `disable()` / `dispose()` are available but not yet implemented.
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { Atmosphere } from 'u-space/plugins/atmosphere';
|
|
305
|
+
|
|
306
|
+
const atmosphere = new Atmosphere(viewer);
|
|
307
|
+
atmosphere.enable();
|
|
308
|
+
```
|
package/docs/api-viewer.md
CHANGED
|
@@ -10,10 +10,10 @@ new Viewer(options: ViewerOptions)
|
|
|
10
10
|
|
|
11
11
|
### `ViewerOptions`
|
|
12
12
|
|
|
13
|
-
| Property | Type
|
|
14
|
-
| :---------------- |
|
|
15
|
-
| `el` | `HTMLElement`
|
|
16
|
-
| `rendererOptions` | `
|
|
13
|
+
| Property | Type | Required | Description |
|
|
14
|
+
| :---------------- | :------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| `el` | `HTMLElement` | Yes | The DOM element where the WebGPURenderer's canvas will be injected. |
|
|
16
|
+
| `rendererOptions` | `WebGPURendererParameters` | No | Options passed directly to the underlying `WebGPURenderer`. By default, it uses high-performance settings for WebGPU. |
|
|
17
17
|
|
|
18
18
|
## Properties
|
|
19
19
|
|
|
@@ -23,12 +23,18 @@ The `Viewer` instance exposes several core Three.js and `u-space` components.
|
|
|
23
23
|
| :------------------- | :------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------- |
|
|
24
24
|
| `el` | `HTMLElement` | The container element. |
|
|
25
25
|
| `renderer` | `WebGPURenderer` | The underlying WebGPU renderer instance. |
|
|
26
|
-
| `scene` | `Scene` | The main Three.js scene.
|
|
26
|
+
| `scene` | `Scene` | The main Three.js scene. Background defaults to `0x000000`. |
|
|
27
27
|
| `camera` | `PerspectiveCamera` \| `OrthographicCamera` | The active camera. |
|
|
28
28
|
| `controls` | `CameraControls` | Camera controls (powered by `camera-controls` library). |
|
|
29
|
+
| `renderPipeline` | `RenderPipeline` | Manages post-processing passes and the final render call. |
|
|
30
|
+
| `timer` | `Timer` | Three.js `Timer` instance for accurate delta time tracking each frame. |
|
|
31
|
+
| `roomEnvironment` | `RoomEnvironment` | Provides a default room-like IBL environment map for the scene. |
|
|
32
|
+
| `info` | `Info` | Renders renderer diagnostics (draw calls, triangles, etc.) as an overlay. |
|
|
33
|
+
| `viewerHelper` | `ViewerHelper` | Exposes utility helpers (e.g., axes, grid display) for development/debugging. |
|
|
29
34
|
| `interactionManager` | `InteractionManager` | Manages pointer events and raycasting on objects. |
|
|
30
35
|
| `objectManager` | `ObjectManager` | A utility for registering and retrieving objects by ID or name. |
|
|
31
36
|
| `frameloop` | `'always'` \| `'demand'` | Sets the rendering mode. Default is `'demand'` (render only when required). Set to `'always'` for continuous rendering. |
|
|
37
|
+
| `frameCount` | `number` | Internal counter of pending render frames. Incremented by `render()`. |
|
|
32
38
|
|
|
33
39
|
## Methods
|
|
34
40
|
|
|
@@ -42,10 +48,13 @@ await viewer.init();
|
|
|
42
48
|
|
|
43
49
|
### `render(frame?: number)`
|
|
44
50
|
|
|
45
|
-
Requests a render frame. In `'demand'` frameloop mode, this must be called whenever the scene changes visually to update the canvas. `frame` specifies how many frames to render.
|
|
51
|
+
Requests a render frame. In `'demand'` frameloop mode, this must be called whenever the scene changes visually to update the canvas. `frame` specifies how many frames to render (default `1`). Returns a `Promise<void>` that resolves after the frame is rendered.
|
|
46
52
|
|
|
47
53
|
```typescript
|
|
48
54
|
viewer.render();
|
|
55
|
+
|
|
56
|
+
// Await the rendered frame
|
|
57
|
+
await viewer.render();
|
|
49
58
|
```
|
|
50
59
|
|
|
51
60
|
### `setCamera(camera: PerspectiveCamera | OrthographicCamera)`
|
|
@@ -65,6 +74,32 @@ Convenience method to switch the camera type while maintaining the viewer contex
|
|
|
65
74
|
viewer.setCameraByType('orthographic');
|
|
66
75
|
```
|
|
67
76
|
|
|
77
|
+
### `createScene()`
|
|
78
|
+
|
|
79
|
+
Creates and returns a new `Scene` with a black background. Called internally by the constructor but can be used to reset/replace the scene.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
viewer.scene = viewer.createScene();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `createPerspectiveCamera()`
|
|
86
|
+
|
|
87
|
+
Creates a `PerspectiveCamera` with sensible defaults (50° fov, near `0.1`, far `1e5`, positioned at `(5, 5, 5)`).
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
const camera = viewer.createPerspectiveCamera();
|
|
91
|
+
viewer.setCamera(camera);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `createOrthographicCamera()`
|
|
95
|
+
|
|
96
|
+
Creates an `OrthographicCamera` sized to the container element, near `0.1`, far `1e5`, positioned at `(5, 5, 5)`.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const camera = viewer.createOrthographicCamera();
|
|
100
|
+
viewer.setCamera(camera);
|
|
101
|
+
```
|
|
102
|
+
|
|
68
103
|
### `dispose()`
|
|
69
104
|
|
|
70
105
|
Cleans up the viewer, removing the canvas from the DOM, removing event listeners, and disposing of the renderer and environment maps to prevent memory leaks.
|
package/docs/getting-started.md
CHANGED
|
@@ -122,5 +122,10 @@ And that's it! You now have a basic `u-space` application up and running.
|
|
|
122
122
|
## Next Steps
|
|
123
123
|
|
|
124
124
|
- Learn more about the [Viewer API](./api-viewer.md)
|
|
125
|
-
- Explore how to [load Models](./api-objects.md)
|
|
125
|
+
- Explore how to [load Models and work with Objects](./api-objects.md)
|
|
126
126
|
- Understand the [Interaction System](./api-interactions.md)
|
|
127
|
+
- Register and retrieve objects with the [Managers API](./api-managers.md)
|
|
128
|
+
- Add tile maps, minimap, keyboard controls and more with the [Plugins API](./api-plugins.md)
|
|
129
|
+
- Animate properties with the [Animations API](./api-animations.md)
|
|
130
|
+
- Apply visual effects with the [Effects API](./api-effects.md)
|
|
131
|
+
- Browse the [Examples Guide](./examples-guide.md)
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: home
|
|
3
|
+
|
|
4
|
+
hero:
|
|
5
|
+
name: u-space
|
|
6
|
+
text: WebGPU-ready 3D Engine
|
|
7
|
+
tagline: 基于 Three.js 的插件化 3D 可视化库,支持 GIS 瓦片、动画、场景管理与交互系统。
|
|
8
|
+
actions:
|
|
9
|
+
- theme: brand
|
|
10
|
+
text: 快速上手
|
|
11
|
+
link: /getting-started
|
|
12
|
+
- theme: alt
|
|
13
|
+
text: API 文档
|
|
14
|
+
link: /api-viewer
|
|
15
|
+
|
|
16
|
+
features:
|
|
17
|
+
- title: WebGPU 优先
|
|
18
|
+
details: 基于 Three.js WebGPU 渲染器,支持 TSL(Three Shading Language)着色器节点,同时保持 WebGL 兼容回退。
|
|
19
|
+
- title: 插件化架构
|
|
20
|
+
details: 核心轻量,通过独立插件按需扩展:GIS 瓦片、小地图、键盘控制、场景管理、曲线动画等。
|
|
21
|
+
- title: 交互系统
|
|
22
|
+
details: 内置射线检测与事件冒泡,像操作 DOM 元素一样为 3D 对象添加 click、pointerenter 等事件。
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 文档目录
|
|
26
|
+
|
|
27
|
+
### 核心 API
|
|
28
|
+
|
|
29
|
+
| 文档 | 说明 |
|
|
30
|
+
| :--- | :--- |
|
|
31
|
+
| [Viewer](./api-viewer) | 核心类:渲染器、场景、相机、控制器、事件 |
|
|
32
|
+
| [Objects](./api-objects) | 3D 对象:模型加载、基础网格、Poi、Topology |
|
|
33
|
+
| [Interactions](./api-interactions) | 交互管理:射线检测、鼠标/触摸事件 |
|
|
34
|
+
| [Managers](./api-managers) | 对象管理:按 ID / 名称 / 类型检索 |
|
|
35
|
+
| [Animations](./api-animations) | 补间动画:`tweenAnimation`、`Tween`、缓动模式 |
|
|
36
|
+
| [Effects](./api-effects) | 视觉特效:高亮、流动、呼吸、流体(TSL) |
|
|
37
|
+
|
|
38
|
+
### 插件
|
|
39
|
+
|
|
40
|
+
所有插件从 `u-space/plugins/<name>` 导入。
|
|
41
|
+
|
|
42
|
+
| 插件 | 说明 |
|
|
43
|
+
| :--- | :--- |
|
|
44
|
+
| [keyboard-controls](./api-plugins#keyboard-controls) | WASD / 方向键控制相机移动与旋转 |
|
|
45
|
+
| [minimap](./api-plugins#minimap) | 2D 小地图叠加层 |
|
|
46
|
+
| [tiles](./api-plugins#tiles) | ArcGIS 3D 瓦片 / GIS 地球渲染 |
|
|
47
|
+
| [u-manager](./api-plugins#u-manager) | 场景加载、拓扑、动画、属性、视点管理 |
|
|
48
|
+
| [curve-movement](./api-plugins#curve-movement) | 沿样条曲线移动相机或对象 |
|
|
49
|
+
| [tracking-controls](./api-plugins#tracking-controls) | 相机跟随移动目标 |
|
|
50
|
+
| [atmosphere](./api-plugins#atmosphere) | 天空/大气渲染(开发中) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u-space",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "dist/src/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -20,12 +20,23 @@
|
|
|
20
20
|
]
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build:dev": "vite build --mode development && tsc",
|
|
25
|
+
"build:u-space": "cross-env BUILD_TARGET=u-space vite build --mode development",
|
|
26
|
+
"build:plugins": "cross-env BUILD_TARGET=plugins vite build --mode development",
|
|
27
|
+
"build": "cross-env BUILD_TARGET=all vite build --mode production && tsc",
|
|
28
|
+
"docs:dev": "vitepress dev docs",
|
|
29
|
+
"docs:build": "vitepress build docs",
|
|
30
|
+
"docs:preview": "vitepress preview docs",
|
|
31
|
+
"docs:deploy": "pnpm docs:build && vercel --prod"
|
|
32
|
+
},
|
|
23
33
|
"files": [
|
|
24
34
|
"dist",
|
|
25
35
|
"package.json",
|
|
26
36
|
"README.md",
|
|
27
|
-
"docs"
|
|
37
|
+
"docs/*.md"
|
|
28
38
|
],
|
|
39
|
+
"homepage": "https://u-space-phi.vercel.app",
|
|
29
40
|
"keywords": [
|
|
30
41
|
"u-space",
|
|
31
42
|
"space",
|
|
@@ -42,7 +53,8 @@
|
|
|
42
53
|
"node-rsa": "^1.1.1",
|
|
43
54
|
"typescript": "~5.9.3",
|
|
44
55
|
"vite": "^7.3.1",
|
|
45
|
-
"vite-plugin-node-polyfills": "^0.24.0"
|
|
56
|
+
"vite-plugin-node-polyfills": "^0.24.0",
|
|
57
|
+
"vitepress": "^1.6.4"
|
|
46
58
|
},
|
|
47
59
|
"peerDependencies": {
|
|
48
60
|
"3d-tiles-renderer": "^0.4.19",
|
|
@@ -50,11 +62,5 @@
|
|
|
50
62
|
"@types/three": "^0.183.1",
|
|
51
63
|
"camera-controls": "^3.1.2",
|
|
52
64
|
"three": "^0.183.1"
|
|
53
|
-
},
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build:dev": "vite build --mode development && tsc",
|
|
56
|
-
"build:u-space": "cross-env BUILD_TARGET=u-space vite build --mode development",
|
|
57
|
-
"build:plugins": "cross-env BUILD_TARGET=plugins vite build --mode development",
|
|
58
|
-
"build": "cross-env BUILD_TARGET=all vite build --mode production && tsc"
|
|
59
65
|
}
|
|
60
66
|
}
|