u-space 0.0.26 → 0.0.27
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/index.cjs +3 -3
- package/dist/index.js +377 -331
- package/dist/plugins/atmosphere/index.cjs +1 -1
- package/dist/plugins/atmosphere/index.js +3255 -129
- package/dist/plugins/atmosphere/threeR185Compat.d.ts +2 -0
- package/dist/plugins/fire/FireEffect.d.ts +90 -0
- package/dist/plugins/fire/index.cjs +1 -0
- package/dist/plugins/fire/index.d.ts +1 -0
- package/dist/plugins/fire/index.js +433 -0
- package/dist/plugins/u-manager/index.cjs +57 -57
- package/dist/plugins/u-manager/index.d.ts +1 -0
- package/dist/plugins/u-manager/index.js +8791 -8291
- package/dist/plugins/u-manager/loaders/SceneInstancedLayer.d.ts +29 -0
- package/dist/plugins/u-manager/loaders/SceneLoader.d.ts +5 -5
- package/dist/plugins/u-manager/semantics/objects/FacilityInstancedLayer.d.ts +23 -8
- package/dist/src/tools/AnnotationManager.d.ts +4 -1
- package/dist/src/viewers/RenderPipeline.d.ts +6 -5
- package/docs/api-effects.md +2 -0
- package/docs/api-interactions.md +1 -0
- package/docs/api-managers.md +1 -1
- package/docs/api-plugin-fire.md +174 -0
- package/docs/api-plugin-u-manager.md +145 -8
- package/docs/api-tools.md +1 -1
- package/docs/changelog.md +21 -0
- package/docs/examples-guide.md +13 -1
- package/docs/getting-started.md +1 -1
- package/docs/index.md +1 -0
- package/docs/mcp.md +27 -1
- package/package.json +4 -4
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Box3, Color, Group, Object3D, type ColorRepresentation } from 'three/webgpu';
|
|
2
|
+
import { BaseGroup } from 'u-space';
|
|
3
|
+
export declare class SceneInstanceObject extends Group {
|
|
4
|
+
#private;
|
|
5
|
+
isSceneInstanceObject: boolean;
|
|
6
|
+
type: string;
|
|
7
|
+
setSceneInstanceBounds(bounds: Box3): this;
|
|
8
|
+
getSceneInstanceBoundingBox(target?: Box3, world?: boolean): Box3;
|
|
9
|
+
setSceneInstanceVisible(visible: boolean): this;
|
|
10
|
+
setSceneInstanceColor(color: ColorRepresentation): this;
|
|
11
|
+
resetSceneInstanceColor(): this;
|
|
12
|
+
setSceneInstanceOpacity(opacity: number): this;
|
|
13
|
+
getSceneInstanceColor(target?: Color): Color;
|
|
14
|
+
hasSceneInstanceColor(): boolean;
|
|
15
|
+
getSceneInstanceOpacity(): number;
|
|
16
|
+
setSceneInstanceHighlight(color: ColorRepresentation, opacity: number, overwrite?: boolean): this;
|
|
17
|
+
clearSceneInstanceHighlight(): this;
|
|
18
|
+
getSceneInstanceColorMode(): number;
|
|
19
|
+
onSceneInstanceRenderDirty(callback: () => void): () => boolean;
|
|
20
|
+
markSceneInstanceRenderDirty(): this;
|
|
21
|
+
updateMatrixWorld(force?: boolean): void;
|
|
22
|
+
}
|
|
23
|
+
export declare class SceneInstancedLayer extends BaseGroup {
|
|
24
|
+
#private;
|
|
25
|
+
isSceneInstancedLayer: boolean;
|
|
26
|
+
type: string;
|
|
27
|
+
constructor();
|
|
28
|
+
addSceneBatch(url: string, template: Object3D, instances: SceneInstanceObject[]): boolean;
|
|
29
|
+
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Group, Loader } from 'three/webgpu';
|
|
2
|
-
import { type Viewer } from 'u-space';
|
|
2
|
+
import { Model, type Viewer } from 'u-space';
|
|
3
3
|
import type { ITreeData } from '../types';
|
|
4
|
-
export
|
|
5
|
-
}
|
|
6
|
-
export declare class SceneLoader extends Loader<unknown, SceneLoaderOptions> {
|
|
4
|
+
export declare class SceneLoader extends Loader {
|
|
7
5
|
#private;
|
|
8
6
|
viewer: Viewer;
|
|
9
7
|
key: string;
|
|
@@ -12,13 +10,15 @@ export declare class SceneLoader extends Loader<unknown, SceneLoaderOptions> {
|
|
|
12
10
|
protected _treeData: ITreeData[];
|
|
13
11
|
constructor(viewer: Viewer);
|
|
14
12
|
setKey(key: string): this;
|
|
13
|
+
protected loadModel(url: string): Promise<Model>;
|
|
15
14
|
protected _preareTreeData(): Promise<void>;
|
|
15
|
+
protected _prepareSemanticIds(): Promise<ReadonlySet<string>>;
|
|
16
16
|
/**
|
|
17
17
|
* 加载场景
|
|
18
18
|
* @param options
|
|
19
19
|
* @returns
|
|
20
20
|
*/
|
|
21
|
-
loadAsync(
|
|
21
|
+
loadAsync(): Promise<Group>;
|
|
22
22
|
clearCache(): void;
|
|
23
23
|
dispose(): void;
|
|
24
24
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { Box3, Color, Group, Object3D, type ColorRepresentation } from 'three/webgpu';
|
|
2
2
|
import { BaseGroup } from 'u-space';
|
|
3
|
+
export interface FacilityInstanceCullingOptions {
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
frustum?: boolean;
|
|
6
|
+
minScreenRadius?: number;
|
|
7
|
+
}
|
|
3
8
|
export declare class FacilityInstanceObject extends Group {
|
|
4
9
|
#private;
|
|
5
10
|
isFacilityInstanceObject: boolean;
|
|
@@ -13,19 +18,29 @@ export declare class FacilityInstanceObject extends Group {
|
|
|
13
18
|
getFacilityColor(target?: Color): Color;
|
|
14
19
|
hasFacilityColor(): boolean;
|
|
15
20
|
getFacilityOpacity(): number;
|
|
21
|
+
setFacilityHighlight(color: ColorRepresentation, opacity: number, overwrite?: boolean): this;
|
|
22
|
+
clearFacilityHighlight(): this;
|
|
23
|
+
getFacilityColorMode(): number;
|
|
24
|
+
onFacilityRenderDirty(callback: () => void): () => boolean;
|
|
25
|
+
markFacilityRenderDirty(): this;
|
|
16
26
|
}
|
|
17
27
|
export declare class FacilityInstancedLayer extends BaseGroup {
|
|
18
28
|
#private;
|
|
19
29
|
isFacilityInstancedLayer: boolean;
|
|
20
30
|
type: string;
|
|
21
|
-
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
22
|
-
cameraDistanceCulling: boolean;
|
|
23
|
-
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
24
|
-
cameraCullDistance: number;
|
|
25
|
-
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
26
|
-
cameraCullOverviewFactor: number;
|
|
27
|
-
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
28
|
-
cameraCullPlanViewThreshold: number;
|
|
29
31
|
constructor();
|
|
32
|
+
getFacilities(): FacilityInstanceObject[];
|
|
33
|
+
getInstanceCulling(): {
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
frustum: boolean;
|
|
36
|
+
minScreenRadius: number;
|
|
37
|
+
};
|
|
38
|
+
setInstanceCulling(options?: FacilityInstanceCullingOptions): this;
|
|
39
|
+
setFacilityVisible(visible: boolean): this;
|
|
40
|
+
setFacilityColor(color: ColorRepresentation): this;
|
|
41
|
+
resetFacilityColor(): this;
|
|
42
|
+
setFacilityOpacity(opacity: number): this;
|
|
43
|
+
setFacilityHighlight(color: ColorRepresentation, opacity: number, overwrite?: boolean): this;
|
|
44
|
+
clearFacilityHighlight(): this;
|
|
30
45
|
addFacilityBatch(url: string, template: Object3D, facilities: FacilityInstanceObject[]): boolean;
|
|
31
46
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Line, type Scene, type ColorRepresentation, Group } from 'three/webgpu';
|
|
2
|
+
export type AnnotationLabelStyle = {
|
|
3
|
+
[K in keyof CSSStyleDeclaration as CSSStyleDeclaration[K] extends string ? K : never]?: CSSStyleDeclaration[K];
|
|
4
|
+
};
|
|
2
5
|
export interface AnnotationOptions {
|
|
3
6
|
/** Position of the annotation anchor in 3D space */
|
|
4
7
|
position: {
|
|
@@ -19,7 +22,7 @@ export interface AnnotationOptions {
|
|
|
19
22
|
/** Leader line color */
|
|
20
23
|
lineColor?: ColorRepresentation;
|
|
21
24
|
/** CSS styles for the label element */
|
|
22
|
-
labelStyle?:
|
|
25
|
+
labelStyle?: AnnotationLabelStyle;
|
|
23
26
|
}
|
|
24
27
|
export interface Annotation {
|
|
25
28
|
id: string;
|
|
@@ -12,8 +12,9 @@ export interface SSGIConfig {
|
|
|
12
12
|
radius?: number;
|
|
13
13
|
thickness?: number;
|
|
14
14
|
}
|
|
15
|
-
export type
|
|
16
|
-
export type
|
|
15
|
+
export type ColorOutputNode = Node<'vec4'>;
|
|
16
|
+
export type OutputNodeComposer = (scenePass: PassNode) => ColorOutputNode;
|
|
17
|
+
export type OutputNodeEffect = ((scenePass: PassNode, inputNode: ColorOutputNode) => ColorOutputNode) & {
|
|
17
18
|
includesTemporalAntialias?: boolean;
|
|
18
19
|
includesOutputTransform?: boolean;
|
|
19
20
|
};
|
|
@@ -27,11 +28,11 @@ export declare class RenderPipeline extends RenderPipelineBase {
|
|
|
27
28
|
constructor(...args: Args);
|
|
28
29
|
/** @deprecated Use `scenePass` instead */
|
|
29
30
|
get currentOutputNode(): PassNode;
|
|
30
|
-
addOverlayPass(pass:
|
|
31
|
-
removeOverlayPass(pass:
|
|
31
|
+
addOverlayPass(pass: ColorOutputNode): void;
|
|
32
|
+
removeOverlayPass(pass: ColorOutputNode): void;
|
|
32
33
|
setCamera(camera: Camera): void;
|
|
33
34
|
/** @deprecated Use `setOutputComposer` instead */
|
|
34
|
-
setCurrentOutputNode(node:
|
|
35
|
+
setCurrentOutputNode(node: ColorOutputNode): void;
|
|
35
36
|
/** @deprecated Use `setOutputComposer(null)` instead */
|
|
36
37
|
resetCurrentOutputNode(): void;
|
|
37
38
|
setOutputComposer(composer: OutputNodeComposer | null): void;
|
package/docs/api-effects.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
## `MaterialEffects`
|
|
6
6
|
|
|
7
7
|
静态工具类,将基于 TSL 的视觉特效直接应用于对象的材质。适用于任何 `Object3D`(支持单个或数组),会自动遍历所有子网格。
|
|
8
|
+
当对象是 `SceneLoader` 自动批处理生成的 `SceneInstanceObject` 时,`highlightColor()` / `removeHighlightColor()` 会改写该实例的 per-instance color / opacity,而不是改动共享 batch 材质。
|
|
9
|
+
`SceneInstanceObject` 会支持 `overwrite` 的替换/染色语义;`depthWrite` 属于共享 batch 材质状态,不能按单个实例设置,因此对该类对象不会生效。
|
|
8
10
|
|
|
9
11
|
特性:
|
|
10
12
|
- **效果可叠加**:高亮和呼吸效果可同时作用于同一对象,呼吸在高亮结果之上混合
|
package/docs/api-interactions.md
CHANGED
|
@@ -16,6 +16,7 @@ viewer.interactionManager.pointerMoveEventsEnabled = true;
|
|
|
16
16
|
### 目标对象
|
|
17
17
|
|
|
18
18
|
可以限制射线检测所针对的对象范围。默认值为 `scene.children`(即整个场景的直接子级,含递归嵌套)。
|
|
19
|
+
`BaseMesh` / `BaseGroup` 默认会在自身 `visible === false` 时让 `raycast()` 返回 `false`,从而阻止自身和子级继续参与递归射线检测;如需隐藏但仍可交互,可将对象的 `ignoreInvisibleWhenRaycast` 设为 `false`。`setInteractable(object, false)` / `addIgnore(object)` 会在命中后过滤该对象及其子对象。
|
|
19
20
|
|
|
20
21
|
```typescript
|
|
21
22
|
// 仅检测指定对象
|
package/docs/api-managers.md
CHANGED
|
@@ -129,7 +129,7 @@ viewer.objectManager.showAll();
|
|
|
129
129
|
|
|
130
130
|
#### `setOpacity(id: string, opacity: number)`
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
设置指定对象所有材质的透明度。对于 `SceneLoader` 自动批处理生成的 `SceneInstanceObject`,会写入该实例的 per-instance opacity,而不会影响同一模型 path 的其他实例。
|
|
133
133
|
|
|
134
134
|
```typescript
|
|
135
135
|
viewer.objectManager.setOpacity('building-01', 0.3);
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# fire
|
|
2
|
+
|
|
3
|
+
体积火焰插件,基于 Three.js 官方 `webgpu_volume_fire` 示例封装。插件在 GPU 上运行 3D 流体模拟,并通过独立的 volumetric pass 叠加到 `Viewer.renderPipeline` output effect 链中,提供火焰、烟雾、扰动、阴影和动态点光源效果。
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { Vector3 } from 'three/webgpu';
|
|
7
|
+
import { FireEffect } from 'u-space/plugins/fire';
|
|
8
|
+
|
|
9
|
+
const fire = new FireEffect(viewer, {
|
|
10
|
+
position: new Vector3(0, 0, 0),
|
|
11
|
+
size: new Vector3(12, 12, 24),
|
|
12
|
+
fireIntensity: 40,
|
|
13
|
+
smokeLifespan: 3.5,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
fire.enable();
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 能力
|
|
20
|
+
|
|
21
|
+
- 按官方示例的 semi-Lagrangian advection、curl noise、buoyancy、Jacobi pressure projection 流程模拟体积火焰和烟雾。
|
|
22
|
+
- 使用 3D storage texture 保存速度、密度、温度、压力和 curl noise 数据。
|
|
23
|
+
- 默认使用 `TeapotGeometry(0.8, 28)` 作为 emitter 采样几何;也可以传入业务对象和自定义 `BufferGeometry`。
|
|
24
|
+
- 通过 `RenderPipeline.addOutputEffect()` 叠加体积结果,不占用业务侧的 `setOutputComposer()`。
|
|
25
|
+
- 内置 spot light 和 point light:spot light 负责体积阴影方向,point light 跟随火焰核心投射暖色动态光照。
|
|
26
|
+
- 监听 `cameraChange`,相机对象切换后会重建 fire 自己的 volumetric pass。
|
|
27
|
+
|
|
28
|
+
## API
|
|
29
|
+
|
|
30
|
+
### `new FireEffect(viewer, options?)`
|
|
31
|
+
|
|
32
|
+
创建火焰效果实例。构造函数不会立即往场景写入模拟资源;调用 `enable()` 后才会创建体积盒、storage texture、compute pass、灯光和 output effect。
|
|
33
|
+
|
|
34
|
+
### `enable(options?)`
|
|
35
|
+
|
|
36
|
+
开启火焰效果。重复调用时等同于 `update(options)`。启用期间会把 `viewer.frameloop` 临时切到 `always`,关闭时恢复启用前的值。
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
fire.enable({
|
|
40
|
+
position: new Vector3(0, 0, 0),
|
|
41
|
+
size: new Vector3(12, 12, 24),
|
|
42
|
+
renderResolution: 0.5,
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `update(options?)`
|
|
47
|
+
|
|
48
|
+
更新火焰参数。大多数视觉和模拟强度参数会通过 uniform 直接生效。`gridSize`、`emitterGeometry`、`volumeLayer` 或 `raymarchSteps` 改变时会重建相关资源。
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
fire.update({
|
|
52
|
+
emitTemperature: 6,
|
|
53
|
+
emitDensity: 8,
|
|
54
|
+
emitterRadius: 1.4,
|
|
55
|
+
smokeLifespan: 6,
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### `setPosition(position)`
|
|
60
|
+
|
|
61
|
+
更新体积盒底部中心位置。等同于 `update({ position })`。
|
|
62
|
+
|
|
63
|
+
### `setEmitter(emitter, geometry?)`
|
|
64
|
+
|
|
65
|
+
设置驱动 emitter 的对象和采样几何。`emitter` 的 `matrixWorld` 会在每帧写入模拟;如果只想使用默认内部 emitter,可以传入 `null`。
|
|
66
|
+
|
|
67
|
+
### `reset()`
|
|
68
|
+
|
|
69
|
+
清空当前模拟状态并重新创建模拟资源。
|
|
70
|
+
|
|
71
|
+
### `disable()`
|
|
72
|
+
|
|
73
|
+
关闭火焰效果,移除 `beforeRender` / `cameraChange` 监听、output effect、体积盒、灯光、storage texture 和 compute pass,并恢复启用前的 `viewer.frameloop`。
|
|
74
|
+
|
|
75
|
+
### `dispose()`
|
|
76
|
+
|
|
77
|
+
关闭效果并释放插件持有的默认 emitter geometry。
|
|
78
|
+
|
|
79
|
+
## Options
|
|
80
|
+
|
|
81
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
82
|
+
| --- | --- | --- | --- |
|
|
83
|
+
| `position` | `Vector3` | `(0, 0, 0)` | 体积盒底部中心世界坐标 |
|
|
84
|
+
| `size` | `Vector3` | `(12, 12, 24)` | 体积盒世界尺寸,也是烟雾扩散的约束范围 |
|
|
85
|
+
| `gridSize` | `{ x?: number; y?: number; z?: number }` | `{ x: 100, y: 100, z: 200 }` | 3D 模拟网格尺寸,越大越细腻也越耗显存 |
|
|
86
|
+
| `volumeLayer` | `number` | `10` | 体积盒所在 layer,用于隔离 volumetric pass |
|
|
87
|
+
| `emitterGeometry` | `BufferGeometry \| null` | `TeapotGeometry(0.8, 28)` | emit pass 采样的几何顶点 |
|
|
88
|
+
| `emitter` | `Object3D \| null` | 内部 `Object3D` | 驱动 emitter matrix 和扰动速度的对象 |
|
|
89
|
+
| `emitterRadius` | `number` | `1` | emitter 移动时影响流场的半径,作为 uniform 更新 |
|
|
90
|
+
| `simulate` | `boolean` | `true` | 是否推进流体模拟 |
|
|
91
|
+
| `simSpeed` | `number` | `1.2` | 模拟速度倍率 |
|
|
92
|
+
| `pressureIterations` | `number` | `2` | Jacobi pressure projection 次数,会自动向上限制为正偶数 |
|
|
93
|
+
| `raymarchSteps` | `number` | `16` | 体积 raymarch 步数,改变后会重建体积材质 |
|
|
94
|
+
| `renderResolution` | `number` | `0.5` | volumetric pass 分辨率倍率,范围 `0.1..1` |
|
|
95
|
+
| `denoise` | `boolean` | `true` | 是否对体积 pass 做 Gaussian blur |
|
|
96
|
+
| `denoiseStrength` | `number` | `0.5` | 降噪强度 |
|
|
97
|
+
| `bloom` | `boolean` | `true` | 是否对火焰输出追加 bloom |
|
|
98
|
+
| `bloomStrength` | `number` | `0.1` | bloom 强度 |
|
|
99
|
+
| `bloomRadius` | `number` | `1` | bloom 半径 |
|
|
100
|
+
| `bloomThreshold` | `number` | `0.5` | bloom 阈值 |
|
|
101
|
+
| `smokeLifespan` | `number` | `3.5` | 烟雾寿命,越大烟雾保留越久 |
|
|
102
|
+
| `smokeIntensity` | `number` | `1` | 烟雾散射可见度倍率 |
|
|
103
|
+
| `smokeColor` | `ColorRepresentation` | `0xffffff` | 烟雾散射颜色 |
|
|
104
|
+
| `fireLifespan` | `number` | `1.3` | 火焰温度衰减时间 |
|
|
105
|
+
| `turbulence` | `number` | `3.2` | 火焰和烟雾湍流强度 |
|
|
106
|
+
| `turbulenceDecay` | `number` | `0.1` | 湍流随年龄衰减速度 |
|
|
107
|
+
| `turbulenceFrequency` | `number` | `10` | curl noise 频率 |
|
|
108
|
+
| `buoyancy` | `number` | `3` | 热浮力 |
|
|
109
|
+
| `velocityDamping` | `number` | `0.25` | 速度阻尼 |
|
|
110
|
+
| `emitDensity` | `number` | `7` | emitter 注入密度 |
|
|
111
|
+
| `emitTemperature` | `number` | `5.5` | emitter 注入温度 |
|
|
112
|
+
| `motionBoost` | `number` | `0.25` | emitter 移动带来的额外发射量 |
|
|
113
|
+
| `windStrength` | `number` | `6.5` | emitter 移动对流场的扰动强度 |
|
|
114
|
+
| `fireIntensity` | `number` | `40` | 火焰发光强度 |
|
|
115
|
+
| `glowSpread` | `number` | `5` | 火焰亮度扩散范围 |
|
|
116
|
+
| `fireHue` | `number` | `0` | 火焰色相偏移,单位为度 |
|
|
117
|
+
| `saturation` | `number` | `1.1` | 输出饱和度 |
|
|
118
|
+
| `fireStartColor` | `ColorRepresentation` | `0xffe68c` | 高温火焰颜色 |
|
|
119
|
+
| `fireMidColor` | `ColorRepresentation` | `0xff7305` | 中段火焰颜色 |
|
|
120
|
+
| `fireEndColor` | `ColorRepresentation` | `0xff0000` | 低温火焰颜色 |
|
|
121
|
+
| `phaseAsymmetry` | `number` | `0` | Henyey-Greenstein 相函数 g 值 |
|
|
122
|
+
| `powderStrength` | `number` | `0.59` | powder effect 强度 |
|
|
123
|
+
| `multiScattering` | `number` | `1` | 多次散射近似强度 |
|
|
124
|
+
| `shadowAbsorption` | `number` | `2` | 体积阴影吸收系数 |
|
|
125
|
+
| `shadowAmbient` | `number` | `0.5` | 阴影环境补光 |
|
|
126
|
+
| `keyLight` | `boolean` | `true` | 是否创建体积阴影 spot light |
|
|
127
|
+
| `pointLight` | `boolean` | `true` | 是否创建火焰动态点光源 |
|
|
128
|
+
| `pointLightIntensity` | `number` | `1` | 动态点光源强度 |
|
|
129
|
+
| `pointLightDistance` | `number` | `40` | 动态点光源距离 |
|
|
130
|
+
|
|
131
|
+
## Emitter
|
|
132
|
+
|
|
133
|
+
如果不设置 `emitterGeometry`,插件会创建一个内部 `TeapotGeometry(0.8, 28)`,这和官方示例保持一致。emit pass 会遍历该几何的 position 顶点,把密度和温度写入体积纹理。传入自定义 `emitterGeometry` 时,该几何必须包含 `position` attribute。
|
|
134
|
+
|
|
135
|
+
如果不设置 `emitter`,插件会使用内部 `Object3D`,并把它放在 `position` 位置。传入业务对象后,插件每帧读取该对象的 `matrixWorld` 和世界位置变化,移动速度会影响流场扰动和额外发射量。
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
const fire = new FireEffect(viewer, {
|
|
139
|
+
emitter: torchMesh,
|
|
140
|
+
emitterGeometry: torchFlameGeometry,
|
|
141
|
+
emitterRadius: 0.8,
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## 光源与体积范围
|
|
146
|
+
|
|
147
|
+
火焰本体不是场景里的普通透明 mesh 直接混合,而是先放在 `volumeLayer` 的体积盒里单独渲染,再通过 output effect 叠加到主场景。烟雾和火焰的可见范围由 `position + size` 定义的体积盒限制,超出盒子的密度会在边界处淡出。要让烟雾扩散范围更大,优先增大 `size`;要提升细节,再同步增大 `gridSize`。
|
|
148
|
+
|
|
149
|
+
插件会按需创建两个光源:
|
|
150
|
+
|
|
151
|
+
- `FireEffect.keyLight`:`SpotLight`,用于体积阴影方向和烟雾散射计算。
|
|
152
|
+
- `FireEffect.pointLight`:`PointLight`,跟随 emitter / 火焰核心移动,并通过 TSL `colorNode` 产生随温度、密度和噪声变化的暖色照明。
|
|
153
|
+
|
|
154
|
+
如果业务场景已经有自己的灯光,可以通过 `keyLight: false` 或 `pointLight: false` 关闭插件内置光源。
|
|
155
|
+
|
|
156
|
+
## 与 RenderPipeline 的关系
|
|
157
|
+
|
|
158
|
+
`FireEffect` 使用 `viewer.renderPipeline.addOutputEffect()` 和 `removeOutputEffect()` 接入输出链。它不会调用 `setOutputComposer()`,因此不会覆盖业务或其他插件的 output effects。注意如果业务主动设置自定义 `setOutputComposer()`,RenderPipeline 会按自定义 composer 的语义跳过 output effects,火焰叠加也会被跳过。
|
|
159
|
+
|
|
160
|
+
`renderResolution` 只影响独立 volumetric pass 的分辨率;主场景分辨率仍由 `Viewer` 和 renderer 控制。启用 `denoise` 和 `bloom` 时,插件会在 output effect 内创建并释放对应节点。
|
|
161
|
+
|
|
162
|
+
## 示例
|
|
163
|
+
|
|
164
|
+
示例页见 `examples/test_fire.html`。本地运行时先构建插件:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
pnpm build:plugins -- plugins/fire
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
然后通过本地静态服务访问:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
http://127.0.0.1:5174/examples/test_fire.html
|
|
174
|
+
```
|
|
@@ -121,11 +121,11 @@ if (vent) {
|
|
|
121
121
|
|
|
122
122
|
`tree_models.matrix` 是相对父节点的本地矩阵;`SemanticLoader` 会沿树父级累乘得到设备世界矩阵,再转换为对应 `FloorMesh` 的局部矩阵。因此楼层移动、隔离或显示隐藏时设备会跟随楼层一起工作。即使某个 story 只有 `Facilities`、没有墙柱空间等合并几何,也会创建一个空的 `FloorMesh` 作为设备容器。
|
|
123
123
|
|
|
124
|
-
Facilities 会在单次 `SemanticParser` 解析范围内按模型 URL 自动分组。静态模型会被转换为 scene-level `InstancedMesh` batch
|
|
124
|
+
Facilities 会在单次 `SemanticParser` 解析范围内按模型 URL 自动分组。静态模型会被转换为 scene-level `InstancedMesh` batch 并挂到 `SemanticSceneGroup.facilityLayer`;每个设备仍会在所属 `FloorMesh` 下保留一个轻量引用,用于 `getFacilityById()`、显隐、颜色、透明度和 `viewer.objectManager` 检索。设备 batch 使用普通 `Group` 包裹,以保证每帧渲染前都能执行相机实例裁剪和 hide/show 后的实例同步;带动画、骨骼、morph target 或缺少合法 `geometry.groups` 的多材质 Mesh 会自动回退为普通 `Model`,继续作为实际 `Object3D` 挂到所属 `FloorMesh`。
|
|
125
125
|
|
|
126
126
|
`facilityLayer` 使用 `FacilityInstancedLayer`,并继承自 `BaseGroup`。当 `facilityLayer.visible = false` 时,layer 会阻止内部 `InstancedMesh` 继续参与射线检测,避免隐藏的批处理设备仍被点击命中;单个设备的显隐仍应通过楼层下的设备引用或 `showFacility()` / `hideFacility()` 控制。
|
|
127
127
|
|
|
128
|
-
Instanced 设备通过 per-instance opacity attribute 控制单个设备透明度。batch 材质默认沿用源材质的透明状态;只有源材质本身透明,或当前参与渲染的设备存在 `opacity < 1` 时,材质才会切到 `transparent: true`,`setFacilityOpacity(id, 1)` 可在没有其他半透明实例时回到不透明渲染队列。`resetFacilityColor()` 只清除颜色 override,不影响透明度 override。`FacilityInstancedLayer`
|
|
128
|
+
Instanced 设备通过 per-instance opacity attribute 控制单个设备透明度。batch 材质默认沿用源材质的透明状态;只有源材质本身透明,或当前参与渲染的设备存在 `opacity < 1` 时,材质才会切到 `transparent: true`,`setFacilityOpacity(id, 1)` 可在没有其他半透明实例时回到不透明渲染队列。`resetFacilityColor()` 只清除颜色 override,不影响透明度 override。`FacilityInstancedLayer` 会在设备显隐、颜色、透明度、floor planish/unplanish 改变设备 transform,或相机矩阵、投影矩阵、viewport 高度变化时,在下一次渲染前同步实例矩阵、颜色、透明度和当前 active instance count。普通 fallback `Model` 的颜色和透明度控制依赖 `MaterialEffects`,单材质和多材质 Mesh 都会应用 override。
|
|
129
129
|
|
|
130
130
|
加载成功后,设备引用会写入 `userData.facilityId`、`semanticId`、`semanticKind: 'Facilities'`、`semanticName`、`spaces`、`twinsIdentifier`、`storyId` 和 `floorIndex`,并按 `Facility.ID` 注册到 `viewer.objectManager`。自动 instancing 的引用还会带有 `userData.instanced: true` 和 `userData.modelUrl`。
|
|
131
131
|
|
|
@@ -162,6 +162,102 @@ semanticScene
|
|
|
162
162
|
|
|
163
163
|
对 Facilities 推荐使用 `controls.flyToBox()` 飞向设备包围盒。instanced 设备引用是楼层下的轻量 `FacilityInstanceObject`,可通过 `getFacilityBoundingBox(box, true)` 取得完整世界包围盒;普通 fallback `Model` 也可以直接使用 `viewer.controls.flyToObject(facility)`。
|
|
164
164
|
|
|
165
|
+
### `FacilityInstanceObject`
|
|
166
|
+
|
|
167
|
+
`FacilityInstanceObject` 继承自 Three.js `Group`,表示一个被 scene-level `FacilityInstancedLayer` 批量渲染的设备引用。它会挂在所属 `FloorMesh` 下,用于 ID 检索、事件派发、显隐、颜色、透明度和包围盒查询;真正的设备几何不会作为它的子网格重复挂载,而是由 `SemanticSceneGroup.facilityLayer` 里的 `InstancedMesh` 统一渲染。
|
|
168
|
+
|
|
169
|
+
通常不需要手动创建 `FacilityInstanceObject`。`SemanticParser` 在解析 `Facilities` 时会自动创建它,并写入 `userData.facilityId`、`semanticId`、`semanticKind: 'Facilities'`、`semanticName`、`spaces`、`twinsIdentifier`、`storyId`、`floorIndex`、`instanced: true` 和 `modelUrl`。如果设备模型无法 instancing,则会回退为普通 `Model`,不会具备这些实例引用专用方法。
|
|
170
|
+
|
|
171
|
+
加载完成后,instanced 设备也可以按 `Facility.ID` 从全局 `objectManager` 取回。推荐使用 `getFacilityBoundingBox(box, true)` 取得完整世界包围盒,再调用 `viewer.controls.flyToBox()`;如果取到的是普通 fallback `Model`,则继续用 `viewer.controls.flyToObject(facility)`。
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { Box3 } from 'three';
|
|
175
|
+
import { FacilityInstanceObject } from 'u-space/plugins/u-manager';
|
|
176
|
+
|
|
177
|
+
const facility = viewer.objectManager.getById<FacilityInstanceObject>('FACILITY_001');
|
|
178
|
+
|
|
179
|
+
if (facility?.isFacilityInstanceObject) {
|
|
180
|
+
const box = facility.getFacilityBoundingBox(new Box3(), true);
|
|
181
|
+
|
|
182
|
+
await viewer.controls.flyToBox(box, {
|
|
183
|
+
viewpoint: 'rightFrontTop',
|
|
184
|
+
padding: 0.2,
|
|
185
|
+
enableTransition: true,
|
|
186
|
+
});
|
|
187
|
+
} else if (facility) {
|
|
188
|
+
await viewer.controls.flyToObject(facility, {
|
|
189
|
+
viewpoint: 'rightFrontTop',
|
|
190
|
+
padding: 0.2,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
| 属性 / 方法 | 说明 |
|
|
196
|
+
| :---------- | :--- |
|
|
197
|
+
| `isFacilityInstanceObject` | 类型标记,值为 `true`。 |
|
|
198
|
+
| `type` | Three.js 对象类型名,值为 `'FacilityInstanceObject'`。 |
|
|
199
|
+
| `setLocalBounds(bounds)` | 设置设备模板在引用本地空间内的包围盒,并返回自身;主要由 `FacilityInstancedLayer.addFacilityBatch()` 在建 batch 时写入。 |
|
|
200
|
+
| `getFacilityBoundingBox(target?, world?)` | 获取设备完整包围盒。`world = true` 时会应用 `matrixWorld`,适合传给 `viewer.controls.flyToBox()`;没有 bounds 时返回 empty `Box3`。 |
|
|
201
|
+
| `setFacilityVisible(visible)` | 设置单个设备引用的 `visible`,并返回自身;渲染和射线检测都会跳过不可见引用。 |
|
|
202
|
+
| `setFacilityColor(color)` | 设置单个设备的颜色 override,并返回自身。`color` 支持 Three.js `ColorRepresentation`。 |
|
|
203
|
+
| `resetFacilityColor()` | 清除颜色 override,恢复使用源材质颜色,并返回自身;不会清除透明度 override。 |
|
|
204
|
+
| `setFacilityOpacity(opacity)` | 设置单个设备透明度,并返回自身;值会被限制在 `0..1`。 |
|
|
205
|
+
| `getFacilityColor(target?)` | 读取当前颜色 override;没有 override 时返回白色 `(1, 1, 1)`。 |
|
|
206
|
+
| `hasFacilityColor()` | 判断当前设备是否存在颜色 override。 |
|
|
207
|
+
| `getFacilityOpacity()` | 读取当前透明度 override。 |
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { Box3 } from 'three';
|
|
211
|
+
import { FacilityInstanceObject } from 'u-space/plugins/u-manager';
|
|
212
|
+
|
|
213
|
+
const box = new Box3();
|
|
214
|
+
const facility = floor.getFacilityById('FACILITY_001');
|
|
215
|
+
|
|
216
|
+
if (facility instanceof FacilityInstanceObject) {
|
|
217
|
+
facility
|
|
218
|
+
.setFacilityColor('#29ccff')
|
|
219
|
+
.setFacilityOpacity(0.6)
|
|
220
|
+
.setFacilityVisible(true);
|
|
221
|
+
|
|
222
|
+
await viewer.controls.flyToBox(facility.getFacilityBoundingBox(box, true), {
|
|
223
|
+
viewpoint: 'rightFrontTop',
|
|
224
|
+
padding: 0.2,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### `FacilityInstancedLayer`
|
|
230
|
+
|
|
231
|
+
`FacilityInstancedLayer` 继承自 `BaseGroup`,是 scene-level Facilities 的批量渲染层。`SemanticSceneGroup.facilityLayer` 默认就是该类型;它会按模型 URL 把同一模板的静态设备合并为一个或多个 `InstancedMesh`,并用普通 `Group` 包裹每个模型 URL batch,保证设备显隐、颜色、透明度和相机实例裁剪能在每帧渲染前同步,同时保留每个楼层下的 `FacilityInstanceObject` 引用用于业务 API 和事件冒泡。
|
|
232
|
+
|
|
233
|
+
使用 `SemanticLoader` 时通常不需要直接调用 `addFacilityBatch()`;只有自定义语义解析或自建设备 batch 时才需要手动创建 layer,然后通过 `semanticScene.setFacilityLayer(layer)` 挂回语义场景。
|
|
234
|
+
|
|
235
|
+
| 属性 / 方法 | 说明 |
|
|
236
|
+
| :---------- | :--- |
|
|
237
|
+
| `isFacilityInstancedLayer` | 类型标记,值为 `true`。 |
|
|
238
|
+
| `type` | Three.js 对象类型名,值为 `'FacilityInstancedLayer'`。 |
|
|
239
|
+
| `name` | 构造函数默认设为 `'Facilities'`。 |
|
|
240
|
+
| `getInstanceCulling()` | 返回当前实例裁剪配置:`enabled`、`frustum`、`minScreenRadius`。 |
|
|
241
|
+
| `setInstanceCulling(options)` | 设置实例裁剪配置,并返回自身。默认 `enabled: false`、`frustum: true`、`minScreenRadius: 0`;默认不按相机裁剪设备,避免相机距离影响设备显隐。需要性能压缩时可设置 `enabled: true` 开启视锥裁剪,或再把 `minScreenRadius` 设为大于 0 的值开启屏幕尺寸裁剪。 |
|
|
242
|
+
| `addFacilityBatch(url, template, facilities)` | 尝试把同一模型 URL 的设备引用合并为 instanced batch。成功返回 `true`,失败返回 `false`,失败时调用方应回退为普通模型渲染。 |
|
|
243
|
+
|
|
244
|
+
`addFacilityBatch(url, template, facilities)` 会从 `template` 收集可 instancing 的可见 `Mesh`,克隆源材质,并为每个 batch 建立 instance matrix、颜色和透明度 attribute。没有动画、没有骨骼、没有 morph target,且每个多材质 `Mesh` 都有合法 `geometry.groups` 的模板会进入 instancing;不满足条件、模板没有可用 Mesh 或 `facilities` 为空时会返回 `false`。
|
|
245
|
+
|
|
246
|
+
渲染前,layer 会同步每个 `FacilityInstanceObject` 的世界矩阵、颜色和透明度,并只在数据变化时上传对应 buffer。默认情况下,相机移动不会改变设备 active instance 集合;显式调用 `setInstanceCulling({ enabled: true })` 后,layer 才会按当前渲染相机逐实例压缩 `InstancedMesh.count`,视锥外设备不会进入本帧实例 buffer;只有同时设置 `minScreenRadius > 0` 时,屏幕半径小于该阈值的设备才会被跳过。相机矩阵、投影矩阵或 viewport 高度未变化时不会重复压缩;设备显隐、透明度为 0、颜色/透明度变化或 `planish('Facilities')` / `unplanish('Facilities')` 改变 transform 时会标记 batch dirty。全部设备不可渲染时,内部 `InstancedMesh.visible` 会被关闭;只有被当前相机裁掉时,mesh 会保留可见并把 `count` 设为 0,以便相机移动后自动恢复。射线检测命中 batch 内实例时,`hit.object` 会被改写为对应的 `FacilityInstanceObject`,并附加 `facility`、`facilityId`、`semanticId`、`semanticKind: 'Facilities'`、`semanticName` 和 `semanticIndex`,事件随后会按楼层引用对象继续冒泡。
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { FacilityInstancedLayer, FacilityInstanceObject } from 'u-space/plugins/u-manager';
|
|
250
|
+
|
|
251
|
+
const layer = new FacilityInstancedLayer();
|
|
252
|
+
const refs = facilityItems.map(() => new FacilityInstanceObject());
|
|
253
|
+
|
|
254
|
+
if (layer.addFacilityBatch('/models/camera.glb', templateObject, refs)) {
|
|
255
|
+
semanticScene.setFacilityLayer(layer);
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
如果只想整体隐藏或禁用 scene-level batch,可以设置 `semanticScene.facilityLayer.visible = false`;如果只想控制单个设备,继续使用 `floor.showFacility(id)`、`semanticScene.setFacilityOpacity(id, opacity)` 或设备引用自身的 `setFacilityVisible()` / `setFacilityOpacity()`。
|
|
260
|
+
|
|
165
261
|
### `FloorMesh`
|
|
166
262
|
|
|
167
263
|
`FloorMesh` 继承自 `BaseMesh`,表示一个楼层。它不是 `BatchedMesh`,而是把同一楼层内的语义对象合并为一份几何,并通过 TSL + `DataTexture` 在 GPU 侧按 `semanticIndex` 控制颜色、透明度、显示隐藏和实例矩阵。楼层语义网格会按实例透明度拆分为不透明和透明两个材质通道;墙、柱、门等默认不透明实例会进入 opaque pipeline,`Spaces`、`Windows` 或通过 `setOpacityAt()` 改成半透明的实例会进入 transparent pipeline。Facilities 通过楼层下的引用对象进行检索和控制;实际渲染可能来自 `SemanticSceneGroup.facilityLayer` 的 `InstancedMesh` batch,也可能是 fallback 的普通 `Model`。
|
|
@@ -265,6 +361,10 @@ if (index !== undefined) {
|
|
|
265
361
|
## `SceneLoader`
|
|
266
362
|
|
|
267
363
|
从服务端场景包加载完整场景树(模型、组、形状、拉伸区域),并自动将所有已加载对象按 `id` 和 `sid` 注册到 `viewer.objectManager`。
|
|
364
|
+
默认会尝试读取同一路径下的 `db/semantic_model.json`,如果场景树节点的 `id` 已存在于语义文件中,则跳过该节点,方便和 `SemanticLoader` 同时加载而不重复创建建筑或设备。
|
|
365
|
+
对语义去重后仍保留的 3D 节点,`SceneLoader` 默认会按模型 `path` 自动合并重复静态模型:同一 `path` 的多个实例只加载一次模板,并由 `SceneInstancedLayer` 通过 `InstancedMesh` + `BundleGroup` 批量渲染。原场景树中仍会保留每个 `id` / `sid` 对应的 `SceneInstanceObject` 逻辑对象,用于业务检索、显隐、颜色、透明度、包围盒和事件派发。
|
|
366
|
+
|
|
367
|
+
模板包含动画、骨骼、morph target、材质数组或没有可实例化网格时,会自动回退为普通 `Model` 渲染;调用侧不需要额外配置。
|
|
268
368
|
|
|
269
369
|
```typescript
|
|
270
370
|
import { SceneLoader } from 'u-space/plugins/u-manager';
|
|
@@ -278,12 +378,49 @@ viewer.scene.add(group);
|
|
|
278
378
|
|
|
279
379
|
**方法:**
|
|
280
380
|
|
|
281
|
-
| 方法
|
|
282
|
-
|
|
|
283
|
-
| `setKey(key)`
|
|
284
|
-
| `loadAsync()`
|
|
285
|
-
| `clearCache()`
|
|
286
|
-
| `dispose()`
|
|
381
|
+
| 方法 | 说明 |
|
|
382
|
+
| :------------------ | :------------------------------------------------------------------- |
|
|
383
|
+
| `setKey(key)` | 设置授权场景的 RSA 解密密钥。 |
|
|
384
|
+
| `loadAsync()` | 加载并解析场景,返回去除语义重复节点后的 `Group`。 |
|
|
385
|
+
| `clearCache()` | 从 `objectManager` 中移除此加载器注册的所有 ID。 |
|
|
386
|
+
| `dispose()` | 清除缓存并释放水印叠加层。 |
|
|
387
|
+
|
|
388
|
+
### `SceneInstanceObject`
|
|
389
|
+
|
|
390
|
+
`SceneInstanceObject` 继承自 Three.js `Group`,表示一个由 `SceneInstancedLayer` 批量渲染的场景模型引用。它会保留在原场景树层级中,并注册到 `viewer.objectManager`,因此 `getById()`、`show()` / `hide()`、`isolate()`、`showAll()`、`setOpacity()` 和 `getBoundingBox()` 可以继续按单个模型 ID 使用。
|
|
391
|
+
|
|
392
|
+
可用方法包括 `setSceneInstanceVisible(visible)`、`setSceneInstanceColor(color)`、`resetSceneInstanceColor()`、`setSceneInstanceOpacity(opacity)`、`getSceneInstanceOpacity()`、`getSceneInstanceBoundingBox(target?, world?)` 和 `markSceneInstanceRenderDirty()`。`MaterialEffects.highlightColor()` / `removeHighlightColor()` 也会识别该逻辑对象并写入 per-instance color / opacity。
|
|
393
|
+
|
|
394
|
+
加载完成后可以按场景树节点 `id` 从 `objectManager` 取回 `SceneInstanceObject` 并直接传给 `viewer.controls.flyToObject()`。`SceneInstanceObject` 内部带有不可见的本地 bounds,因此不需要加载真实 Mesh 副本也能计算飞行包围盒。
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
import { SceneInstanceObject } from 'u-space/plugins/u-manager';
|
|
398
|
+
|
|
399
|
+
const object = viewer.objectManager.getById<SceneInstanceObject>('SCENE_NODE_ID');
|
|
400
|
+
|
|
401
|
+
if (object?.isSceneInstanceObject) {
|
|
402
|
+
await viewer.controls.flyToObject(object, {
|
|
403
|
+
viewpoint: 'current',
|
|
404
|
+
padding: 0.2,
|
|
405
|
+
enableTransition: true,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
如果需要自己控制包围盒,也可以取世界包围盒后调用 `flyToBox()`:
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
import { Box3 } from 'three/webgpu';
|
|
414
|
+
|
|
415
|
+
const box = object.getSceneInstanceBoundingBox(new Box3(), true);
|
|
416
|
+
await viewer.controls.flyToBox(box, { viewpoint: 'frontTop', padding: 0.2 });
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
射线检测命中批处理实例时,`intersect.object` 会被改写为对应的 `SceneInstanceObject`,并附加 `sceneInstance`、`sceneInstanceId` 和 `sceneInstanceIndex`,事件会按逻辑对象所在的原场景树继续冒泡。
|
|
420
|
+
|
|
421
|
+
### `SceneInstancedLayer`
|
|
422
|
+
|
|
423
|
+
`SceneInstancedLayer` 是 `SceneLoader` 内部使用的批量渲染层,默认 `name = 'SceneInstances'`。每个重复模型 URL 会生成一个 `BundleGroup` batch,batch 内按模板的可实例化 Mesh 创建 `InstancedMesh`。渲染前只在实例矩阵、显隐、颜色或透明度变化时同步 instance buffer;普通相机移动不会重新上传所有实例数据。
|
|
287
424
|
|
|
288
425
|
## `TopologiesLoader` / `TopologyParser`
|
|
289
426
|
|
package/docs/api-tools.md
CHANGED
|
@@ -221,7 +221,7 @@ annotationManager.add('label-01', {
|
|
|
221
221
|
| `labelOffset` | `{x, y, z}` | `{0, 2, 0}` | 标签相对锚点的偏移。 |
|
|
222
222
|
| `showLeaderLine` | `boolean` | `true` | 是否显示引线。 |
|
|
223
223
|
| `lineColor` | `ColorRepresentation` | `0xffffff` | 引线颜色。 |
|
|
224
|
-
| `labelStyle` | `
|
|
224
|
+
| `labelStyle` | `AnnotationLabelStyle` | — | 自定义 CSS 样式。 |
|
|
225
225
|
|
|
226
226
|
### `addText(text, position, options?)`
|
|
227
227
|
|
package/docs/changelog.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## 未发布
|
|
4
4
|
|
|
5
|
+
### 变更
|
|
6
|
+
|
|
7
|
+
- **u-manager semantics** — `FacilityInstancedLayer` 的相机逐实例裁剪改为显式开启:默认不再按当前相机视锥或 `minScreenRadius` 压缩 active instances,避免相机距离影响设备显隐;需要性能压缩时可通过 `setInstanceCulling({ enabled: true })` 开启。
|
|
8
|
+
- **u-manager semantics** — `FacilityInstancedLayer` 使用动态 `Group` 包裹 Facilities `InstancedMesh` batch,避免 Three.js WebGPU render bundle 缓存跳过子 mesh 的渲染前同步;`hideAllFacilities()` 后再 `showAllFacilities()` 不会复用过期 active instance 状态。
|
|
9
|
+
- **u-manager semantics** — `FacilityInstancedLayer` 支持合法 `material[]` + `geometry.groups` 的设备模板进入 instancing;只有 groups 缺失或材质索引非法的多材质 Mesh 才回退为普通 `Model`。
|
|
10
|
+
- **u-manager semantics** — Facilities instancing 会在相机矩阵、投影矩阵或 viewport 高度变化时重新压缩当前帧实例;设备显隐、颜色、透明度和 `planish('Facilities')` / `unplanish('Facilities')` 改变 transform 时刷新 instance data。
|
|
11
|
+
- **u-manager semantics** — 全部设备隐藏或透明度为 0 时,`FacilityInstancedLayer` 会关闭空的内部 `InstancedMesh`;通过 `showAllFacilities()` 或单设备 API 恢复时会重新加入渲染同步。
|
|
12
|
+
- **fire 插件** — 新增 `FireEffect`,封装 Three.js 官方 `webgpu_volume_fire` 体积火焰示例,支持 WebGPU 3D 流体模拟、烟雾散射、动态光照、体积阴影、output effect 叠加和 `cameraChange` 相机切换同步。
|
|
13
|
+
- **u-manager loader** — `SceneLoader` 默认读取同路径 `db/semantic_model.json` 并按语义 `ID` 跳过重复场景树节点,支持与 `SemanticLoader` 同时加载。
|
|
14
|
+
- **u-manager loader** — `SceneLoader` 默认按模型 `path` 合并重复静态 3D 节点,通过 `SceneInstancedLayer` 批量渲染,同时保留 `SceneInstanceObject` 逻辑对象用于单模型 ID 检索、显隐、颜色、透明度、包围盒和事件派发。
|
|
15
|
+
- **docs/mcp** — 补充 `SceneInstanceObject` 通过 `objectManager.getById()` + `controls.flyToObject()` 飞向单个 path-instanced 场景模型、`FacilityInstanceObject` 通过 `getFacilityBoundingBox()` + `controls.flyToBox()` 飞向单个设备的示例与 MCP 检索说明。
|
|
16
|
+
- **ObjectManager / MaterialEffects** — `setOpacity()`、`show()` / `hide()`、`isolate()`、`showAll()` 以及 `highlightColor()` / `removeHighlightColor()` 支持 `SceneInstanceObject` 的 per-instance 控制。
|
|
17
|
+
- **u-manager loader** — `SceneLoader` 创建的根组、`GROUP` 和 `STUB` 节点改为 `BaseGroup`,隐藏后可通过对象自身 `raycast()` 返回值阻止子级继续参与递归射线检测。
|
|
18
|
+
- **Viewer** — 默认使用 Three.js `reversedDepthBuffer` 替代 `logarithmicDepthBuffer`,减少 WebGPU 顶视角多层透明场景的 fragment 压力,同时保留远距离深度精度。
|
|
19
|
+
|
|
20
|
+
## 0.0.26
|
|
21
|
+
|
|
5
22
|
### 修复
|
|
6
23
|
|
|
7
24
|
- **u-manager semantics** — `FloorMesh.planish()` 会在压平后的语义实例和 Facilities 上加入稳定的轻微 Y 偏移,减少门、墙等重叠薄片之间的共面闪烁。
|
|
@@ -13,6 +30,10 @@
|
|
|
13
30
|
- **MaterialEffects** — 高亮、呼吸色、线框和淡入淡出效果支持材质数组,确保多材质 Mesh 和 `FloorMesh` 双材质通道都能正确应用并恢复材质状态。
|
|
14
31
|
- **docs/mcp** — 补充 Facilities auto instancing 的动态材质透明度、包围盒视锥裁剪、`controls.flyToBox()` 飞向设备,以及多材质 fallback 对颜色/透明度 override 的支持说明。
|
|
15
32
|
|
|
33
|
+
### 示例与文档
|
|
34
|
+
|
|
35
|
+
- **在线示例** — `examples/importmap.js` 的 CDN fallback 版本更新为 `0.0.26`,Vercel 部署会继续按 `package.json` 注入当前版本。
|
|
36
|
+
|
|
16
37
|
## 0.0.25
|
|
17
38
|
|
|
18
39
|
### 新增
|
package/docs/examples-guide.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 运行方式与版本
|
|
6
6
|
|
|
7
|
-
示例统一通过 `examples/importmap.js` 注入 Import Map。本地通过 `localhost`、`127.0.0.1`、`0.0.0.0` 或 `192.168.x.x` 访问时会加载仓库里的 `../dist/` 构建产物;在线部署或非本地域名访问时会从 jsDelivr 加载当前发布版本 `u-space@0.0.
|
|
7
|
+
示例统一通过 `examples/importmap.js` 注入 Import Map。本地通过 `localhost`、`127.0.0.1`、`0.0.0.0` 或 `192.168.x.x` 访问时会加载仓库里的 `../dist/` 构建产物;在线部署或非本地域名访问时会从 jsDelivr 加载当前发布版本 `u-space@0.0.26`。Vercel 文档部署会继续把 `__VERSION__` 占位符替换为 `package.json` 中的版本号,源码里的 `0.0.26` 作为直接托管 `examples/` 时的 fallback。
|
|
8
8
|
|
|
9
9
|
插件示例可以在页面加载 `importmap.js` 前通过 `window.__IMPORTS__` 声明额外依赖。将 `u-space/plugins/<name>` 的值设为 `true` 时,`importmap.js` 会自动在本地和 CDN 路径之间切换。
|
|
10
10
|
|
|
@@ -197,3 +197,15 @@
|
|
|
197
197
|
- 支持 4 种预设:`indoor`(室内)、`outdoor`(室外)、`studio`(摄影棚)、`warehouse`(仓库)。
|
|
198
198
|
- 使用 `showAllHelpers()` / `hideAllHelpers()` 显示或隐藏灯光辅助可视化。
|
|
199
199
|
- 每种预设会自动清除旧灯光并创建新的灯光组合。
|
|
200
|
+
|
|
201
|
+
## 17. `test_fire.html`:WebGPU 体积火焰
|
|
202
|
+
|
|
203
|
+
该示例演示了 `u-space/plugins/fire` 的 `FireEffect` 插件,封装 Three.js 官方体积火焰示例,在独立 volumetric pass 中模拟火焰和烟雾后叠加到主场景。
|
|
204
|
+
|
|
205
|
+
### 核心要点:
|
|
206
|
+
|
|
207
|
+
- 使用 `FireEffect` 创建 WebGPU 体积火焰、烟雾、扰动、动态点光源和体积阴影。
|
|
208
|
+
- 通过 `position` 和 `size` 设置体积盒底部中心和烟雾扩散约束范围。
|
|
209
|
+
- 默认使用 `TeapotGeometry(0.8, 28)` 作为 emitter;也可以传入业务 `Object3D` 和自定义 `emitterGeometry`。
|
|
210
|
+
- 通过 `fire.update()` 实时调整 `fireIntensity`、`smokeLifespan`、`emitterRadius` 等参数。
|
|
211
|
+
- 插件使用 RenderPipeline output effect 接入,不占用业务侧的 `setOutputComposer()`。
|
package/docs/getting-started.md
CHANGED
|
@@ -125,7 +125,7 @@ box.addEventListener('pointerleave', (e) => {
|
|
|
125
125
|
|
|
126
126
|
```typescript
|
|
127
127
|
import { version } from 'u-space';
|
|
128
|
-
console.log(version); // e.g. '0.0.
|
|
128
|
+
console.log(version); // e.g. '0.0.26'
|
|
129
129
|
|
|
130
130
|
// 也可以通过全局变量访问
|
|
131
131
|
console.log(window.__USPACE__.version);
|
package/docs/index.md
CHANGED
|
@@ -56,6 +56,7 @@ features:
|
|
|
56
56
|
| [curve-movement](./api-plugin-curve-movement) | 沿样条曲线移动相机或对象 |
|
|
57
57
|
| [tracking-controls](./api-plugin-tracking-controls) | 相机跟随移动目标 |
|
|
58
58
|
| [atmosphere](./api-plugin-atmosphere) | 天空背景、天空环境、太阳/月亮光照与阴影 |
|
|
59
|
+
| [fire](./api-plugin-fire) | WebGPU 体积火焰、烟雾、湍流、动态光照与阴影 |
|
|
59
60
|
| [object-controls](./api-plugin-object-controls) | 交互式移动、旋转、缩放 3D 对象 |
|
|
60
61
|
| [topology-drawer](./api-plugin-topology-drawer) | 在场景任意表面交互式绘制拓扑路径图 |
|
|
61
62
|
|