u-space-mcp 0.0.1
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 +40 -0
- package/dist/generated/docs-index.d.ts +13 -0
- package/dist/generated/docs-index.js +1367 -0
- package/dist/generated/docs-index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +269 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,1367 @@
|
|
|
1
|
+
export const docsIndex = [
|
|
2
|
+
{
|
|
3
|
+
"id": "api-animations",
|
|
4
|
+
"path": "api-animations.md",
|
|
5
|
+
"title": "Animations API",
|
|
6
|
+
"summary": "`u-space` 提供了 `Tween` 类和 `tweenAnimation` 辅助函数,用于对任意数值属性进行动画处理。两者都是对 [`@tweenjs/tween.js`](https://github.com/tweenjs/tween.js) 的轻量封装,并自动与 `Viewer` 渲染循环集成。 对任意对象属性执行动画的最简方式,返回一个在动画完成后 resolve 的 `Promise`。 ```typescript",
|
|
7
|
+
"headings": [
|
|
8
|
+
{
|
|
9
|
+
"level": 1,
|
|
10
|
+
"text": "Animations API"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"level": 2,
|
|
14
|
+
"text": "tweenAnimation"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"level": 3,
|
|
18
|
+
"text": "AnimationOptions"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"level": 3,
|
|
22
|
+
"text": "AnimationModeType"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"level": 2,
|
|
26
|
+
"text": "Tween"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"level": 3,
|
|
30
|
+
"text": "方法"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"content": "# Animations API\n\n`u-space` 提供了 `Tween` 类和 `tweenAnimation` 辅助函数,用于对任意数值属性进行动画处理。两者都是对 [`@tweenjs/tween.js`](https://github.com/tweenjs/tween.js) 的轻量封装,并自动与 `Viewer` 渲染循环集成。\n\n## `tweenAnimation`\n\n对任意对象属性执行动画的最简方式,返回一个在动画完成后 resolve 的 `Promise`。\n\n```typescript\nimport { tweenAnimation } from 'u-space';\n\nconst source = { x: 0, y: 0, z: 0 };\n\nawait tweenAnimation(\n viewer,\n source, // 可变的起始状态(每帧被修改)\n { x: 10, y: 5, z: 10 }, // 目标状态\n {\n duration: 1500, // 毫秒\n delay: 0,\n mode: 'Cubic.InOut',\n repeat: false,\n yoyo: false,\n },\n (current) => {\n // 每帧以插值结果调用\n myObject.position.set(current.x, current.y, current.z);\n },\n);\n```\n\n### `AnimationOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :--------- | :-------------------------- | :-------------- | :------------------------------------------------- |\n| `duration` | `number` | `1000` | 动画时长(毫秒)。 |\n| `delay` | `number` | `0` | 开始延迟(毫秒)。 |\n| `mode` | `AnimationModeType` | `'Linear.None'` | 缓动函数。 |\n| `repeat` | `number \\| boolean` | `false` | 额外重复次数,或 `true` 表示无限循环。 |\n| `yoyo` | `boolean` | `false` | 在每个循环周期反向播放。 |\n\n### `AnimationModeType`\n\n支持所有标准缓动模式:\n\n`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`\n\n## `Tween`\n\n提供完全控制的底层类。继承自 `tween.js` 的基础 `Tween`,并通过 `addEventListener('afterControlsUpdate', ...)` 挂入 `Viewer` 事件循环。\n\n```typescript\nimport { Tween } from 'u-space';\n\nconst source = { opacity: 1 };\n\nconst tween = new Tween(viewer, source)\n .to({ opacity: 0 }, 800)\n .easingByMode('Sinusoidal.Out')\n .onUpdate((s) => {\n myMaterial.opacity = s.opacity;\n viewer.render();\n })\n .onComplete(() => console.log('完成'));\n\ntween.start();\n// tween.stop();\n```\n\n### 方法\n\n| 方法 | 说明 |\n| :------------------------ | :-------------------------------------------------------------- |\n| `easingByMode(mode)` | 使用 `AnimationModeType` 设置缓动函数的便捷简写。 |\n| `start(time?)` | 启动补间并注册到 viewer 循环中。 |\n| `stop()` | 停止补间并从 viewer 循环中注销。 |\n\n其他方法(`to`、`delay`、`repeat`、`yoyo`、`onUpdate`、`onComplete`、`onStop`、`onStart`)均继承自 `tween.js` 的基础 `Tween` 类。\n"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "api-camera-controls",
|
|
37
|
+
"path": "api-camera-controls.md",
|
|
38
|
+
"title": "CameraControls API",
|
|
39
|
+
"summary": "`CameraControls` 是 `u-space` 对 [`camera-controls`](https://github.com/yomotsu/camera-controls) 库的扩展封装,提供相机飞行、视角切换等高级功能。通过 `viewer.controls` 访问。 > 更多基础属性和方法请参考 [camera-controls 文档](https://github.com/yomotsu/camera-controls)。 将相机飞行到指定的 `Box3` 包围盒。",
|
|
40
|
+
"headings": [
|
|
41
|
+
{
|
|
42
|
+
"level": 1,
|
|
43
|
+
"text": "CameraControls API"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"level": 2,
|
|
47
|
+
"text": "默认配置"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"level": 2,
|
|
51
|
+
"text": "方法"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"level": 3,
|
|
55
|
+
"text": "flyToBox(box, options?)"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"level": 4,
|
|
59
|
+
"text": "FlyToBoxOptions"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"level": 3,
|
|
63
|
+
"text": "flyToObject(object, options?)"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"level": 3,
|
|
67
|
+
"text": "setCameraViewpoint(viewpoint, enableTransition?)"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"level": 4,
|
|
71
|
+
"text": "CameraViewpointData"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"level": 3,
|
|
75
|
+
"text": "flyTo(position, target, options?)"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"level": 3,
|
|
79
|
+
"text": "getCameraViewpoint()"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"level": 3,
|
|
83
|
+
"text": "lock() / unlock()"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"level": 3,
|
|
87
|
+
"text": "setViewMode(mode, enableTransition?)"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"level": 3,
|
|
91
|
+
"text": "absoluteRotations()"
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
"content": "# CameraControls API\n\n`CameraControls` 是 `u-space` 对 [`camera-controls`](https://github.com/yomotsu/camera-controls) 库的扩展封装,提供相机飞行、视角切换等高级功能。通过 `viewer.controls` 访问。\n\n## 默认配置\n\n| 属性 | 默认值 | 说明 |\n| :------------ | :----- | :----------------------------- |\n| `minDistance` | `0.2` | 相机最小缩放距离。 |\n| `smoothTime` | `0.2` | 平滑过渡时间(秒)。 |\n| `dollySpeed` | `0.2` | 滚轮缩放速度。 |\n\n> 更多基础属性和方法请参考 [camera-controls 文档](https://github.com/yomotsu/camera-controls)。\n\n## 方法\n\n### `flyToBox(box, options?)`\n\n将相机飞行到指定的 `Box3` 包围盒。\n\n```typescript\nimport { Box3 } from 'three/webgpu';\n\nconst box = new Box3().setFromObject(myModel);\nawait viewer.controls.flyToBox(box, {\n viewpoint: 'frontTop',\n enableTransition: true,\n padding: 0.1,\n});\n```\n\n#### `FlyToBoxOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :----------------- | :-------- | :----------- | :------------------------------------------------ |\n| `viewpoint` | `string` | `'frontTop'` | 预设视角方向,见下方视角列表。设为 `'current'` 保持当前朝向。 |\n| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |\n| `padding` | `number` | `0.1` | 包围盒四周的留白比例。 |\n| `cover` | `boolean` | `false` | 是否以覆盖模式适配(类似 CSS `object-fit: cover`)。 |\n\n**预设视角:**\n\n`top` | `bottom` | `front` | `back` | `left` | `right` | `frontTop` | `backTop` | `leftTop` | `rightTop` | `leftFrontTop` | `rightFrontTop` | `leftBackTop` | `rightBackTop` | `current`\n\n### `flyToObject(object, options?)`\n\n将相机飞行到指定对象的包围盒。参数同 `flyToBox`。\n\n```typescript\nawait viewer.controls.flyToObject(myModel, { viewpoint: 'rightFrontTop' });\n```\n\n### `setCameraViewpoint(viewpoint, enableTransition?)`\n\n将相机平滑过渡到指定的位置、目标和缩放。\n\n```typescript\nawait viewer.controls.setCameraViewpoint({\n position: { x: 10, y: 5, z: 10 },\n target: { x: 0, y: 0, z: 0 },\n zoom: 1.0,\n});\n\n// 禁用过渡动画,立即跳转\nawait viewer.controls.setCameraViewpoint(viewpoint, false);\n```\n\n**参数:**\n\n| 参数 | 类型 | 默认值 | 说明 |\n| :----------------- | :--------------------- | :------ | :---------------------------------- |\n| `viewpoint` | `CameraViewpointData` | — | 包含 `position`、`target`、`zoom`。 |\n| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |\n\n#### `CameraViewpointData`\n\n| 属性 | 类型 | 说明 |\n| :--------- | :--------- | :------------------- |\n| `position` | `IVector3` | 相机位置。 |\n| `target` | `IVector3` | 相机注视目标位置。 |\n| `zoom` | `number` | 相机缩放值。 |\n\n### `flyTo(position, target, options?)`\n\n将相机飞行到指定的位置和注视目标。\n\n```typescript\nawait viewer.controls.flyTo(\n { x: 10, y: 8, z: 10 },\n { x: 0, y: 0, z: 0 },\n { enableTransition: true },\n);\n```\n\n**参数:**\n\n| 参数 | 类型 | 默认值 | 说明 |\n| :----------------- | :--------- | :----- | :---------------------- |\n| `position` | `IVector3` | — | 相机目标位置。 |\n| `target` | `IVector3` | — | 相机注视目标。 |\n| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |\n\n### `getCameraViewpoint()`\n\n获取当前相机的视角数据,返回 `CameraViewpointData`。与 `setCameraViewpoint` 对应,方便保存/恢复视角。\n\n```typescript\nconst viewpoint = viewer.controls.getCameraViewpoint();\nconsole.log(viewpoint.position, viewpoint.target, viewpoint.zoom);\n\n// 稍后恢复\nawait viewer.controls.setCameraViewpoint(viewpoint);\n```\n\n### `lock()` / `unlock()`\n\n锁定或解锁相机控制(禁用/启用所有用户交互)。\n\n```typescript\nviewer.controls.lock(); // 禁止用户操作相机\nviewer.controls.unlock(); // 恢复用户操作\n```\n\n### `setViewMode(mode, enableTransition?)`\n\n在 2D 俯视图和 3D 透视图之间切换。2D 模式会将相机旋转到正上方,并锁定极角。\n\n```typescript\nawait viewer.controls.setViewMode('2d'); // 切换到 2D 俯视模式\nawait viewer.controls.setViewMode('3d'); // 切换回 3D 模式\n```\n\n**参数:**\n\n| 参数 | 类型 | 默认值 | 说明 |\n| :----------------- | :---------------- | :----- | :---------------------- |\n| `mode` | `'2d'` \\| `'3d'` | — | 视图模式。 |\n| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |\n\n### `absoluteRotations()`\n\n将方位角(azimuth)归一化到 `[-π, π]` 范围内,避免相机在飞行过渡时产生多余旋转。在 `flyToBox` 内部自动调用。\n\n```typescript\nviewer.controls.absoluteRotations();\n```\n"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"id": "api-css-renderer",
|
|
98
|
+
"path": "api-css-renderer.md",
|
|
99
|
+
"title": "CSSRenderer API",
|
|
100
|
+
"summary": "`viewer.cssRenderer` 用于在 3D 场景中叠加渲染 HTML 元素。支持三种模式: 底层渲染器采用**懒加载**:首次调用对应 `create` 方法时才初始化 `CSS2DRenderer` 或 `CSS3DRenderer`,不使用则无开销。 创建的对象是标准 Three.js `Object3D`,直接添加到场景中即可:",
|
|
101
|
+
"headings": [
|
|
102
|
+
{
|
|
103
|
+
"level": 1,
|
|
104
|
+
"text": "CSSRenderer API"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"content": "# CSSRenderer API\n\n`viewer.cssRenderer` 用于在 3D 场景中叠加渲染 HTML 元素。支持三种模式:\n\n| 模式 | 方法 | 返回类型 | 说明 |\n| :--- | :--- | :------- | :--- |\n| CSS2D | `createCSS2DObject(element)` | `CSS2DObject` | HTML 元素始终面向相机,屏幕尺寸固定不随距离缩放。适合标签、工具提示。 |\n| CSS2.5D | `createCSS25DObject(element)` | `CSS3DSprite` | HTML 元素面向相机,但尺寸随距离缩放(近大远小)。 |\n| CSS3D | `createCSS3DObject(element)` | `CSS3DObject` | HTML 元素具有完整的 3D 变换,可旋转、缩放,参与透视投影。适合面板、信息板。 |\n\n底层渲染器采用**懒加载**:首次调用对应 `create` 方法时才初始化 `CSS2DRenderer` 或 `CSS3DRenderer`,不使用则无开销。\n\n创建的对象是标准 Three.js `Object3D`,直接添加到场景中即可:\n\n```typescript\n// CSS2D 标签\nconst labelEl = document.createElement('div');\nlabelEl.textContent = '标签';\nlabelEl.style.cssText = 'background:rgba(0,0,0,0.7);color:#fff;padding:4px 8px;border-radius:4px;font-size:13px;';\nconst label = viewer.cssRenderer.createCSS2DObject(labelEl);\nlabel.position.set(0, 2, 0);\nviewer.scene.add(label);\n\n// CSS2.5D 精灵(需设置 scale,通常 0.01 左右)\nconst spriteEl = document.createElement('div');\nspriteEl.textContent = '精灵';\nconst sprite = viewer.cssRenderer.createCSS25DObject(spriteEl);\nsprite.position.set(3, 2, 0);\nsprite.scale.setScalar(0.01);\nviewer.scene.add(sprite);\n\n// CSS3D 面板(需设置 scale,通常 0.01 左右)\nconst panelEl = document.createElement('div');\npanelEl.innerHTML = '<h3>面板</h3><p>3D 空间中的 HTML</p>';\nconst panel = viewer.cssRenderer.createCSS3DObject(panelEl);\npanel.position.set(0, 1.5, -3);\npanel.scale.setScalar(0.01);\nviewer.scene.add(panel);\n```\n\n> `CSSRenderer` 的生命周期(渲染、缩放、销毁)已自动集成到 `Viewer` 中,无需手动调用。\n\n同时从 `u-space` 包中导出了 `CSS2DObject`、`CSS3DObject`、`CSS3DSprite` 类型,供直接使用。\n"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "api-effects",
|
|
111
|
+
"path": "api-effects.md",
|
|
112
|
+
"title": "Effects API",
|
|
113
|
+
"summary": "`u-space` 提供了两个基于 Three.js 着色语言(TSL/WebGPU 节点)的静态特效工具:`MaterialEffects` 用于为对象应用高亮、呼吸等材质特效,`TSLEffects` 用于生成动态颜色节点模式。 静态工具类,将基于 TSL 的视觉特效直接应用于对象的材质。适用于任何 `Object3D`(支持单个或数组),会自动遍历所有子网格。 特性:",
|
|
114
|
+
"headings": [
|
|
115
|
+
{
|
|
116
|
+
"level": 1,
|
|
117
|
+
"text": "Effects API"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"level": 2,
|
|
121
|
+
"text": "MaterialEffects"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"level": 3,
|
|
125
|
+
"text": "MaterialEffects.highlightColor(object, options?)"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"level": 4,
|
|
129
|
+
"text": "HighlightColorOptions"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"level": 3,
|
|
133
|
+
"text": "MaterialEffects.removeHighlightColor(object)"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"level": 3,
|
|
137
|
+
"text": "MaterialEffects.breatheColor(object, options?)"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"level": 4,
|
|
141
|
+
"text": "BreatheColorOptions"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"level": 3,
|
|
145
|
+
"text": "MaterialEffects.removeBreatheColor(object)"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"level": 3,
|
|
149
|
+
"text": "MaterialEffects.wireframe(object, enabled?)"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"level": 3,
|
|
153
|
+
"text": "MaterialEffects.fadeIn(object, options?) / MaterialEffects.fadeOut(object, options?)"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"level": 4,
|
|
157
|
+
"text": "FadeOptions"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"level": 2,
|
|
161
|
+
"text": "TSLEffects"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"level": 3,
|
|
165
|
+
"text": "TSLEffects.flow(parameters?)"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"level": 3,
|
|
169
|
+
"text": "TSLEffects.breathe(parameters?)"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"level": 3,
|
|
173
|
+
"text": "TSLEffects.fluid(parameters?)"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"content": "# Effects API\n\n`u-space` 提供了两个基于 Three.js 着色语言(TSL/WebGPU 节点)的静态特效工具:`MaterialEffects` 用于为对象应用高亮、呼吸等材质特效,`TSLEffects` 用于生成动态颜色节点模式。\n\n## `MaterialEffects`\n\n静态工具类,将基于 TSL 的视觉特效直接应用于对象的材质。适用于任何 `Object3D`(支持单个或数组),会自动遍历所有子网格。\n\n特性:\n- **效果可叠加**:高亮和呼吸效果可同时作用于同一对象,呼吸在高亮结果之上混合\n- **共享材质安全**:按材质跟踪引用计数,多个 Mesh 共享材质时互不干扰\n- **完整还原**:移除效果时自动恢复材质原始的 `colorNode`、`opacityNode`、`transparent` 和 `depthWrite` 状态\n\n### `MaterialEffects.highlightColor(object, options?)`\n\n为对象中所有网格应用颜色/透明度高亮。\n\n```typescript\nimport { MaterialEffects } from 'u-space';\n\n// 以 50% 透明度高亮为红色(叠加模式)\nMaterialEffects.highlightColor(myModel, {\n color: 0xff0000,\n opacity: 0.5,\n overwrite: false, // false = 叠加(相乘),true = 完全替换颜色\n});\n\n// 半透明效果\nMaterialEffects.highlightColor(myModel, { opacity: 0.3 });\n\n// X 光效果(替换颜色 + 关闭深度写入)\nMaterialEffects.highlightColor(myModel, {\n color: 0x0088ff,\n opacity: 0.25,\n overwrite: true,\n depthWrite: false,\n});\n\n// 支持数组\nMaterialEffects.highlightColor([model1, model2], { color: 0x00ff00 });\n```\n\n#### `HighlightColorOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :---------- | :-------------------- | :---------- | :--------------------------------------------------------------------------- |\n| `color` | `ColorRepresentation` | `0xff0000` | 高亮颜色。 |\n| `opacity` | `number` | `0.5` | 高亮时材质的透明度。 |\n| `overwrite` | `boolean` | `false` | `false` = 与原始颜色相乘(叠加);`true` = 完全替换颜色。 |\n| `depthWrite` | `boolean` | — | 可选。设为 `false` 可产生 X 光透视效果。不设置时保持原始值。 |\n\n### `MaterialEffects.removeHighlightColor(object)`\n\n移除高亮效果。当对象上所有效果都被移除后,材质将完整恢复到原始状态。\n\n```typescript\nMaterialEffects.removeHighlightColor(myModel);\n```\n\n### `MaterialEffects.breatheColor(object, options?)`\n\n为对象应用呼吸灯效果,颜色在材质原色与目标颜色之间随时间脉冲变化。需要 `viewer.frameloop = 'always'`。\n\n```typescript\nMaterialEffects.breatheColor(myModel, {\n color: 0x00ff00,\n speed: 1.0,\n intensity: 2.0,\n});\nviewer.frameloop = 'always';\n```\n\n#### `BreatheColorOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :---------- | :-------------------- | :---------- | :--------------------------------- |\n| `color` | `ColorRepresentation` | `0x00ff00` | 呼吸目标颜色。 |\n| `speed` | `number` | `1.0` | 振荡速度。 |\n| `intensity` | `number` | `2.0` | 控制峰值的锐度。 |\n\n### `MaterialEffects.removeBreatheColor(object)`\n\n移除呼吸效果。\n\n```typescript\nMaterialEffects.removeBreatheColor(myModel);\n```\n\n### `MaterialEffects.wireframe(object, enabled?)`\n\n开启或关闭线框渲染模式。\n\n```typescript\nMaterialEffects.wireframe(myModel); // 开启线框\nMaterialEffects.wireframe(myModel, false); // 关闭线框\nMaterialEffects.removeWireframe(myModel); // 等同于 wireframe(obj, false)\n```\n\n### `MaterialEffects.fadeIn(object, options?)` / `MaterialEffects.fadeOut(object, options?)`\n\n淡入/淡出动画效果。返回 `Promise`,在动画完成后 resolve。淡出后对象材质保持透明状态。\n\n```typescript\n// 淡出\nawait MaterialEffects.fadeOut(myModel, { duration: 1000 });\n\n// 淡入\nawait MaterialEffects.fadeIn(myModel, { duration: 500 });\n```\n\n> 动画期间需要持续渲染,建议配合 `viewer.frameloop = 'always'` 使用。\n\n#### `FadeOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :--------- | :------- | :----- | :------------------ |\n| `duration` | `number` | `500` | 动画时长(毫秒)。 |\n\n---\n\n## `TSLEffects`\n\n静态工厂类,返回 TSL 颜色节点。将返回值赋给 `NodeMaterial` 的 `material.colorNode` 即可应用动态着色器特效。持续动画需要 `viewer.frameloop = 'always'`。\n\n### `TSLEffects.flow(parameters?)`\n\n沿网格 UV X 轴方向的定向光扫效果,适用于道路、管道和流线。\n\n```typescript\nimport { TSLEffects } from 'u-space';\n\nmyTubeMesh.material.colorNode = TSLEffects.flow({\n baseColor: 0x001133,\n flowColor: 0x00aaff,\n speed: 1.5,\n scale: 4.0,\n intensity: 6.0,\n});\nviewer.frameloop = 'always';\n```\n\n**参数:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :---------- | :-------------------- | :---------- | :------------------------------------------------ |\n| `baseColor` | `ColorRepresentation` | `0xffffff` | 背景/底色。 |\n| `flowColor` | `ColorRepresentation` | `0x00ff00` | 扫光高亮颜色。 |\n| `speed` | `number` | `1.0` | 动画速度(越高扫光越快)。 |\n| `scale` | `number` | `3.0` | 图案的空间频率。 |\n| `intensity` | `number` | `4.0` | 峰值锐度,值越高光束越细。 |\n\n### `TSLEffects.breathe(parameters?)`\n\n在两种颜色之间随时间振荡的脉冲发光效果,适合状态指示器和警报。\n\n```typescript\nmyMesh.material.colorNode = TSLEffects.breathe({\n baseColor: 0x333333,\n breathColor: 0x00ff88,\n speed: 2.0,\n intensity: 3.0,\n});\n```\n\n**参数:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :------------ | :-------------------- | :---------- | :--------------------------------- |\n| `baseColor` | `ColorRepresentation` | `0xffffff` | 低/静息状态的颜色。 |\n| `breathColor` | `ColorRepresentation` | `0x00ff00` | 峰值亮度时的颜色。 |\n| `speed` | `number` | `1.0` | 振荡速度。 |\n| `intensity` | `number` | `2.0` | 控制峰值的锐度。 |\n\n### `TSLEffects.fluid(parameters?)`\n\n噪声扭曲的流动效果,适用于水面、等离子体或有机流动材质。\n\n```typescript\nmyPlaneMesh.material.colorNode = TSLEffects.fluid({\n baseColor: 0x002244,\n flowColor: 0x0066ff,\n speed: 0.5,\n scale: 2.0,\n intensity: 1.5,\n distortion: 0.3,\n});\n```\n\n**参数:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :----------- | :-------------------- | :---------- | :-------------------------------------------- |\n| `baseColor` | `ColorRepresentation` | `0xffffff` | 基础颜色。 |\n| `flowColor` | `ColorRepresentation` | `0x0000ff` | 流体高亮颜色。 |\n| `speed` | `number` | `1.0` | 动画速度。 |\n| `scale` | `number` | `1.0` | 噪声图案的 UV 缩放比例。 |\n| `intensity` | `number` | `1.0` | 流体图案的锐度。 |\n| `distortion` | `number` | `0.5` | 采样前噪声对 UV 的扭曲程度。 |\n"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "api-interactions",
|
|
180
|
+
"path": "api-interactions.md",
|
|
181
|
+
"title": "Interactions API",
|
|
182
|
+
"summary": "`InteractionManager` 提供了一种统一的方式来处理 3D 场景中的用户输入(鼠标、触摸、指针)。它将屏幕空间的射线检测转换为世界空间坐标,并将对应事件直接分发到被命中的 3D 对象上。 `InteractionManager` 在 `Viewer` 内部自动实例化,可通过 `viewer.interactionManager` 访问。 出于性能考虑,指针移动事件默认处于禁用状态。如需悬停和拖拽效果,必须显式开启。",
|
|
183
|
+
"headings": [
|
|
184
|
+
{
|
|
185
|
+
"level": 1,
|
|
186
|
+
"text": "Interactions API"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"level": 2,
|
|
190
|
+
"text": "启用交互事件"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"level": 3,
|
|
194
|
+
"text": "目标对象"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"level": 2,
|
|
198
|
+
"text": "添加事件监听"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"level": 2,
|
|
202
|
+
"text": "支持的事件类型"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"level": 3,
|
|
206
|
+
"text": "事件冒泡"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"level": 2,
|
|
210
|
+
"text": "InteractionEvent"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"level": 3,
|
|
214
|
+
"text": "属性"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"level": 3,
|
|
218
|
+
"text": "方法"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"level": 4,
|
|
222
|
+
"text": "stopPropagation()"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"level": 2,
|
|
226
|
+
"text": "InteractionManager API"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"level": 3,
|
|
230
|
+
"text": "属性"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"level": 3,
|
|
234
|
+
"text": "方法"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"level": 4,
|
|
238
|
+
"text": "enable() / disable()"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"level": 4,
|
|
242
|
+
"text": "setInteractable(object, interactable)"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"level": 4,
|
|
246
|
+
"text": "addIgnore(object) / removeIgnore(object)"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"level": 4,
|
|
250
|
+
"text": "setCamera(camera)"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"level": 4,
|
|
254
|
+
"text": "dispose()"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"level": 2,
|
|
258
|
+
"text": "Selection"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"level": 3,
|
|
262
|
+
"text": "基础选择"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"level": 3,
|
|
266
|
+
"text": "属性"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"level": 3,
|
|
270
|
+
"text": "框选"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"level": 4,
|
|
274
|
+
"text": "BoxSelectionOptions"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"level": 3,
|
|
278
|
+
"text": "事件"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"level": 3,
|
|
282
|
+
"text": "方法"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"level": 4,
|
|
286
|
+
"text": "setCamera(camera)"
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"level": 4,
|
|
290
|
+
"text": "dispose()"
|
|
291
|
+
}
|
|
292
|
+
],
|
|
293
|
+
"content": "# Interactions API\n\n`InteractionManager` 提供了一种统一的方式来处理 3D 场景中的用户输入(鼠标、触摸、指针)。它将屏幕空间的射线检测转换为世界空间坐标,并将对应事件直接分发到被命中的 3D 对象上。\n\n`InteractionManager` 在 `Viewer` 内部自动实例化,可通过 `viewer.interactionManager` 访问。\n\n## 启用交互事件\n\n出于性能考虑,指针移动事件默认处于禁用状态。如需悬停和拖拽效果,必须显式开启。\n\n```typescript\n// 启用鼠标移动事件(如 pointerenter 和 pointerleave)\nviewer.interactionManager.pointerMoveEventsEnabled = true;\n```\n\n### 目标对象\n\n可以限制射线检测所针对的对象范围。默认值为 `scene.children`(即整个场景的直接子级,含递归嵌套)。\n\n```typescript\n// 仅检测指定对象\nviewer.interactionManager.targetObjects = [myBox, myModel];\n\n// 恢复默认:检测整个场景\nviewer.interactionManager.targetObjects = viewer.scene.children;\n```\n\n## 添加事件监听\n\n由于 `u-space` 对象(以及继承自 `BaseMesh`、`BaseGroup` 的对象)支持自定义事件,你可以像操作 DOM 元素一样原生地绑定监听器。\n\n```typescript\nconst myBox = new Mesh(geometry, material);\nviewer.scene.add(myBox);\n\n// 直接在 Mesh 或 Model 上绑定监听器\nmyBox.addEventListener('click', (eventData) => {\n // 底层指针事件和射线检测数据\n const intersect = eventData.event.intersect;\n\n console.log('点击位置:', intersect.point);\n});\n```\n\n## 支持的事件类型\n\n以下事件类型可在可交互对象上监听:\n\n- `click`:指针点击对象时触发。内置智能过滤:长按(>500ms)或移动距离过大时忽略,双击时不重复触发。\n- `dblclick`:快速双击对象时触发。\n- `rightclick`:右键短按松开时触发(长按或拖拽不触发;浏览器原生上下文菜单已被阻止)。在 `pointerup` 时派发,因此可以正确过滤相机拖拽等操作。\n- `pointerdown`:指针按键在对象上按下时触发。\n- `pointerup`:指针按键在对象上释放时触发。\n- `pointermove`:指针在对象上移动时触发,需要 `pointerMoveEventsEnabled = true`。\n- `pointerenter`:光标进入对象范围时触发,需要 `pointerMoveEventsEnabled = true`。\n- `pointerleave`:光标离开对象范围时触发,需要 `pointerMoveEventsEnabled = true`。\n\n### 事件冒泡\n\n事件会沿父级链向上冒泡。若要阻止事件继续传播,可调用事件载荷上的 `stopPropagation()`:\n\n```typescript\nmyObject.addEventListener('click', (e) => {\n e.event.stopPropagation();\n});\n```\n\n## `InteractionEvent`\n\n传递给所有监听回调的事件对象,位于 `event` 键下。\n\n### 属性\n\n| 属性 | 类型 | 说明 |\n| :-------------- | :----------------------------------------- | :-------------------------------------------------------------------------- |\n| `type` | `InteractionEventType` | 事件类型字符串(如 `'click'`)。 |\n| `target` | `Object3D` | 触发事件的原始 3D 对象(第一个命中点)。 |\n| `currentTarget` | `Object3D` | 冒泡链中当前处理事件的对象。 |\n| `intersect` | `Intersection \\| null` | Three.js 射线检测数据:`point`、`face`、`distance`、`uv` 等。 |\n| `originalEvent` | `PointerEvent \\| MouseEvent` | 原始 DOM 指针/鼠标事件。 |\n\n### 方法\n\n#### `stopPropagation()`\n\n阻止事件继续向上冒泡。\n\n## `InteractionManager` API\n\n### 属性\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :------------------------- | :---------------------------- | :---------------- | :--------------------------------------------------------- |\n| `targetObjects` | `Object3D[]` | `scene.children` | 射线检测的目标对象列表,默认为场景的直接子级。 |\n| `pointerMoveEventsEnabled` | `boolean` | `false` | 启用 `pointermove`、`pointerenter`、`pointerleave` 事件。 |\n\n### 方法\n\n#### `enable()` / `disable()`\n\n全局启用或禁用所有交互事件。禁用后不再触发任何交互事件。\n\n```typescript\nviewer.interactionManager.disable(); // 暂停交互\nviewer.interactionManager.enable(); // 恢复交互\n```\n\n#### `setInteractable(object, interactable)`\n\n控制单个对象是否可交互。设为 `false` 后该对象及其所有子对象不再参与射线检测。\n\n```typescript\nviewer.interactionManager.setInteractable(myModel, false); // 禁止交互\nviewer.interactionManager.setInteractable(myModel, true); // 恢复交互\n```\n\n#### `addIgnore(object)` / `removeIgnore(object)`\n\n`setInteractable` 的别名。`addIgnore(obj)` 等同于 `setInteractable(obj, false)`,`removeIgnore(obj)` 等同于 `setInteractable(obj, true)`。\n\n```typescript\nviewer.interactionManager.addIgnore(helperObject); // 忽略辅助对象\nviewer.interactionManager.removeIgnore(helperObject); // 恢复\n```\n\n#### `setCamera(camera)`\n\n更新用于射线检测的相机。由 `viewer.setCamera()` 自动调用。\n\n#### `dispose()`\n\n移除所有 DOM 事件监听,清理内部状态。\n\n```typescript\nviewer.interactionManager.dispose();\n```\n\n---\n\n## Selection\n\n`Selection` 提供对象选择能力,包括单选、多选、toggle 和框选(rubber-band)。\n\n```typescript\nimport { Selection } from 'u-space';\n\nconst selection = new Selection(viewer.renderer.domElement, viewer.scene, viewer.camera);\n```\n\n### 基础选择\n\n```typescript\nselection.select(myObject); // 选中\nselection.select([obj1, obj2]); // 多选\nselection.deselect(myObject); // 取消选择\nselection.toggle(myObject); // 切换选择状态\nselection.clear(); // 清空选择\nselection.isSelected(myObject); // 检查是否已选\n```\n\n### 属性\n\n| 属性 | 类型 | 说明 |\n| :-------------- | :-------------- | :---------------------------------- |\n| `selected` | `Set<Object3D>` | 当前已选对象集合。 |\n| `selectedArray` | `Object3D[]` | 当前已选对象数组。 |\n| `targetObjects` | `Object3D[]` | 框选时的候选对象(默认为场景子级)。 |\n\n### 框选\n\n启用后可用鼠标拖动矩形区域选择多个对象。框选覆盖层会渲染在容器元素上。\n\n```typescript\nselection.enableBoxSelection({ deep: true }); // 开启框选\nselection.disableBoxSelection(); // 关闭框选\n```\n\n#### `BoxSelectionOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :---------- | :-------- | :----- | :------------------------------ |\n| `className` | `string` | — | 框选矩形的 CSS 类名。 |\n| `deep` | `boolean` | `true` | 是否递归检测子对象。 |\n\n### 事件\n\n```typescript\nselection.addEventListener('select', (e) => {\n console.log('新选中:', e.objects);\n});\n\nselection.addEventListener('deselect', (e) => {\n console.log('取消选中:', e.objects);\n});\n\nselection.addEventListener('change', (e) => {\n console.log('当前选中:', e.selected.size, '个对象');\n});\n```\n\n### 方法\n\n#### `setCamera(camera)`\n\n更新用于框选投影计算的相机。切换相机时需调用。\n\n#### `dispose()`\n\n关闭框选、移除事件监听、清空选择集。\n"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"id": "api-managers",
|
|
297
|
+
"path": "api-managers.md",
|
|
298
|
+
"title": "Managers API",
|
|
299
|
+
"summary": "`u-space` 使用专用管理器来处理特定领域的逻辑,例如用于缓存和注册 3D 对象的 `ObjectManager`。 `ObjectManager` 提供了一个集中式字典/映射层,让你无需递归遍历 Three.js 场景图,就能通过字符串 ID 或字符串名称轻松检索复杂模型或特定网格。 默认实例可通过 `viewer.objectManager` 访问。",
|
|
300
|
+
"headings": [
|
|
301
|
+
{
|
|
302
|
+
"level": 1,
|
|
303
|
+
"text": "Managers API"
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"level": 2,
|
|
307
|
+
"text": "ObjectManager"
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"level": 3,
|
|
311
|
+
"text": "添加对象"
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"level": 3,
|
|
315
|
+
"text": "检索对象"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"level": 4,
|
|
319
|
+
"text": "getById(id: string)"
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"level": 4,
|
|
323
|
+
"text": "getByName(name: string)"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"level": 4,
|
|
327
|
+
"text": "getByType(type: string)"
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"level": 4,
|
|
331
|
+
"text": "getObjectIds(object: Object3D)"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"level": 3,
|
|
335
|
+
"text": "移除对象"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"level": 4,
|
|
339
|
+
"text": "remove(object: Object3D)"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"level": 4,
|
|
343
|
+
"text": "removeById(id: string)"
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"level": 4,
|
|
347
|
+
"text": "removeByName(name: string)"
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"level": 4,
|
|
351
|
+
"text": "removeByType(type: string)"
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"level": 3,
|
|
355
|
+
"text": "显隐控制"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"level": 4,
|
|
359
|
+
"text": "show(id: string) / hide(id: string)"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"level": 4,
|
|
363
|
+
"text": "isolate(ids: string[])"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"level": 4,
|
|
367
|
+
"text": "showAll()"
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"level": 3,
|
|
371
|
+
"text": "材质操作"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"level": 4,
|
|
375
|
+
"text": "setOpacity(id: string, opacity: number)"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"level": 3,
|
|
379
|
+
"text": "空间查询"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"level": 4,
|
|
383
|
+
"text": "getBoundingBox(id?: string)"
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"level": 3,
|
|
387
|
+
"text": "遍历与过滤"
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"level": 4,
|
|
391
|
+
"text": "forEach(callback)"
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"level": 4,
|
|
395
|
+
"text": "filter(predicate)"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"level": 3,
|
|
399
|
+
"text": "工具方法"
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"level": 2,
|
|
403
|
+
"text": "SceneManager"
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"level": 3,
|
|
407
|
+
"text": "方法"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"level": 4,
|
|
411
|
+
"text": "create(key, options?)"
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"level": 4,
|
|
415
|
+
"text": "add(key, scene) / get(key) / remove(key)"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"level": 4,
|
|
419
|
+
"text": "serialize(key)"
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"level": 4,
|
|
423
|
+
"text": "keys() / size / clear()"
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"level": 2,
|
|
427
|
+
"text": "LightManager"
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
"level": 3,
|
|
431
|
+
"text": "灯光创建"
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
"level": 3,
|
|
435
|
+
"text": "灯光预设"
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"level": 3,
|
|
439
|
+
"text": "Helper 可视化"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"level": 4,
|
|
443
|
+
"text": "showHelper(id, size?, color?)"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"level": 3,
|
|
447
|
+
"text": "管理"
|
|
448
|
+
}
|
|
449
|
+
],
|
|
450
|
+
"content": "# Managers API\n\n`u-space` 使用专用管理器来处理特定领域的逻辑,例如用于缓存和注册 3D 对象的 `ObjectManager`。\n\n## ObjectManager\n\n`ObjectManager` 提供了一个集中式字典/映射层,让你无需递归遍历 Three.js 场景图,就能通过字符串 ID 或字符串名称轻松检索复杂模型或特定网格。\n\n默认实例可通过 `viewer.objectManager` 访问。\n\n### 添加对象\n\n向管理器添加对象时,必须提供唯一标识符。\n\n```typescript\nconst myModel = new Model();\n// ... 加载逻辑\n\n// 用指定的唯一 ID 添加\nviewer.objectManager.add('my-unique-car-id', myModel);\n\n// 一个对象可以注册多个 ID\nviewer.objectManager.add('player-vehicle', myModel);\n```\n\n### 检索对象\n\n管理器提供快速访问对象的方法。\n\n#### `getById(id: string)`\n\n精确检索与指定 ID 匹配的一个对象(或 `undefined`)。\n\n```typescript\nconst car = viewer.objectManager.getById('my-unique-car-id');\n```\n\n#### `getByName(name: string)`\n\n由于 Three.js 对象可以共享同一个 `.name` 属性,此方法返回一个 `Set<Object3D>`,包含所有与指定名称匹配的已注册对象。\n\n```typescript\n// 假设 myModel.name = 'sedan'\nconst sedans = viewer.objectManager.getByName('sedan');\n\nsedans.forEach((vehicle) => {\n vehicle.position.y += 10;\n});\n```\n\n#### `getByType(type: string)`\n\n返回一个 `Set<Object3D>`,包含所有 `object.type` 与指定类型匹配的已注册对象。\n\n```typescript\nconst models = viewer.objectManager.getByType('Model');\n```\n\n#### `getObjectIds(object: Object3D)`\n\n返回给定对象已注册的所有 ID 的 `Set<string>`。\n\n```typescript\nconst ids = viewer.objectManager.getObjectIds(myModel);\n```\n\n### 移除对象\n\n#### `remove(object: Object3D)`\n\n从所有内部映射中移除该对象及其所有关联 ID。\n\n```typescript\nviewer.objectManager.remove(myModel);\n```\n\n#### `removeById(id: string)`\n\n移除注册在指定 ID 下的对象。\n\n```typescript\nviewer.objectManager.removeById('my-unique-car-id');\n```\n\n#### `removeByName(name: string)`\n\n移除所有具有指定 `.name` 的对象。\n\n```typescript\nviewer.objectManager.removeByName('sedan');\n```\n\n#### `removeByType(type: string)`\n\n移除所有具有指定 `.type` 的对象。\n\n```typescript\nviewer.objectManager.removeByType('Model');\n```\n\n### 显隐控制\n\n#### `show(id: string)` / `hide(id: string)`\n\n控制对象的可见性。\n\n```typescript\nviewer.objectManager.hide('car-01');\nviewer.objectManager.show('car-01');\n```\n\n#### `isolate(ids: string[])`\n\n孤立显示:仅显示指定 ID 的对象,隐藏其余所有。\n\n```typescript\nviewer.objectManager.isolate(['car-01', 'car-02']);\n```\n\n#### `showAll()`\n\n恢复显示所有已管理对象。\n\n```typescript\nviewer.objectManager.showAll();\n```\n\n### 材质操作\n\n#### `setOpacity(id: string, opacity: number)`\n\n设置指定对象所有材质的透明度。\n\n```typescript\nviewer.objectManager.setOpacity('building-01', 0.3);\nviewer.objectManager.setOpacity('building-01', 1.0); // 恢复不透明\n```\n\n### 空间查询\n\n#### `getBoundingBox(id?: string)`\n\n获取指定对象的包围盒,不传 `id` 则返回所有已管理对象的包围盒。\n\n```typescript\nconst box = viewer.objectManager.getBoundingBox('car-01');\nconst allBox = viewer.objectManager.getBoundingBox(); // 全部对象\n```\n\n### 遍历与过滤\n\n#### `forEach(callback)`\n\n遍历所有已管理对象。\n\n```typescript\nviewer.objectManager.forEach((object, ids) => {\n console.log(`对象: ${object.name}, IDs: ${Array.from(ids).join(', ')}`);\n});\n```\n\n#### `filter(predicate)`\n\n按条件过滤对象,返回匹配的数组。\n\n```typescript\nconst cars = viewer.objectManager.filter((obj) => obj.name.startsWith('car'));\n```\n\n### 工具方法\n\n- `getAll()`:返回所有已跟踪对象的 `Set<Object3D>`。\n- `clear()`:从所有内部映射中移除所有对象。\n- `size`:返回当前管理器跟踪的唯一对象总数。\n\n---\n\n## SceneManager\n\n`SceneManager` 用于管理多个场景的创建、注册、切换和序列化。\n\n```typescript\nimport { SceneManager } from 'u-space';\n\nconst sceneManager = new SceneManager();\n```\n\n### 方法\n\n#### `create(key, options?)`\n\n创建并注册一个新场景。\n\n```typescript\nconst scene = sceneManager.create('indoor', { background: 0x333333 });\n```\n\n#### `add(key, scene)` / `get(key)` / `remove(key)`\n\n手动注册、获取或移除场景。\n\n```typescript\nsceneManager.add('outdoor', existingScene);\nconst scene = sceneManager.get('outdoor');\nsceneManager.remove('outdoor');\n```\n\n#### `serialize(key)`\n\n将场景元数据序列化为 JSON 快照。\n\n```typescript\nconst snapshot = sceneManager.serialize('indoor');\n// { name, background, environmentRotation, children }\n```\n\n#### `keys()` / `size` / `clear()`\n\n列出所有场景 key、获取场景数量或清空。\n\n---\n\n## LightManager\n\n`LightManager` 提供灯光的便捷创建、预设和 Helper 可视化。\n\n```typescript\nimport { LightManager } from 'u-space';\n\nconst lightManager = new LightManager(viewer.scene);\n```\n\n### 灯光创建\n\n```typescript\nlightManager.addAmbient('ambient', { color: 0xffffff, intensity: 0.5 });\nlightManager.addDirectional('sun', { position: { x: 5, y: 10, z: 5 }, castShadow: true });\nlightManager.addPoint('bulb', { position: { x: 0, y: 3, z: 0 }, intensity: 2 });\nlightManager.addSpot('spot', { position: { x: 0, y: 10, z: 0 }, angle: Math.PI / 6 });\nlightManager.addHemisphere('hemi', { skyColor: 0x87ceeb, groundColor: 0x362907 });\n```\n\n### 灯光预设\n\n一键应用常见场景的灯光配置:\n\n```typescript\nlightManager.applyPreset('indoor'); // 室内:环境光 + 顶部点光源\nlightManager.applyPreset('outdoor'); // 室外:半球光 + 方向光(阳光)\nlightManager.applyPreset('studio'); // 摄影棚:三点布光\nlightManager.applyPreset('warehouse'); // 仓库:多点光源照明\n```\n\n| 预设 | 配置 |\n| :---------- | :-------------------------------------- |\n| `indoor` | 环境光 + 2 个点光源 |\n| `outdoor` | 半球光 + 方向光(带阴影) |\n| `studio` | 环境光 + 主光 + 补光 + 轮廓光 |\n| `warehouse` | 环境光 + 4 个点光源(四角分布) |\n\n### Helper 可视化\n\n```typescript\nlightManager.showHelper('sun'); // 显示单个灯光 Helper(默认 size=5, color=0xff0000)\nlightManager.showHelper('sun', 2, 0x00ff00); // 自定义尺寸和颜色\nlightManager.showAllHelpers(); // 显示所有灯光 Helper\nlightManager.hideHelper('sun'); // 隐藏单个\nlightManager.hideAllHelpers(); // 隐藏所有\n```\n\n#### `showHelper(id, size?, color?)`\n\n| 参数 | 类型 | 默认值 | 说明 |\n| :------ | :-------------------- | :---------- | :---------------- |\n| `id` | `string` | — | 灯光 ID。 |\n| `size` | `number` | `5` | Helper 尺寸。 |\n| `color` | `ColorRepresentation` | `0xff0000` | Helper 颜色。 |\n\n### 管理\n\n```typescript\nlightManager.get('sun'); // 获取灯光\nlightManager.remove('sun'); // 移除灯光\nlightManager.removeAll(); // 移除所有\nlightManager.dispose(); // 清理\n```\n"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"id": "api-objects",
|
|
454
|
+
"path": "api-objects.md",
|
|
455
|
+
"title": "Objects API",
|
|
456
|
+
"summary": "`u-space` 提供了若干对象封装类,主要扩展自 Three.js 的基础节点,使 3D 资产的操作和加载更加便捷。 继承自 `THREE.Mesh`,`u-space` 中所有基础网格类都继承于此。 **关键属性:**",
|
|
457
|
+
"headings": [
|
|
458
|
+
{
|
|
459
|
+
"level": 1,
|
|
460
|
+
"text": "Objects API"
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
"level": 2,
|
|
464
|
+
"text": "基础类"
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
"level": 3,
|
|
468
|
+
"text": "BaseMesh"
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"level": 3,
|
|
472
|
+
"text": "BaseGroup"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"level": 2,
|
|
476
|
+
"text": "模型"
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"level": 3,
|
|
480
|
+
"text": "加载资产"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"level": 4,
|
|
484
|
+
"text": "ModelParameters"
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
"level": 4,
|
|
488
|
+
"text": "缓存示例"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"level": 3,
|
|
492
|
+
"text": "动画"
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
"level": 4,
|
|
496
|
+
"text": "playAnimation(nameOrIndex?, options?)"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"level": 4,
|
|
500
|
+
"text": "playAllAnimations(options?)"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"level": 4,
|
|
504
|
+
"text": "stopAnimation(nameOrIndex?)"
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
"level": 4,
|
|
508
|
+
"text": "updateAnimation(delta)"
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
"level": 3,
|
|
512
|
+
"text": "空间查询"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"level": 4,
|
|
516
|
+
"text": "getBoundingBox()"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
"level": 4,
|
|
520
|
+
"text": "getCenter()"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"level": 3,
|
|
524
|
+
"text": "材质操作"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
"level": 4,
|
|
528
|
+
"text": "setMaterial(material)"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"level": 3,
|
|
532
|
+
"text": "清除缓存"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
"level": 2,
|
|
536
|
+
"text": "网格"
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
"level": 3,
|
|
540
|
+
"text": "SphereMesh"
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"level": 3,
|
|
544
|
+
"text": "PlaneMesh"
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
"level": 3,
|
|
548
|
+
"text": "CircleMesh"
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
"level": 3,
|
|
552
|
+
"text": "TubeMesh"
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
"level": 3,
|
|
556
|
+
"text": "ShapeMesh"
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
"level": 3,
|
|
560
|
+
"text": "ExtrudeMesh"
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"level": 2,
|
|
564
|
+
"text": "Poi"
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
"level": 3,
|
|
568
|
+
"text": "PoiParameters"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"level": 3,
|
|
572
|
+
"text": "方法"
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
"level": 4,
|
|
576
|
+
"text": "updateAsync(parameters?)"
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
"level": 4,
|
|
580
|
+
"text": "dispose()"
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
"level": 2,
|
|
584
|
+
"text": "Topology"
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
"level": 3,
|
|
588
|
+
"text": "TopologyParameters"
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
"level": 3,
|
|
592
|
+
"text": "方法"
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
"level": 4,
|
|
596
|
+
"text": "addNode(id, position)"
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
"level": 4,
|
|
600
|
+
"text": "removeNode(id)"
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
"level": 4,
|
|
604
|
+
"text": "addEdge(from, to, weight?, bidirectional?)"
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
"level": 4,
|
|
608
|
+
"text": "removeEdge(from, to, bidirectional?)"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"level": 4,
|
|
612
|
+
"text": "getShortestPath(startId, endId): Vector3[]"
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
"level": 4,
|
|
616
|
+
"text": "renderGraph()"
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
"level": 4,
|
|
620
|
+
"text": "clearGraph()"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"level": 4,
|
|
624
|
+
"text": "renderPath(points, color?): TubeMesh"
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
"level": 4,
|
|
628
|
+
"text": "clearPaths()"
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
"level": 4,
|
|
632
|
+
"text": "getNeighbors(id): Map<string, number> | undefined"
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
"level": 4,
|
|
636
|
+
"text": "exportData(): TopologyData"
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"level": 4,
|
|
640
|
+
"text": "importData(data: TopologyData)"
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
"level": 4,
|
|
644
|
+
"text": "dispose()"
|
|
645
|
+
}
|
|
646
|
+
],
|
|
647
|
+
"content": "# Objects API\n\n`u-space` 提供了若干对象封装类,主要扩展自 Three.js 的基础节点,使 3D 资产的操作和加载更加便捷。\n\n## 基础类\n\n### `BaseMesh`\n\n继承自 `THREE.Mesh`,`u-space` 中所有基础网格类都继承于此。\n\n**关键属性:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :--------------------------- | :-------- | :----- | :------------------------------------------------------------- |\n| `ignoreInvisibleWhenRaycast` | `boolean` | `true` | 为 `true` 时,不可见的网格在射线检测时会被跳过(不参与碰撞)。 |\n\n### `BaseGroup`\n\n继承自 `THREE.Group`,`Model` 和 `Topology` 均继承于此。\n\n**关键属性:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :--------------------------- | :-------- | :----- | :--------------------------------------------------------------- |\n| `ignoreInvisibleWhenRaycast` | `boolean` | `true` | 为 `true` 时,不可见的组在射线检测时会被跳过(不参与碰撞)。 |\n\n## 模型\n\n`Model` 类继承自 `BaseGroup`(进而继承自 `THREE.Group`),简化了异步加载 `glb`、`gltf` 等外部 3D 模型的流程,内置多层缓存支持。\n\n```typescript\nimport { Model } from 'u-space';\n\nconst myModel = new Model();\n```\n\n### 加载资产\n\n`loadAsync` 方法负责从 URL 加载资产并将其添加到组中。\n\n```typescript\nawait myModel.loadAsync(parameters: ModelParameters)\n```\n\n#### `ModelParameters`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :----------- | :-------- | :----- | :-------------------------------------------------------------------------------------- |\n| `url` | `string` | — | `.gltf` 或 `.glb` 文件的 URL。 |\n| `cache` | `boolean` | `true` | 启用内存缓存。若模型已加载过,则直接从内存中获取并克隆。 |\n| `persistent` | `boolean` | `true` | 使用浏览器 Cache API 启用持久化磁盘缓存,适合较大的模型。 |\n\n#### 缓存示例\n\n```javascript\n// 默认开启双层缓存,直接加载即可\nconst model1 = new Model();\nmodel1.loadAsync({ url: 'model.glb' });\n\n// 禁用内存缓存(每次都从网络或持久化缓存重新加载)\nconst model2 = new Model();\nmodel2.loadAsync({ url: 'model.glb', cache: false });\n\n// 完全禁用缓存\nconst model3 = new Model();\nmodel3.loadAsync({ url: 'model.glb', cache: false, persistent: false });\n```\n\n### 动画\n\n`Model` 在加载含内置动画的模型(如 glTF/FBX)后,会自动初始化 `AnimationMixer` 并收集 `AnimationClip`。\n\n**属性:**\n\n| 属性 | 类型 | 说明 |\n| :----------- | :-------------------------- | :----------------------------------------- |\n| `mixer` | `AnimationMixer \\| null` | 动画混合器,加载含动画模型后自动创建。 |\n| `animations` | `AnimationClip[]` | 模型内置的动画片段列表。 |\n\n#### `playAnimation(nameOrIndex?, options?)`\n\n播放指定动画。不传参时播放第一个动画。\n\n```typescript\n// 按名称播放\nmodel.playAnimation('Walk');\n\n// 按索引播放\nmodel.playAnimation(0);\n\n// 带选项\nmodel.playAnimation('Run', {\n loop: true, // 是否循环(默认 true)\n repetitions: 3, // 循环次数(默认 Infinity)\n timeScale: 1.5, // 播放速度(默认 1)\n clampWhenFinished: true, // 播放结束后停留在最后一帧(默认 false)\n});\n```\n\n#### `playAllAnimations(options?)`\n\n播放模型所有内置动画。参数同 `playAnimation`。\n\n```typescript\nmodel.playAllAnimations({ timeScale: 2 });\n```\n\n#### `stopAnimation(nameOrIndex?)`\n\n停止指定动画。不传参时停止所有动画。\n\n```typescript\nmodel.stopAnimation('Walk'); // 停止指定动画\nmodel.stopAnimation(); // 停止所有动画\n```\n\n#### `updateAnimation(delta)`\n\n推进动画时间,需在渲染循环中调用。`delta` 为帧间隔时间(秒),可从 Viewer 事件的 `delta` 属性获取。\n\n```typescript\nviewer.addEventListener('beforeRender', (e) => {\n model.updateAnimation(e.delta);\n});\n```\n\n### 空间查询\n\n#### `getBoundingBox()`\n\n获取模型的轴对齐包围盒(AABB)。\n\n```typescript\nconst box = myModel.getBoundingBox();\nconst size = box.getSize(new Vector3());\nconsole.log('模型尺寸:', size);\n```\n\n#### `getCenter()`\n\n获取模型包围盒的中心点。\n\n```typescript\nconst center = myModel.getCenter();\nconsole.log('模型中心:', center);\n```\n\n### 材质操作\n\n#### `setMaterial(material)`\n\n将模型内所有 Mesh 的材质统一替换为指定材质。\n\n```typescript\nimport { MeshStandardMaterial } from 'three/webgpu';\n\nmyModel.setMaterial(new MeshStandardMaterial({ color: 0xff0000 }));\n```\n\n### 清除缓存\n\n可通过 `Model` 类的静态方法手动清除内部缓存:\n\n- `Model.clearMemoryCache()`:清除运行时内存缓存。\n- `await Model.clearPersistentCache()`:完全清除浏览器中 `u-space` 模型的持久化缓存。\n\n## 网格\n\n`u-space` 提供了多种精简的网格类,均继承自 `BaseMesh`。所有类默认使用 `MeshStandardNodeMaterial`,构造函数接受 `{ geometryParameters, materialParameters }` 参数,并支持交互事件分发。\n\n### `SphereMesh`\n\n```typescript\nimport { SphereMesh } from 'u-space';\n\nconst sphere = new SphereMesh({\n geometryParameters: { radius: 1, widthSegments: 32, heightSegments: 32 },\n materialParameters: { color: 0x0077ff },\n});\n```\n\n**`SphereMeshParameters`**\n\n| 属性 | 类型 | 说明 |\n| :-------------------- | :----------------------------------- | :----------------------------------------------- |\n| `geometryParameters` | `SphereGeometry` 构造函数参数 | `radius`、`widthSegments`、`heightSegments` 等。 |\n| `materialParameters` | `MeshStandardNodeMaterialParameters` | 标准材质选项(颜色等)。 |\n\n### `PlaneMesh`\n\n水平平面网格。\n\n```typescript\nimport { PlaneMesh } from 'u-space';\n\nconst plane = new PlaneMesh({\n geometryParameters: { width: 10, height: 10 },\n materialParameters: { color: 0x888888 },\n});\n```\n\n### `CircleMesh`\n\n圆形平面网格。\n\n```typescript\nimport { CircleMesh } from 'u-space';\n\nconst circle = new CircleMesh({\n geometryParameters: { radius: 5, segments: 64 },\n});\n```\n\n### `TubeMesh`\n\n沿指定 `Curve<Vector3>` 曲线生成的管道网格。\n\n```typescript\nimport { TubeMesh } from 'u-space';\nimport { CatmullRomCurve3, Vector3 } from 'three/webgpu';\n\nconst path = new CatmullRomCurve3([new Vector3(0,0,0), new Vector3(5,2,5)]);\nconst tube = new TubeMesh({\n geometryParameters: { path, tubularSegments: 20, radius: 0.2, radialSegments: 8 },\n materialParameters: { color: 0x00ff00 },\n});\n```\n\n### `ShapeMesh`\n\n由 `THREE.Shape` 或 2D 点生成的平面网格。\n\n```typescript\nimport { ShapeMesh } from 'u-space';\n\n// 从显式 Shape 创建\nconst mesh = new ShapeMesh({ geometryParameters: { shape: myShape } });\n\n// 静态辅助方法:从 x/z 点数组创建\nconst mesh2 = ShapeMesh.createFromPoints([{ x: 0, z: 0 }, { x: 5, z: 0 }, { x: 5, z: 5 }]);\n```\n\n### `ExtrudeMesh`\n\n由 `THREE.Shape` 或 2D 点拉伸生成的 3D 实体网格。\n\n```typescript\nimport { ExtrudeMesh } from 'u-space';\n\nconst solid = new ExtrudeMesh({\n geometryParameters: {\n shape: myShape,\n options: { depth: 3, bevelEnabled: false },\n },\n materialParameters: { color: 0xff8800 },\n});\n\n// 静态辅助方法\nconst solid2 = ExtrudeMesh.createFromPoints(\n [{ x: 0, z: 0 }, { x: 5, z: 0 }, { x: 5, z: 5 }],\n { geometryParameters: { options: { depth: 2, bevelEnabled: false } } }\n);\n```\n\n## Poi\n\n`Poi` 是一个基于 canvas 渲染的公告板(精灵),用于在 3D 场景中放置图标和标签,继承自 `BaseSprite`。\n\n```typescript\nimport { Poi } from 'u-space';\n\nconst poi = new Poi({\n img: '/icons/marker.png',\n text: '我的位置',\n fontSize: 28,\n color: '#ffffff',\n backgroundColor: 'rgba(0,0,0,0.6)',\n textPosition: 'right',\n});\n// 构造时会自动调用 updateAsync(),无需手动调用\n// 如需更新参数,可再次调用:\n// await poi.updateAsync({ text: '新文字' });\n\npoi.position.set(10, 5, 10);\nviewer.scene.add(poi);\n```\n\n### `PoiParameters`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :---------------- | :------------------------------------------ | :----------------------- | :--------------------------------- |\n| `img` | `string \\| CanvasImageSource` | `''` | 图标图片 URL 或元素。 |\n| `text` | `string` | `''` | 标签文字。 |\n| `fontSize` | `number` | `32` | 字体大小(像素)。 |\n| `fontFamily` | `string` | `'Arial'` | 字体族。 |\n| `color` | `string` | `'#ffffff'` | 文字颜色。 |\n| `iconSize` | `number` | `64` | 图标大小(像素)。 |\n| `padding` | `number` | `10` | 内容四周的内边距。 |\n| `backgroundColor` | `string` | `'rgba(0, 0, 0, 0)'` | 背景填充颜色。 |\n| `borderRadius` | `number` | `8` | 背景圆角半径。 |\n| `textPosition` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'right'` | 文字相对图标的位置。 |\n| `scaleFactor` | `number` | `0.01` | canvas 像素到世界单位的缩放系数。 |\n\n### 方法\n\n#### `updateAsync(parameters?)`\n\n使用可选的参数覆盖重新渲染 canvas 纹理。构造时会自动调用一次,后续参数未变化时会跳过重绘。\n\n```typescript\nawait poi.updateAsync({ text: '更新后的标签', color: '#ffff00' });\nviewer.render();\n```\n\n#### `dispose()`\n\n释放 canvas 纹理和材质。\n\n## Topology\n\n`Topology` 是一个带有内置 3D 可视化的图数据结构。它存储节点(位置)和带权重的边,实现了 Dijkstra 最短路径算法,并将图渲染为球体和管道。\n\n```typescript\nimport { Topology } from 'u-space';\n\nconst topo = new Topology({\n nodeColor: 0x0000ff,\n nodeRadius: 0.3,\n edgeColor: 0x00ff00,\n edgeRadius: 0.05,\n});\n\ntopo.addNode('A', new Vector3(0, 0, 0));\ntopo.addNode('B', new Vector3(5, 0, 0));\ntopo.addNode('C', new Vector3(5, 0, 5));\n\ntopo.addEdge('A', 'B');\ntopo.addEdge('B', 'C');\n\ntopo.renderGraph(); // 创建球体 + 管道网格\nviewer.scene.add(topo);\n```\n\n### `TopologyParameters`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :------------ | :-------------------- | :---------- | :----------------------- |\n| `nodeColor` | `ColorRepresentation` | `0x0000ff` | 节点球体颜色。 |\n| `nodeRadius` | `number` | `0.5` | 节点球体半径。 |\n| `edgeColor` | `ColorRepresentation` | `0x00ff00` | 边管道颜色。 |\n| `edgeRadius` | `number` | `0.1` | 边管道半径。 |\n| `pathColor` | `ColorRepresentation` | `0xff00ff` | 路径可视化颜色。 |\n| `pathRadius` | `number` | `0.2` | 路径管道半径。 |\n\n### 方法\n\n#### `addNode(id, position)`\n\n向图中添加一个节点。\n\n#### `removeNode(id)`\n\n移除一个节点及其关联的边。\n\n#### `addEdge(from, to, weight?, bidirectional?)`\n\n在两个节点之间添加一条边。`weight` 默认为欧氏距离,`bidirectional` 默认为 `true`(双向)。\n\n#### `removeEdge(from, to, bidirectional?)`\n\n移除两个节点之间的边。\n\n#### `getShortestPath(startId, endId): Vector3[]`\n\n使用 Dijkstra 算法返回最短路径(世界坐标位置数组)。若不存在路径则返回 `[]`。\n\n#### `renderGraph()`\n\n根据当前节点和边构建球体/管道场景图。修改图后需调用此方法刷新可视化。\n\n#### `clearGraph()`\n\n移除并释放所有图网格。\n\n#### `renderPath(points, color?): TubeMesh`\n\n将给定点通过 CatmullRomCurve3 平滑处理后渲染为管道网格。\n\n```typescript\nconst path = topo.getShortestPath('A', 'C');\ntopo.renderPath(path, 0xff0000);\nviewer.render();\n```\n\n#### `clearPaths()`\n\n移除并释放所有路径网格。\n\n#### `getNeighbors(id): Map<string, number> | undefined`\n\n返回节点的邻接表(邻居 ID → 边权重)。\n\n#### `exportData(): TopologyData`\n\n将当前拓扑图(节点和边)导出为 JSON 可序列化对象。\n\n```typescript\nconst data = topo.exportData();\n// { nodes: Record<string, {x,y,z}>, edges: Array<{from,to,weight}> }\n```\n\n双向边在导出时会去重,只保留一条记录。\n\n#### `importData(data: TopologyData)`\n\n从 `exportData()` 返回的数据中还原拓扑图,替换当前所有节点、边和路径网格,并重新渲染。\n\n```typescript\ntopo.importData(data);\n```\n\n#### `dispose()`\n\n清除图和路径网格。\n"
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
"id": "api-plugin-atmosphere",
|
|
651
|
+
"path": "api-plugin-atmosphere.md",
|
|
652
|
+
"title": "atmosphere",
|
|
653
|
+
"summary": "天空和大气渲染插件。目前为占位实现,`enable()` / `disable()` / `dispose()` 方法可用,但尚未实现具体功能。 ```typescript import { Atmosphere } from 'u-space/plugins/atmosphere';",
|
|
654
|
+
"headings": [
|
|
655
|
+
{
|
|
656
|
+
"level": 1,
|
|
657
|
+
"text": "atmosphere"
|
|
658
|
+
}
|
|
659
|
+
],
|
|
660
|
+
"content": "# atmosphere\n\n天空和大气渲染插件。目前为占位实现,`enable()` / `disable()` / `dispose()` 方法可用,但尚未实现具体功能。\n\n```typescript\nimport { Atmosphere } from 'u-space/plugins/atmosphere';\n\nconst atmosphere = new Atmosphere(viewer);\natmosphere.enable();\n```\n"
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
"id": "api-plugin-curve-movement",
|
|
664
|
+
"path": "api-plugin-curve-movement.md",
|
|
665
|
+
"title": "curve-movement",
|
|
666
|
+
"summary": "沿样条路径对相机或对象进行动画。提供两个具体子类:`CurveMovementCamera` 和 `CurveMovementObject`。 ```typescript import { CurveMovementObject } from 'u-space/plugins/curve-movement';",
|
|
667
|
+
"headings": [
|
|
668
|
+
{
|
|
669
|
+
"level": 1,
|
|
670
|
+
"text": "curve-movement"
|
|
671
|
+
}
|
|
672
|
+
],
|
|
673
|
+
"content": "# curve-movement\n\n沿样条路径对相机或对象进行动画。提供两个具体子类:`CurveMovementCamera` 和 `CurveMovementObject`。\n\n```typescript\nimport { CurveMovementObject } from 'u-space/plugins/curve-movement';\nimport { Vector3 } from 'three/webgpu';\n\nconst movement = new CurveMovementObject(viewer, myModel);\nmovement.setFromPoints([\n new Vector3(0, 0, 0),\n new Vector3(10, 2, 0),\n new Vector3(20, 0, 10),\n]);\nmovement.speed = 0.05; // 每秒进度\nmovement.loop = 'repeat'; // 'once' | 'repeat' | 'pingpong'\nmovement.autoLookAt = true;\n\nmovement.play();\n// movement.pause() / movement.resume() / movement.stop()\n\n// 监听事件\nmovement.addEventListener('update', ({ progress }) => console.log(progress));\nmovement.addEventListener('complete', () => console.log('完成'));\n```\n\n**`CurveMovement` 属性:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :-------------- | :--------------------------------- | :-------- | :----------------------------------- |\n| `path` | `Curve<Vector3> \\| null` | `null` | 样条路径。 |\n| `progress` | `number` | `0` | 当前归一化进度(0–1)。 |\n| `speed` | `number` | `0.1` | 每秒进度单位。 |\n| `loop` | `'once' \\| 'repeat' \\| 'pingpong'` | `'once'` | 循环行为。 |\n| `autoLookAt` | `boolean` | `true` | 朝向路径切线方向。 |\n| `lookAtOffset` | `number` | `0` | Y 轴旋转偏移量(弧度)。 |\n| `positionOffset`| `Vector3` | `(0,0,0)` | 叠加到每个位置上的世界坐标偏移量。 |\n| `direction` | `1 \\| -1` | `1` | 当前行进方向。 |\n"
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"id": "api-plugin-keyboard-controls",
|
|
677
|
+
"path": "api-plugin-keyboard-controls.md",
|
|
678
|
+
"title": "keyboard-controls",
|
|
679
|
+
"summary": "为激活相机提供 WASD 或方向键的平移和旋转控制。 ```typescript import { KeyboardControls, ACTION } from 'u-space/plugins/keyboard-controls';",
|
|
680
|
+
"headings": [
|
|
681
|
+
{
|
|
682
|
+
"level": 1,
|
|
683
|
+
"text": "keyboard-controls"
|
|
684
|
+
}
|
|
685
|
+
],
|
|
686
|
+
"content": "# keyboard-controls\n\n为激活相机提供 WASD 或方向键的平移和旋转控制。\n\n```typescript\nimport { KeyboardControls, ACTION } from 'u-space/plugins/keyboard-controls';\n\nconst keyboardControls = new KeyboardControls(viewer);\n\n// 可选:自定义移动速度\nkeyboardControls.moveDistanceDelta = 0.5;\nkeyboardControls.rotateAngleDelta = (Math.PI / 180) * 2;\n\n// 激活监听\nkeyboardControls.enable();\n// 之后:\nkeyboardControls.disable();\n```\n\n**默认按键绑定**(`keyboardControls.keys`):\n\n| 按键 | 动作 |\n| :----------- | :------- |\n| `W` | 向前移动 |\n| `S` | 向后移动 |\n| `A` | 向左移动 |\n| `D` | 向右移动 |\n| `Q` | 向上移动 |\n| `E` | 向下移动 |\n| `ArrowLeft` | 向左旋转 |\n| `ArrowRight` | 向右旋转 |\n| `ArrowUp` | 向上旋转 |\n| `ArrowDown` | 向下旋转 |\n\n通过 `ACTION` 常量重新绑定任意按键:\n\n```typescript\nimport { ACTION } from 'u-space/plugins/keyboard-controls';\nkeyboardControls.keys['Space'] = ACTION.MOVE_UP;\n```\n"
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
"id": "api-plugin-minimap",
|
|
690
|
+
"path": "api-plugin-minimap.md",
|
|
691
|
+
"title": "minimap",
|
|
692
|
+
"summary": "生成一个 2D 小地图叠加层,在 3D 场景中跟踪目标对象。渲染到注入 `viewer.el` 的 `<canvas>` 元素中。 ```typescript import { Minimap } from 'u-space/plugins/minimap';",
|
|
693
|
+
"headings": [
|
|
694
|
+
{
|
|
695
|
+
"level": 1,
|
|
696
|
+
"text": "minimap"
|
|
697
|
+
}
|
|
698
|
+
],
|
|
699
|
+
"content": "# minimap\n\n生成一个 2D 小地图叠加层,在 3D 场景中跟踪目标对象。渲染到注入 `viewer.el` 的 `<canvas>` 元素中。\n\n```typescript\nimport { Minimap } from 'u-space/plugins/minimap';\n\nconst minimap = new Minimap(viewer);\nminimap.target = myCharacterModel; // 要跟踪并显示的 Object3D\nminimap.setSize(300, 300); // 宽高(像素)\n\n// 可选:设置小地图场景样式\nminimap.scene.background = new THREE.Color(0x111111);\n\nminimap.enable();\n// 之后:\nminimap.disable();\nminimap.dispose();\n```\n\n**属性:**\n\n| 属性 | 类型 | 说明 |\n| :------------ | :-------------------- | :--------------------------------------- |\n| `target` | `Object3D \\| null` | 小地图居中显示的对象。 |\n| `scene` | `Scene` | 小地图内部的 Three.js 场景。 |\n| `camera` | `OrthographicCamera` | 正交俯视相机。 |\n| `marker` | `Object3D` | 显示主相机位置/朝向的箭头网格。 |\n| `needsUpdate` | `boolean` | 设置为 `true` 可强制重新渲染小地图。 |\n\n**方法:**\n\n- `setSize(width, height)` — 调整小地图画布和相机视锥大小。\n- `enable()` — 将画布附加到 `viewer.el` 并开始渲染。\n- `disable()` — 移除画布并停止渲染。\n- `dispose()` — 禁用并清理所有资源。\n"
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
"id": "api-plugin-object-controls",
|
|
703
|
+
"path": "api-plugin-object-controls.md",
|
|
704
|
+
"title": "object-controls",
|
|
705
|
+
"summary": "对场景中的 3D 对象进行交互式移动、旋转、缩放操作。继承自 Three.js `TransformControls`,集成了 u-space `Viewer` 生命周期管理。 ```typescript import { ObjectControls } from 'u-space/plugins/object-controls';",
|
|
706
|
+
"headings": [
|
|
707
|
+
{
|
|
708
|
+
"level": 1,
|
|
709
|
+
"text": "object-controls"
|
|
710
|
+
}
|
|
711
|
+
],
|
|
712
|
+
"content": "# object-controls\n\n对场景中的 3D 对象进行交互式移动、旋转、缩放操作。继承自 Three.js `TransformControls`,集成了 u-space `Viewer` 生命周期管理。\n\n```typescript\nimport { ObjectControls } from 'u-space/plugins/object-controls';\n\nconst controls = new ObjectControls(viewer, {\n mode: 'translate', // 'translate' | 'rotate' | 'scale',默认 'translate'\n space: 'world', // 'world' | 'local',默认 'world'\n size: 1, // 控件显示大小,默认 1\n});\n\ncontrols.enable();\ncontrols.attach(myMesh); // 将控件附加到目标对象\n\n// 切换模式(直接赋值,继承自 TransformControls)\ncontrols.mode = 'rotate';\ncontrols.space = 'local';\n\n// 监听变换事件\ncontrols.addEventListener('objectChange', () => {\n console.log(myMesh.position);\n});\n\ncontrols.addEventListener('dragging-changed', ({ value }) => {\n console.log('拖拽中:', value); // true = 开始,false = 结束\n});\n```\n\n**说明:**\n\n- `enable()` 时将 gizmo 加入场景并切换 `frameloop` 为 `'always'`,确保拖拽时连续渲染。\n- 拖拽期间自动挂起 `viewer.controls`(CameraControls)以避免冲突;`disable()` 时无论如何都强制还原相机控制,防止 mid-drag 调用 disable 导致相机卡死。\n- 监听 `viewer` 的 `cameraChange` 事件,`viewer.setCamera()` 切换相机后 gizmo 自动同步,无需手动更新。\n\n**构造选项(`ObjectControlsOptions`):**\n\n| 选项 | 类型 | 默认值 | 说明 |\n| :------- | :--------------------------------- | :------------ | :--------------- |\n| `mode` | `'translate' \\| 'rotate' \\| 'scale'` | `'translate'` | 初始变换模式。 |\n| `space` | `'world' \\| 'local'` | `'world'` | 初始变换空间。 |\n| `size` | `number` | `1` | gizmo 大小。 |\n| `showX` | `boolean` | `true` | 显示 X 轴手柄。 |\n| `showY` | `boolean` | `true` | 显示 Y 轴手柄。 |\n| `showZ` | `boolean` | `true` | 显示 Z 轴手柄。 |\n\n**方法:**\n\n| 方法 | 说明 |\n| :---------- | :----------------------------------------------------------- |\n| `enable()` | 将 gizmo 加入场景,切换 frameloop 为 `'always'`。 |\n| `disable()` | 移除 gizmo,还原 frameloop 和 CameraControls。 |\n| `attach(object)` | 将控件附加到指定 Object3D。 |\n| `detach()` | 解除当前附加对象。 |\n| `dispose()` | 完全释放所有资源。 |\n\n**属性:**\n\n| 属性 | 类型 | 说明 |\n| :--------- | :-------- | :------------------------------------ |\n| `isActive` | `boolean` | 当前是否已调用 `enable()`(只读)。 |\n| `object` | `Object3D \\| undefined` | 当前附加的对象(继承自 TransformControls)。 |\n| `mode` | `string` | 当前变换模式,可直接赋值切换。 |\n| `space` | `string` | 当前变换空间,可直接赋值切换。 |\n\n> 由于 `ObjectControls` 直接继承 `TransformControls`,所有原生属性(`translationSnap`、`rotationSnap`、`scaleSnap`、`showX/Y/Z` 等)和事件均可直接使用,参考 [Three.js TransformControls 文档](https://threejs.org/docs/#examples/en/controls/TransformControls)。\n"
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
"id": "api-plugin-tiles",
|
|
716
|
+
"path": "api-plugin-tiles.md",
|
|
717
|
+
"title": "tiles",
|
|
718
|
+
"summary": "提供与 `3d-tiles-renderer` 和地理空间数据的集成。主要导出 `ArcgisTilesRenderer`,可流式加载 ArcGIS Online 3D 瓦片并将地球重新定向到指定地理位置。 ```typescript import { ArcgisTilesRenderer } from 'u-space/plugins/tiles';",
|
|
719
|
+
"headings": [
|
|
720
|
+
{
|
|
721
|
+
"level": 1,
|
|
722
|
+
"text": "tiles"
|
|
723
|
+
}
|
|
724
|
+
],
|
|
725
|
+
"content": "# tiles\n\n提供与 `3d-tiles-renderer` 和地理空间数据的集成。主要导出 `ArcgisTilesRenderer`,可流式加载 ArcGIS Online 3D 瓦片并将地球重新定向到指定地理位置。\n\n```typescript\nimport { ArcgisTilesRenderer } from 'u-space/plugins/tiles';\n\nconst arcgisTilesRenderer = new ArcgisTilesRenderer(viewer);\n\n// 设置原点为经度、纬度、高度\narcgisTilesRenderer.invalidate(120.002269, 30.284849, 4);\n\n// 瓦片持续流式加载,使用 always 模式\nviewer.frameloop = 'always';\n\narcgisTilesRenderer.enable();\n```\n\n**方法:**\n\n| 方法 | 说明 |\n| :-------------------------- | :--------------------------------------------------------------------------------------------- |\n| `invalidate(lon, lat, alt)` | 将瓦片原点设置为指定的 WGS84 坐标(度)。可多次调用。返回一个取消订阅的函数。 |\n| `enable()` | 将瓦片添加到场景并启动更新循环。 |\n| `disable()` | 从场景中移除瓦片并暂停更新循环。 |\n| `dispose()` | 禁用并完全释放瓦片渲染器。 |\n"
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
"id": "api-plugin-topology-drawer",
|
|
729
|
+
"path": "api-plugin-topology-drawer.md",
|
|
730
|
+
"title": "topology-drawer",
|
|
731
|
+
"summary": "在 3D 场景中交互式绘制拓扑路径图。点击场景中的任意对象表面放置节点,自动连接成路径;点击空白处则落回不可见的地面平面。事件检测通过 `viewer.interactionManager` 实现(`scene.addEventListener` 冒泡)。 ```typescript import { TopologyDrawer } from 'u-space/plugins/topology-drawer';",
|
|
732
|
+
"headings": [
|
|
733
|
+
{
|
|
734
|
+
"level": 1,
|
|
735
|
+
"text": "topology-drawer"
|
|
736
|
+
}
|
|
737
|
+
],
|
|
738
|
+
"content": "# topology-drawer\n\n在 3D 场景中交互式绘制拓扑路径图。点击场景中的任意对象表面放置节点,自动连接成路径;点击空白处则落回不可见的地面平面。事件检测通过 `viewer.interactionManager` 实现(`scene.addEventListener` 冒泡)。\n\n```typescript\nimport { TopologyDrawer } from 'u-space/plugins/topology-drawer';\n\nconst drawer = new TopologyDrawer(viewer, {\n groundY: 0, // 空白区域兜底地面的 Y 坐标,默认 0\n snapRadius: 1.0, // 自动吸附已有节点的世界单位半径,默认 1.0\n nodeRadius: 0.3,\n nodeColor: 0x0088ff,\n edgeRadius: 0.1,\n edgeColor: 0x00ddff,\n previewColor: 0xffff00, // 预览线颜色\n});\n\ndrawer.enable();\n```\n\n**操作说明:**\n\n| 操作 | 效果 |\n| :--- | :--- |\n| 左键点击空白 / 模型表面 | 放置新节点,与上一节点自动连边 |\n| 左键点击已有节点(`snapRadius` 范围内) | 吸附并连接到该节点,不新增节点 |\n| 左键点击已有边 | 切断该边,在点击处插入新节点并重连两端 |\n| 右键 / `Escape` | 结束当前路径链,下次点击开始新路径 |\n| `Ctrl / Cmd + Z` | 撤销最后一步(节点、边或结束路径) |\n\n**方法:**\n\n| 方法 | 说明 |\n| :--- | :--- |\n| `enable()` | 进入绘制模式,将拓扑与地面平面加入场景。同时自动将 `viewer.interactionManager.pointerMoveEventsEnabled` 置为 `true`(用于预览线跟随光标),并在 `disable()` 时恢复为原值。 |\n| `disable()` | 退出绘制模式,已绘内容仍保留在场景中。恢复 `pointerMoveEventsEnabled` 为调用 `enable()` 前的值。 |\n| `finishPath()` | 结束当前路径链(等同于右键 / Escape)。 |\n| `undo()` | 撤销最后一步操作。 |\n| `clear()` | 清空所有已绘节点、边和路径。 |\n| `exportData()` | 以 JSON 可序列化格式导出当前拓扑数据。 |\n| `importData(data)` | 加载 `exportData()` 返回的数据,替换当前内容。 |\n| `dispose()` | 完全释放所有资源并从场景移除拓扑。 |\n\n**属性:**\n\n| 属性 | 类型 | 说明 |\n| :--- | :--- | :--- |\n| `topology` | `Topology` | 底层 `Topology` 对象,可进一步访问节点、边和路径方法。 |\n\n**导出 / 导入:**\n\n```typescript\n// 导出\nconst data = drawer.exportData();\n// data: { nodes: Record<string, {x,y,z}>, edges: Array<{from,to,weight}> }\n\n// 导入\ndrawer.importData(data);\n```\n\n**结合 `SceneLoader` 在模型表面绘制:**\n\n```typescript\nimport { SceneLoader } from 'u-space/plugins/u-manager';\nimport { TopologyDrawer } from 'u-space/plugins/topology-drawer';\n\nconst sceneLoader = new SceneLoader(viewer);\nsceneLoader.setPath('./scenes/my-scene');\nconst group = await sceneLoader.loadAsync();\nviewer.scene.add(group);\n\nconst drawer = new TopologyDrawer(viewer, { snapRadius: 1.0 });\ndrawer.enable(); // 可直接在加载的模型表面点击绘制\n```\n"
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
"id": "api-plugin-tracking-controls",
|
|
742
|
+
"path": "api-plugin-tracking-controls.md",
|
|
743
|
+
"title": "tracking-controls",
|
|
744
|
+
"summary": "使相机平滑跟随移动的 `Object3D` 目标。 ```typescript import { TrackingControls } from 'u-space/plugins/tracking-controls';",
|
|
745
|
+
"headings": [
|
|
746
|
+
{
|
|
747
|
+
"level": 1,
|
|
748
|
+
"text": "tracking-controls"
|
|
749
|
+
}
|
|
750
|
+
],
|
|
751
|
+
"content": "# tracking-controls\n\n使相机平滑跟随移动的 `Object3D` 目标。\n\n```typescript\nimport { TrackingControls } from 'u-space/plugins/tracking-controls';\n\nconst tracking = new TrackingControls(viewer);\ntracking.target = myMovingObject;\ntracking.type = 'box3'; // 'position'(世界原点)或 'box3'(包围盒中心)\ntracking.offset.set(0, 5, 0); // 相机目标偏移量\n\ntracking.enable();\n// tracking.disable();\n```\n\n**属性:**\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :------- | :---------------------- | :----------- | :-------------------------------------------------------- |\n| `target` | `Object3D \\| null` | `null` | 要跟踪的对象。 |\n| `type` | `'position' \\| 'box3'` | `'position'` | 跟踪世界位置还是包围盒中心。 |\n| `offset` | `Vector3` | `(0,0,0)` | 在移动相机前叠加到跟踪位置上的偏移量。 |\n"
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
"id": "api-plugin-u-manager",
|
|
755
|
+
"path": "api-plugin-u-manager.md",
|
|
756
|
+
"title": "u-manager",
|
|
757
|
+
"summary": "`u-manager` 是一套全面的加载器和解析器,用于从服务器路径流式传输、解密并显示结构化场景数据。支持场景、拓扑、动画、属性和相机视点。 所有加载器均继承自 Three.js 的 `Loader`,并提供 `setPath(path)` 方法,在调用 `loadAsync()` 前配置基础数据目录。 从服务端场景包加载完整场景树(模型、组、形状、拉伸区域),并自动将所有已加载对象按 `id` 和 `sid` 注册到 `viewer.objectManager`。",
|
|
758
|
+
"headings": [
|
|
759
|
+
{
|
|
760
|
+
"level": 1,
|
|
761
|
+
"text": "u-manager"
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
"level": 2,
|
|
765
|
+
"text": "SceneLoader"
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
"level": 2,
|
|
769
|
+
"text": "TopologiesLoader / TopologyParser"
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
"level": 2,
|
|
773
|
+
"text": "VisionsLoader / VisionsParser"
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
"level": 2,
|
|
777
|
+
"text": "AnimationsLoader / AnimationsParser"
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
"level": 2,
|
|
781
|
+
"text": "PropertiesLoader"
|
|
782
|
+
}
|
|
783
|
+
],
|
|
784
|
+
"content": "# u-manager\n\n`u-manager` 是一套全面的加载器和解析器,用于从服务器路径流式传输、解密并显示结构化场景数据。支持场景、拓扑、动画、属性和相机视点。\n\n所有加载器均继承自 Three.js 的 `Loader`,并提供 `setPath(path)` 方法,在调用 `loadAsync()` 前配置基础数据目录。\n\n## `SceneLoader`\n\n从服务端场景包加载完整场景树(模型、组、形状、拉伸区域),并自动将所有已加载对象按 `id` 和 `sid` 注册到 `viewer.objectManager`。\n\n```typescript\nimport { SceneLoader } from 'u-space/plugins/u-manager';\n\nconst sceneLoader = new SceneLoader(viewer);\nsceneLoader.setPath('./scenes/my-scene');\nsceneLoader.setKey('YOUR_LICENSE_KEY'); // 官方授权场景必需\nconst group = await sceneLoader.loadAsync();\nviewer.scene.add(group);\n```\n\n**方法:**\n\n| 方法 | 说明 |\n| :--------------- | :------------------------------------------------------------ |\n| `setKey(key)` | 设置授权场景的 RSA 解密密钥。 |\n| `loadAsync()` | 加载并解析场景,返回包含完整层级的 `Group`。 |\n| `clearCache()` | 从 `objectManager` 中移除此加载器注册的所有 ID。 |\n| `dispose()` | 清除缓存并释放水印叠加层。 |\n\n## `TopologiesLoader` / `TopologyParser`\n\n加载拓扑图数据并将其转换为 `Topology` 对象。\n\n```typescript\nimport { TopologiesLoader } from 'u-space/plugins/u-manager';\n\nconst loader = new TopologiesLoader();\nloader.setPath('./scenes/my-scene');\nconst topologies = await loader.loadAsync(); // Topology[]\nviewer.scene.add(...topologies);\n```\n\n## `VisionsLoader` / `VisionsParser`\n\n加载命名相机视点,并将相机飞行到指定视点。\n\n```typescript\nimport { VisionsLoader, VisionsParser } from 'u-space/plugins/u-manager';\n\nconst visionsLoader = new VisionsLoader();\nvisionsLoader.setPath('./scenes/my-scene');\nconst visionsData = await visionsLoader.loadAsync();\n// visionsData 是 Record<string, IVisions[]>\n\nconst visionsParser = new VisionsParser(viewer);\n\n// 飞行到指定视点\nawait visionsParser.flyTo(visionsData['HOME'][0]);\n\n// 飞行到主(默认)视点\nawait visionsParser.flyToPrimary(visionsData['HOME']);\n```\n\n**`IVisions` 字段:**\n\n| 字段 | 类型 | 说明 |\n| :--------- | :------------ | :------------------------------ |\n| `camera` | `'P' \\| 'O'` | 相机类型:透视或正交。 |\n| `position` | `IVector3` | 相机世界位置。 |\n| `target` | `IVector3` | 相机朝向目标点。 |\n| `zoom` | `number` | 相机缩放级别。 |\n| `primary` | `boolean` | 是否为默认视点。 |\n\n## `AnimationsLoader` / `AnimationsParser`\n\n加载关键帧动画数据,并通过 `tweenAnimation` 驱动 `Object3D` 的变换。\n\n```typescript\nimport { AnimationsLoader, AnimationsParser } from 'u-space/plugins/u-manager';\n\nconst animLoader = new AnimationsLoader();\nanimLoader.setPath('./scenes/my-scene');\nconst animationsData = await animLoader.loadAsync(); // IAnimations[]\n\n// 查找特定对象的动画\nconst data = animationsData.find((a) => a.modelId === myModel.userData.id);\n\nconst parser = new AnimationsParser(viewer, myModel);\nparser.initTransform(); // 保存初始位置/旋转/缩放\n\nawait parser.play(data.keyframes); // 播放动画序列\n\n// 中途停止\nparser.stop();\n\n// 重置到初始变换\nparser.reset();\n```\n\n## `PropertiesLoader`\n\n加载与模型关联的结构化属性元数据(如 BIM 属性)。\n\n```typescript\nimport { PropertiesLoader } from 'u-space/plugins/u-manager';\n\nconst propsLoader = new PropertiesLoader();\npropsLoader.setPath('./scenes/my-scene');\nconst properties = await propsLoader.loadAsync(); // IProperties[]\n\n// 查找模型的属性\nconst modelProps = properties.filter(p => p.modelId === myModel.userData.id);\n```\n\n**`IProperties` 字段:**\n\n| 字段 | 类型 | 说明 |\n| :-------- | :--------------- | :----------------------- |\n| `modelId` | `string` | 关联模型的 ID。 |\n| `group` | `string` | 属性分组/类别名称。 |\n| `key` | `string` | 属性键名。 |\n| `value` | `string \\| null` | 属性值。 |\n| `label` | `string \\| null` | 属性的显示标签。 |\n"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
"id": "api-render-pipeline",
|
|
788
|
+
"path": "api-render-pipeline.md",
|
|
789
|
+
"title": "RenderPipeline API(后处理管线)",
|
|
790
|
+
"summary": "`viewer.renderPipeline` 管理渲染后处理链,内置 Bloom、SSGI、TRAA 支持,并提供自定义后处理覆盖机制。 ``` Stage 1: pass(scene, camera) + MRT(按需配置 output/emissive/normal/velocity)",
|
|
791
|
+
"headings": [
|
|
792
|
+
{
|
|
793
|
+
"level": 1,
|
|
794
|
+
"text": "RenderPipeline API(后处理管线)"
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
"level": 2,
|
|
798
|
+
"text": "渲染节点图"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
"level": 2,
|
|
802
|
+
"text": "属性"
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
"level": 2,
|
|
806
|
+
"text": "Bloom"
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
"level": 3,
|
|
810
|
+
"text": "BloomConfig"
|
|
811
|
+
},
|
|
812
|
+
{
|
|
813
|
+
"level": 2,
|
|
814
|
+
"text": "SSGI(屏幕空间全局光照)"
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
"level": 3,
|
|
818
|
+
"text": "SSGIConfig"
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
"level": 2,
|
|
822
|
+
"text": "TRAA(时间抗锯齿)"
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
"level": 2,
|
|
826
|
+
"text": "自定义后处理(OutputComposer)"
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
"level": 2,
|
|
830
|
+
"text": "Overlay Passes"
|
|
831
|
+
}
|
|
832
|
+
],
|
|
833
|
+
"content": "# RenderPipeline API(后处理管线)\n\n`viewer.renderPipeline` 管理渲染后处理链,内置 Bloom、SSGI、TRAA 支持,并提供自定义后处理覆盖机制。\n\n## 渲染节点图\n\n```\nStage 1: pass(scene, camera) + MRT(按需配置 output/emissive/normal/velocity)\n ↓\nStage 2: 后处理链(二选一)\n ├─ 内置模式: SSGI → Bloom(按启用状态组合)\n └─ 自定义模式: outputComposer(scenePass) → Node\n ↓\nStage 3: TRAA 时间抗锯齿\n ↓\nStage 4: Overlay Passes(blendColor 叠加 ViewerHelper 等)\n ↓\noutputNode = 最终结果\n```\n\n## 属性\n\n| 属性 | 类型 | 说明 |\n| :--- | :--- | :--- |\n| `scenePass` | `PassNode` | 场景渲染通道节点,`pass(scene, camera)` 的返回值。 |\n| `needsUpdateOutputNode` | `boolean` | 标记输出节点需要在下一帧重建。 |\n\n## Bloom\n\n基于 emissive MRT 通道的泛光效果。\n\n```typescript\n// 开启 Bloom\nviewer.renderPipeline.enableBloom({ strength: 1.5, radius: 0.4, threshold: 0.2 });\n\n// 运行时更新参数\nviewer.renderPipeline.updateBloom({ strength: 2.0 });\n\n// 关闭 Bloom\nviewer.renderPipeline.disableBloom();\n```\n\n### `BloomConfig`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :--- | :--- | :----- | :--- |\n| `strength` | `number` | `1` | 泛光强度 |\n| `radius` | `number` | `0` | 泛光扩散半径 |\n| `threshold` | `number` | `0` | 亮度阈值,低于此值不产生泛光 |\n\n## SSGI(屏幕空间全局光照)\n\n> 仅支持 `PerspectiveCamera`,使用 `OrthographicCamera` 时会自动跳过并输出警告。\n\n```typescript\n// 开启 SSGI\nviewer.renderPipeline.enableSSGI({ aoIntensity: 1, giIntensity: 10 });\n\n// 运行时更新参数(直接修改 uniform,不重建节点图)\nviewer.renderPipeline.updateSSGI({ giIntensity: 20, radius: 8 });\n\n// 关闭 SSGI\nviewer.renderPipeline.disableSSGI();\n```\n\n### `SSGIConfig`\n\n| 属性 | 类型 | 默认值 | 范围 | 说明 |\n| :--- | :--- | :----- | :--- | :--- |\n| `sliceCount` | `number` | `1` | 1–4 | 半球切片数 |\n| `stepCount` | `number` | `12` | 1–32 | 每切片采样步数 |\n| `aoIntensity` | `number` | `1` | 0–4 | 环境光遮蔽强度 |\n| `giIntensity` | `number` | `10` | 0–100 | 间接漫反射强度 |\n| `radius` | `number` | `12` | 1–25 | 世界空间采样半径 |\n| `thickness` | `number` | `1` | 0.01–10 | 物体厚度(世界单位) |\n\n## TRAA(时间抗锯齿)\n\n基于运动向量的时间分辨率抗锯齿。\n\n```typescript\n// 开启 TRAA\nviewer.renderPipeline.enableTRAA();\n\n// 关闭 TRAA\nviewer.renderPipeline.disableTRAA();\n```\n\n## 自定义后处理(OutputComposer)\n\n使用 `setOutputComposer` 可完全覆盖内置后处理链,接收 `scenePass` 返回自定义的 TSL 节点。\n\n```typescript\nimport { luminance, vec4 } from 'three/tsl';\n\n// 灰度滤镜\nviewer.renderPipeline.setOutputComposer((scenePass) => {\n const color = scenePass.getTextureNode();\n const gray = luminance(color.rgb);\n return vec4(gray, gray, gray, 1.0);\n});\n\n// 恢复默认(清除自定义后处理)\nviewer.renderPipeline.setOutputComposer(null);\n```\n\n## Overlay Passes\n\n用于叠加辅助渲染层(如 ViewerHelper),始终在后处理链之后执行。\n\n```typescript\nviewer.renderPipeline.addOverlayPass(overlayNode);\nviewer.renderPipeline.removeOverlayPass(overlayNode);\n```\n"
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
"id": "api-tools",
|
|
837
|
+
"path": "api-tools.md",
|
|
838
|
+
"title": "Tools API",
|
|
839
|
+
"summary": "`u-space` 提供了一组实用工具类,包括测量、剖切和标注功能。 用于 3D 场景中的距离测量、面积测量和角度测量,测量结果会以可视化线条渲染到场景中。 ```typescript",
|
|
840
|
+
"headings": [
|
|
841
|
+
{
|
|
842
|
+
"level": 1,
|
|
843
|
+
"text": "Tools API"
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
"level": 2,
|
|
847
|
+
"text": "MeasureTool"
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
"level": 3,
|
|
851
|
+
"text": "measureDistance(pointA, pointB, options?)"
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
"level": 3,
|
|
855
|
+
"text": "measureArea(points, options?)"
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
"level": 3,
|
|
859
|
+
"text": "measureAngle(pointA, vertex, pointC, options?)"
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
"level": 3,
|
|
863
|
+
"text": "MeasureResult"
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
"level": 3,
|
|
867
|
+
"text": "MeasureStyleOptions"
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
"level": 3,
|
|
871
|
+
"text": "管理方法"
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
"level": 2,
|
|
875
|
+
"text": "ClippingTool"
|
|
876
|
+
},
|
|
877
|
+
{
|
|
878
|
+
"level": 3,
|
|
879
|
+
"text": "attach() / detach()"
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
"level": 3,
|
|
883
|
+
"text": "addPlane(id, options?)"
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
"level": 4,
|
|
887
|
+
"text": "ClippingPlaneOptions"
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
"level": 3,
|
|
891
|
+
"text": "addBox(id, box, options?) / addBoxFromObject(id, object, padding?, options?)"
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
"level": 3,
|
|
895
|
+
"text": "动态调整"
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
"level": 3,
|
|
899
|
+
"text": "Helper 控制"
|
|
900
|
+
},
|
|
901
|
+
{
|
|
902
|
+
"level": 3,
|
|
903
|
+
"text": "管理方法"
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
"level": 2,
|
|
907
|
+
"text": "AnnotationManager"
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
"level": 3,
|
|
911
|
+
"text": "setCSSObjectFactory(factory)"
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
"level": 3,
|
|
915
|
+
"text": "add(id, options)"
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
"level": 4,
|
|
919
|
+
"text": "AnnotationOptions"
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
"level": 3,
|
|
923
|
+
"text": "addText(text, position, options?)"
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"level": 3,
|
|
927
|
+
"text": "更新与控制"
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
"level": 3,
|
|
931
|
+
"text": "管理方法"
|
|
932
|
+
}
|
|
933
|
+
],
|
|
934
|
+
"content": "# Tools API\n\n`u-space` 提供了一组实用工具类,包括测量、剖切和标注功能。\n\n## MeasureTool\n\n用于 3D 场景中的距离测量、面积测量和角度测量,测量结果会以可视化线条渲染到场景中。\n\n```typescript\nimport { MeasureTool } from 'u-space';\n\nconst measureTool = new MeasureTool(viewer.scene);\n```\n\n### `measureDistance(pointA, pointB, options?)`\n\n测量两点之间的距离,并在场景中绘制连线。\n\n```typescript\nconst result = measureTool.measureDistance(\n { x: 0, y: 0, z: 0 },\n { x: 5, y: 0, z: 5 },\n { lineColor: 0xffff00 },\n);\nconsole.log(result.value, result.unit); // 7.071 m\n```\n\n### `measureArea(points, options?)`\n\n测量由 3 个或更多共面点围成的多边形面积。\n\n```typescript\nconst result = measureTool.measureArea([\n { x: 0, y: 0, z: 0 },\n { x: 5, y: 0, z: 0 },\n { x: 5, y: 0, z: 5 },\n { x: 0, y: 0, z: 5 },\n], { lineColor: 0x00ff00 });\nconsole.log(result.value, result.unit); // 25 m²\n```\n\n### `measureAngle(pointA, vertex, pointC, options?)`\n\n测量以中间点为顶点的夹角(单位:度)。\n\n```typescript\nconst result = measureTool.measureAngle(\n { x: 3, y: 0, z: 0 },\n { x: 0, y: 0, z: 0 },\n { x: 0, y: 0, z: 3 },\n);\nconsole.log(result.value, result.unit); // 90 °\n```\n\n### `MeasureResult`\n\n所有测量方法返回 `MeasureResult` 对象:\n\n| 属性 | 类型 | 说明 |\n| :------- | :---------- | :--------------------------------- |\n| `id` | `string` | 测量的唯一标识。 |\n| `type` | `string` | `'distance'` / `'area'` / `'angle'`。|\n| `value` | `number` | 测量值。 |\n| `unit` | `string` | 单位(`m`、`m²`、`°`)。 |\n| `points` | `Vector3[]` | 测量点坐标。 |\n| `object` | `Group` | 场景中的可视化对象。 |\n\n### `MeasureStyleOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :---------- | :-------------------- | :--------- | :----------- |\n| `lineColor` | `ColorRepresentation` | 因方法而异 | 线条颜色。 |\n\n### 管理方法\n\n```typescript\nmeasureTool.get('measure_dist_0'); // 获取指定测量\nmeasureTool.remove('measure_dist_0'); // 移除指定测量\nmeasureTool.removeAll(); // 清除全部\nmeasureTool.getAll(); // 获取所有测量结果\nmeasureTool.dispose(); // 释放资源\n```\n\n---\n\n## ClippingTool\n\n提供剖切面和剖切盒功能,基于 WebGPU 的 `ClippingGroup` 实现。需要被剖切的对象必须是 `ClippingGroup` 的子节点。\n\n```typescript\nimport { ClippingTool } from 'u-space';\n\nconst clippingTool = new ClippingTool(viewer.scene);\n\n// 将场景中已有的物体移入 ClippingGroup,使其受剖切影响\nclippingTool.attach();\n```\n\n### `attach()` / `detach()`\n\n`attach()` 将场景根节点的所有子对象移入内部的 `ClippingGroup`,使其受剖切面影响。`detach()` 反向操作,将对象移回场景根节点。\n\n也可以手动将对象添加到 `clippingTool.group` 中:\n\n```typescript\nclippingTool.group.add(myModel); // 仅 myModel 受剖切\n```\n\n### `addPlane(id, options?)`\n\n添加一个剖切面。\n\n```typescript\nclippingTool.addPlane('cutY', {\n normal: { x: 0, y: -1, z: 0 }, // 法线方向\n constant: 1.5, // 距离原点的偏移\n showHelper: true, // 显示 Helper\n helperSize: 5,\n helperColor: 0xff0000,\n});\n```\n\n#### `ClippingPlaneOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :------------ | :-------------------- | :----------------- | :----------------------- |\n| `normal` | `{x, y, z}` | `{x:0, y:-1, z:0}` | 法线方向。 |\n| `constant` | `number` | `0` | 距原点偏移。 |\n| `showHelper` | `boolean` | `false` | 是否显示 PlaneHelper。 |\n| `helperSize` | `number` | `5` | Helper 尺寸。 |\n| `helperColor` | `ColorRepresentation` | `0xff0000` | Helper 颜色。 |\n\n### `addBox(id, box, options?)` / `addBoxFromObject(id, object, padding?, options?)`\n\n添加由 6 个面组成的剖切盒。\n\n```typescript\nimport { Box3 } from 'three/webgpu';\n\n// 从 Box3 创建\nconst box = new Box3().setFromObject(myModel);\nclippingTool.addBox('clipBox', box);\n\n// 从对象创建(带边距)\nclippingTool.addBoxFromObject('clipBox', myModel, 0.5);\n```\n\n### 动态调整\n\n```typescript\nclippingTool.setPlaneConstant('cutY', 2.0); // 修改剖切位置\nviewer.render();\n```\n\n### Helper 控制\n\n```typescript\nclippingTool.showHelper('cutY', 5, 0xff0000);\nclippingTool.hideHelper('cutY');\n```\n\n### 管理方法\n\n```typescript\nclippingTool.get('cutY'); // 获取 Plane 对象\nclippingTool.removePlane('cutY'); // 移除单个\nclippingTool.removeBox('clipBox'); // 移除剖切盒(6 个面)\nclippingTool.removeAll(); // 移除全部\nclippingTool.enable(); // 启用剖切\nclippingTool.disable(); // 禁用剖切\nclippingTool.dispose(); // 释放资源(对象移回场景根节点)\n```\n\n---\n\n## AnnotationManager\n\n管理 3D 标注,支持引线标注和 HTML 标签。配合 `CSSRenderer` 使用可实现 HTML 浮动标签。\n\n```typescript\nimport { AnnotationManager } from 'u-space';\n\nconst annotationManager = new AnnotationManager(viewer.scene);\n```\n\n### `setCSSObjectFactory(factory)`\n\n设置 CSS 对象工厂函数(来自 `CSSRenderer`),使标注可渲染为 CSS 叠加元素。\n\n```typescript\nannotationManager.setCSSObjectFactory(\n (el) => viewer.cssRenderer.createCSS2DObject(el),\n);\n```\n\n### `add(id, options)`\n\n添加一个标注。\n\n```typescript\nannotationManager.add('label-01', {\n position: { x: 0, y: 3, z: 0 },\n content: '<b>设备 A</b><br>温度: 25°C',\n labelOffset: { x: 0, y: 2, z: 0 },\n showLeaderLine: true,\n lineColor: 0xffffff,\n labelStyle: {\n background: 'rgba(0, 0, 0, 0.8)',\n padding: '8px 12px',\n borderRadius: '6px',\n },\n});\n```\n\n#### `AnnotationOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :--------------- | :------------------------ | :---------- | :--------------------- |\n| `position` | `{x, y, z}` | — | 标注锚点位置。 |\n| `content` | `string` | — | HTML 内容。 |\n| `labelOffset` | `{x, y, z}` | `{0, 2, 0}` | 标签相对锚点的偏移。 |\n| `showLeaderLine` | `boolean` | `true` | 是否显示引线。 |\n| `lineColor` | `ColorRepresentation` | `0xffffff` | 引线颜色。 |\n| `labelStyle` | `Partial<CSSStyleDeclaration>` | — | 自定义 CSS 样式。 |\n\n### `addText(text, position, options?)`\n\n快捷添加纯文本标注。\n\n```typescript\nannotationManager.addText('入口', { x: 5, y: 0, z: 0 });\n```\n\n### 更新与控制\n\n```typescript\nannotationManager.updateContent('label-01', '温度: 30°C');\nannotationManager.updatePosition('label-01', { x: 1, y: 3, z: 0 });\nannotationManager.show('label-01');\nannotationManager.hide('label-01');\nannotationManager.showAll();\nannotationManager.hideAll();\n```\n\n### 管理方法\n\n```typescript\nannotationManager.get('label-01'); // 获取标注对象\nannotationManager.remove('label-01'); // 移除标注\nannotationManager.removeAll(); // 移除全部\nannotationManager.keys(); // 获取所有 ID\nannotationManager.size; // 标注数量\nannotationManager.dispose(); // 释放资源\n```\n"
|
|
935
|
+
},
|
|
936
|
+
{
|
|
937
|
+
"id": "api-viewer",
|
|
938
|
+
"path": "api-viewer.md",
|
|
939
|
+
"title": "Viewer API",
|
|
940
|
+
"summary": "`Viewer` 是 `u-space` 的核心类,它将 WebGPU 渲染器、场景、相机、控制器以及各种管理器封装为一个易用的接口。 ```typescript new Viewer(options: ViewerOptions)",
|
|
941
|
+
"headings": [
|
|
942
|
+
{
|
|
943
|
+
"level": 1,
|
|
944
|
+
"text": "Viewer API"
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
"level": 2,
|
|
948
|
+
"text": "构造函数"
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
"level": 3,
|
|
952
|
+
"text": "ViewerOptions"
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
"level": 2,
|
|
956
|
+
"text": "属性"
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
"level": 2,
|
|
960
|
+
"text": "方法"
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"level": 3,
|
|
964
|
+
"text": "init()"
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
"level": 3,
|
|
968
|
+
"text": "render(frame?: number)"
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
"level": 3,
|
|
972
|
+
"text": "setCamera(camera: PerspectiveCamera | OrthographicCamera)"
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
"level": 3,
|
|
976
|
+
"text": "setCameraByType(type: 'perspective' | 'orthographic')"
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
"level": 3,
|
|
980
|
+
"text": "createScene()"
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
"level": 3,
|
|
984
|
+
"text": "createPerspectiveCamera()"
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
"level": 3,
|
|
988
|
+
"text": "createOrthographicCamera()"
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
"level": 3,
|
|
992
|
+
"text": "resize(width?, height?)"
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
"level": 3,
|
|
996
|
+
"text": "screenshot(options?)"
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
"level": 4,
|
|
1000
|
+
"text": "ScreenshotOptions"
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
"level": 3,
|
|
1004
|
+
"text": "setBackground(background)"
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
"level": 3,
|
|
1008
|
+
"text": "setEnvironment(envMap)"
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
"level": 3,
|
|
1012
|
+
"text": "enableShadow() / disableShadow()"
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
"level": 3,
|
|
1016
|
+
"text": "enableFog(options?) / enableFogExp2(options?) / disableFog()"
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
"level": 4,
|
|
1020
|
+
"text": "FogOptions"
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
"level": 4,
|
|
1024
|
+
"text": "FogExp2Options"
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
"level": 2,
|
|
1028
|
+
"text": "调试工具"
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
"level": 3,
|
|
1032
|
+
"text": "Info"
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
"level": 3,
|
|
1036
|
+
"text": "ViewerHelper"
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
"level": 3,
|
|
1040
|
+
"text": "dispose()"
|
|
1041
|
+
},
|
|
1042
|
+
{
|
|
1043
|
+
"level": 2,
|
|
1044
|
+
"text": "事件"
|
|
1045
|
+
}
|
|
1046
|
+
],
|
|
1047
|
+
"content": "# Viewer API\n\n`Viewer` 是 `u-space` 的核心类,它将 WebGPU 渲染器、场景、相机、控制器以及各种管理器封装为一个易用的接口。\n\n## 构造函数\n\n```typescript\nnew Viewer(options: ViewerOptions)\n```\n\n### `ViewerOptions`\n\n| 属性 | 类型 | 必填 | 说明 |\n| :---------------- | :------------------------- | :--- | :------------------------------------------------------------------------------------------------------------- |\n| `el` | `HTMLElement` | 是 | WebGPURenderer 的 canvas 将被注入到此 DOM 元素中。 |\n| `rendererOptions` | `WebGPURendererParameters` | 否 | 直接传递给底层 `WebGPURenderer` 的选项。默认使用 WebGPU 的高性能配置。 |\n\n## 属性\n\n`Viewer` 实例暴露了若干核心 Three.js 和 `u-space` 组件。\n\n| 属性 | 类型 | 说明 |\n| :------------------- | :------------------------------------------ | :---------------------------------------------------------------------------------------------------------------- |\n| `el` | `HTMLElement` | 容器元素。 |\n| `renderer` | `WebGPURenderer` | 底层 WebGPU 渲染器实例。 |\n| `scene` | `Scene` | 主 Three.js 场景,背景默认为 `0x000000`。 |\n| `camera` | `PerspectiveCamera` \\| `OrthographicCamera` | 当前激活的相机。 |\n| `controls` | `CameraControls` | 相机控制器(基于 `camera-controls` 库)。 |\n| `renderPipeline` | `RenderPipeline` | 管理后处理通道和最终渲染调用。 |\n| `timer` | `Timer` | Three.js `Timer` 实例,用于每帧精确的 delta time 跟踪。 |\n| `roomEnvironment` | `RoomEnvironment` | 为场景提供默认的类室内 IBL 环境贴图。 |\n| `info` | `Info` | 以叠加层的形式渲染渲染器诊断信息(绘制调用次数、三角面数量等)。 |\n| `viewerHelper` | `ViewerHelper` | 提供实用辅助工具(如坐标轴、网格显示),用于开发/调试。 |\n| `interactionManager` | `InteractionManager` | 管理对象的指针事件和射线检测。 |\n| `objectManager` | `ObjectManager` | 用于按 ID 或名称注册和检索对象的工具。 |\n| `frameloop` | `'always'` \\| `'demand'` | 设置渲染模式。默认为 `'demand'`(仅在需要时渲染)。设置为 `'always'` 可开启持续渲染。 |\n| `cssRenderer` | `CSSRenderer` | CSS 渲染器,支持在 3D 场景中叠加 HTML 元素(CSS2D / CSS2.5D / CSS3D)。 |\n| `frameCount` | `number` | 待渲染帧的内部计数器,调用 `render()` 时递增。 |\n\n## 方法\n\n### `init()`\n\n异步初始化渲染器。如果需要确保渲染器(如环境设置或插件)完全就绪,必须调用此方法。\n\n```typescript\nawait viewer.init();\n```\n\n### `render(frame?: number)`\n\n请求渲染一帧。在 `'demand'` 模式下,每当场景发生视觉变化时必须调用此方法来更新画布。`frame` 指定渲染的帧数(默认 `1`)。返回一个在帧渲染完成后 resolve 的 `Promise<void>`。\n\n```typescript\nviewer.render();\n\n// 等待帧渲染完成\nawait viewer.render();\n```\n\n### `setCamera(camera: PerspectiveCamera | OrthographicCamera)`\n\n为查看器设置自定义相机,并自动更新控制器和交互管理器以使用该相机。\n\n```typescript\nconst customCamera = new PerspectiveCamera(75, width / height, 0.1, 1000);\nviewer.setCamera(customCamera);\n```\n\n### `setCameraByType(type: 'perspective' | 'orthographic')`\n\n便捷方法,在保持查看器上下文的同时切换相机类型。\n\n```typescript\nviewer.setCameraByType('orthographic');\n```\n\n### `createScene()`\n\n创建并返回一个黑色背景的新 `Scene`。由构造函数内部调用,也可用于重置/替换场景。\n\n```typescript\nviewer.scene = viewer.createScene();\n```\n\n### `createPerspectiveCamera()`\n\n使用合理的默认值创建 `PerspectiveCamera`(视角 50°,近裁 `0.1`,远裁 `1e5`,位置在 `(5, 5, 5)`)。\n\n```typescript\nconst camera = viewer.createPerspectiveCamera();\nviewer.setCamera(camera);\n```\n\n### `createOrthographicCamera()`\n\n创建与容器元素等大的 `OrthographicCamera`,近裁 `0.1`,远裁 `1e5`,位置在 `(5, 5, 5)`。\n\n```typescript\nconst camera = viewer.createOrthographicCamera();\nviewer.setCamera(camera);\n```\n\n### `resize(width?, height?)`\n\n手动触发容器尺寸更新。可选传入指定宽高。\n\n```typescript\n// 手动触发 resize(如容器尺寸变化后)\nviewer.resize();\n\n// 指定新尺寸\nviewer.resize(800, 600);\n```\n\n### `screenshot(options?)`\n\n捕获当前渲染画面并返回 Data URL。\n\n```typescript\nconst dataUrl = await viewer.screenshot();\n\n// 指定格式和分辨率\nconst dataUrl = await viewer.screenshot({\n width: 1920,\n height: 1080,\n type: 'image/png',\n quality: 1.0,\n});\n```\n\n#### `ScreenshotOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :-------- | :---------------------------------------------- | :------------ | :--------------------- |\n| `width` | `number` | 容器宽度 | 截图宽度。 |\n| `height` | `number` | 容器高度 | 截图高度。 |\n| `type` | `'image/png'` \\| `'image/jpeg'` \\| `'image/webp'` | `'image/png'` | 图片格式。 |\n| `quality` | `number` | `1.0` | 图片质量(0-1)。 |\n\n### `setBackground(background)`\n\n设置场景背景颜色、纹理或清除背景。\n\n```typescript\nviewer.setBackground(0x333333); // 颜色\nviewer.setBackground('#87ceeb'); // CSS 颜色字符串\nviewer.setBackground(hdrTexture); // 纹理\nviewer.setBackground(null); // 清除背景\n```\n\n### `setEnvironment(envMap)`\n\n设置场景环境贴图(用于反射/IBL)。\n\n```typescript\nviewer.setEnvironment(hdrTexture);\nviewer.setEnvironment(null); // 清除\n```\n\n### `enableShadow()` / `disableShadow()`\n\n开启或关闭阴影渲染。\n\n```typescript\nviewer.enableShadow();\nviewer.disableShadow();\n```\n\n### `enableFog(options?)` / `enableFogExp2(options?)` / `disableFog()`\n\n开启线性雾、指数雾或关闭雾效。\n\n```typescript\n// 线性雾\nviewer.enableFog({ color: 0xcccccc, near: 10, far: 100 });\n\n// 指数雾\nviewer.enableFogExp2({ color: 0xcccccc, density: 0.01 });\n\n// 关闭雾效\nviewer.disableFog();\n```\n\n#### `FogOptions`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :------ | :-------------------- | :---------- | :------------- |\n| `color` | `ColorRepresentation` | `0xcccccc` | 雾的颜色。 |\n| `near` | `number` | `10` | 雾的起始距离。 |\n| `far` | `number` | `100` | 雾的结束距离。 |\n\n#### `FogExp2Options`\n\n| 属性 | 类型 | 默认值 | 说明 |\n| :-------- | :-------------------- | :---------- | :------------- |\n| `color` | `ColorRepresentation` | `0xcccccc` | 雾的颜色。 |\n| `density` | `number` | `0.01` | 雾的密度。 |\n\n## 调试工具\n\n### Info\n\n`viewer.info` 是一个轻量的渲染统计叠加层,显示当前帧的 GPU 诊断数据,适合开发调试阶段使用。\n\n```typescript\nviewer.info.enable(); // 在画面左下角显示统计信息\nviewer.info.disable(); // 隐藏统计信息\n```\n\n启用后将在 `viewer.el` 左下角叠加以下数据:\n\n| 指标 | 说明 |\n| :------------- | :---------------------------- |\n| `draw calls` | 当前帧的绘制调用次数 |\n| `frame calls` | 当前帧的帧调用次数 |\n| `triangles` | 当前帧渲染的三角面数量 |\n| `points` | 当前帧渲染的点数量 |\n| `lines` | 当前帧渲染的线段数量 |\n| `timestamp` | GPU 渲染耗时(ms,WebGPU 专属)|\n\n> `timestamp` 指标仅在 WebGPU 后端可用,WebGL 回退模式下显示 `0`。\n\n### ViewerHelper\n\n`viewer.viewerHelper` 是一个方向指示器 gizmo(基于 Three.js `ViewHelper`),显示当前相机朝向的 XYZ 轴,渲染为画面角落的叠加层。\n\n```typescript\nviewer.viewerHelper.enable(); // 显示方向 gizmo\nviewer.viewerHelper.disable(); // 隐藏方向 gizmo\n```\n\n**属性:**\n\n| 属性 | 类型 | 说明 |\n| :------------- | :---------- | :---------------------------------------- |\n| `location` | `object` | gizmo 在画面中的位置,支持 `top`、`bottom`、`left`、`right` 偏移(像素)。默认右下角。 |\n\n```typescript\n// 调整位置到左下角\nviewer.viewerHelper.location.left = 12;\nviewer.viewerHelper.location.bottom = 12;\nviewer.viewerHelper.location.right = null;\n```\n\n### `dispose()`\n\n清理查看器,从 DOM 中移除 canvas,移除事件监听,并释放渲染器和环境贴图,以防止内存泄漏。\n\n```typescript\nviewer.dispose();\n```\n\n## 事件\n\nViewer 继承自 `EventDispatcher`,会触发以下事件:\n\n- `beforeControlsUpdate`:在 `CameraControls` 更新之前触发,提供 `{ time: number; delta: number }`。\n- `afterControlsUpdate`:在 `CameraControls` 更新之后触发,提供 `{ time: number; delta: number }`。\n- `beforeRender`:在 `renderer.render` 调用之前立即触发,提供 `{ time: number; delta: number }`。\n- `afterRender`:在 `renderer.render` 完成之后立即触发,提供 `{ time: number; delta: number }`。\n- `cameraChange`:调用 `setCamera` 时触发,提供 `{ camera: Camera }`。\n\n其中 `delta` 为上一帧到当前帧的时间间隔(秒),可用于动画更新等场景。\n"
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
"id": "changelog",
|
|
1051
|
+
"path": "changelog.md",
|
|
1052
|
+
"title": "更新日志",
|
|
1053
|
+
"summary": "- **Viewer** — `resize()`、`screenshot()`、`setBackground()`、`setEnvironment()`、`enableShadow()`/`disableShadow()`、`enableFog()`/`enableFogExp2()`/`disableFog()` - **CameraControls** — `flyTo()`、`getCameraViewpoint()`、`lock()`/`unlock()`、`setViewMode('2d' | '3d')` - **ObjectManager** — `show()`/`hide()`、`isolate()`、`showAll()`、`setOpacity()`、`getBoundingBox()`、`forEach()`、`filter()`",
|
|
1054
|
+
"headings": [
|
|
1055
|
+
{
|
|
1056
|
+
"level": 1,
|
|
1057
|
+
"text": "更新日志"
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
"level": 2,
|
|
1061
|
+
"text": "0.0.8"
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
"level": 3,
|
|
1065
|
+
"text": "新增"
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
"level": 3,
|
|
1069
|
+
"text": "修复"
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
"level": 2,
|
|
1073
|
+
"text": "0.0.7"
|
|
1074
|
+
},
|
|
1075
|
+
{
|
|
1076
|
+
"level": 3,
|
|
1077
|
+
"text": "变更"
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
"level": 2,
|
|
1081
|
+
"text": "0.0.6"
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
"level": 3,
|
|
1085
|
+
"text": "新增"
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
"level": 2,
|
|
1089
|
+
"text": "0.0.5"
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
"level": 3,
|
|
1093
|
+
"text": "变更"
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
"level": 2,
|
|
1097
|
+
"text": "0.0.4"
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
"level": 3,
|
|
1101
|
+
"text": "新增"
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
"level": 2,
|
|
1105
|
+
"text": "0.0.3"
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
"level": 3,
|
|
1109
|
+
"text": "新增"
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
"level": 3,
|
|
1113
|
+
"text": "变更"
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
"level": 2,
|
|
1117
|
+
"text": "0.0.0"
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
"level": 3,
|
|
1121
|
+
"text": "新增"
|
|
1122
|
+
}
|
|
1123
|
+
],
|
|
1124
|
+
"content": "# 更新日志\n\n## 0.0.8\n\n### 新增\n\n- **Viewer** — `resize()`、`screenshot()`、`setBackground()`、`setEnvironment()`、`enableShadow()`/`disableShadow()`、`enableFog()`/`enableFogExp2()`/`disableFog()`\n- **CameraControls** — `flyTo()`、`getCameraViewpoint()`、`lock()`/`unlock()`、`setViewMode('2d' | '3d')`\n- **ObjectManager** — `show()`/`hide()`、`isolate()`、`showAll()`、`setOpacity()`、`getBoundingBox()`、`forEach()`、`filter()`\n- **InteractionManager** — `enable()`/`disable()`、`setInteractable()`、`addIgnore()`/`removeIgnore()`\n- **Selection** — 新增框选(rubber-band)和单选/多选/切换模块,支持 `select`/`deselect`/`change` 事件\n- **MaterialEffects** — `wireframe()`/`removeWireframe()`、`transparent()`/`removeTransparent()`、`xray()`/`removeXray()`、`fadeIn()`/`fadeOut()`\n- **Model** — `getBoundingBox()`、`getCenter()`、`setMaterial()`\n- **SceneManager** — 新模块,多场景创建、注册、切换与序列化\n- **LightManager** — 新模块,灯光便捷创建、4 种预设(indoor/outdoor/studio/warehouse)、Helper 可视化\n- **MeasureTool** — 新工具,距离/面积/角度测量,结果可视化渲染到场景\n- **ClippingTool** — 新工具,基于 WebGPU `ClippingGroup` 的剖切面与剖切盒\n- **AnnotationManager** — 新工具,3D 引线标注 + HTML 浮动标签\n- **示例** — 新增 8 个交互式示例页面\n\n### 修复\n\n- **Selection** — 框选覆盖层改为挂载到容器元素(而非 canvas),修复框选矩形不可见的问题\n- **ClippingTool** — 从 `renderer.clippingPlanes`(WebGL API)重写为 `ClippingGroup`(WebGPU API),修复剖切无效的问题\n- **MaterialEffects** — fade 动画在对象移除场景后自动停止,避免内存泄漏\n- **InteractionManager** — `dispose()` 中清除 `clickTimer`,避免定时器泄漏\n- **LightManager** — 修复 `removeAll()`/`hideAllHelpers()` 中遍历 Map 同时删除的问题\n- **ObjectManager** — `setOpacity()` 先检查 `isMesh` 再类型转换\n- **ClippingTool** — `PlaneHelper` 颜色使用 `new Color(color).getHex()` 替代直接 `as number`\n- **MeasureTool** — 移除 WebGPU 不支持的 `linewidth` 属性\n\n---\n\n## 0.0.7\n\n### 变更\n\n- 文档拆分:将插件文档拆分为独立文件\n- 新增 CameraControls 独立文档页\n- 修复 getting-started 中的死链\n- 修复 sbmx loader 示例使用新的 MaterialEffects API\n\n---\n\n## 0.0.6\n\n### 新增\n\n- **MaterialEffects** — 可组合的材质特效系统,支持安全共享材质和 remove API\n- **RenderPipeline** — 内置 Bloom、SSGI、TRAA 后处理及 OutputComposer API\n- **CSSRenderer** — CSS2D / CSS2.5D / CSS3D 叠加渲染 HTML 元素\n- 从 `package.json` 导出 `version`,统一示例 importmap\n\n---\n\n## 0.0.5\n\n### 变更\n\n- 版本发布(无重大功能变更)\n\n---\n\n## 0.0.4\n\n### 新增\n\n- **Model** — 动画播放支持(`playAnimation`、`stopAnimation`、`updateAnimation`)\n- **ViewerEventMap** — 事件回调新增 `delta` 时间参数\n\n---\n\n## 0.0.3\n\n### 新增\n\n- **ObjectControls** 插件 — 交互式移动、旋转、缩放 3D 对象\n- **TopologyDrawer** 插件 — 在场景任意表面交互式绘制拓扑路径图\n- **Topology** — `exportData()` / `importData()` 数据序列化\n\n### 变更\n\n- **Interactions** — `contextmenu` 事件替换为 `rightclick`\n- **Poi** — 优化渲染性能,新增 `scaleFactor` 参数\n- 文档全面完善:本地搜索、侧边栏优化、各插件文档页\n\n---\n\n## 0.0.0\n\n### 新增\n\n- 项目初始化:Viewer 核心、WebGPU 渲染器、场景/相机/控制器\n- 模型加载系统:双层缓存(内存 + 持久化)、Draco/KTX2/Meshopt 支持\n- 交互系统:射线检测、事件冒泡、自定义 3D 对象事件\n- 对象系统:Model、Poi、Topology、基础网格(Sphere/Plane/Circle/Tube/Extrude/Shape)\n- ObjectManager 集中式对象注册\n- 补间动画系统\n- u-manager 插件:场景加载、动画、属性、视点管理\n- tiles 插件:ArcGIS 3D 瓦片 / GIS 地球渲染\n- minimap 插件:2D 小地图\n- keyboard-controls 插件:WASD 键盘控制\n- tracking-controls 插件:相机跟随\n- atmosphere 插件:天空/大气渲染\n- curve-movement 插件:曲线路径动画\n"
|
|
1125
|
+
},
|
|
1126
|
+
{
|
|
1127
|
+
"id": "examples-guide",
|
|
1128
|
+
"path": "examples-guide.md",
|
|
1129
|
+
"title": "示例指南",
|
|
1130
|
+
"summary": "`u-space` 的 `examples/` 目录中包含了大量演示引擎功能的示例。以下是几个关键示例及其所展示的系统特性。 该示例演示了通过 WebGPU 渲染 3D 场景所需的最少配置,与 [快速上手](./getting-started.md) 指南中的内容一致。 - 将 `Viewer` 注入 DOM 元素。",
|
|
1131
|
+
"headings": [
|
|
1132
|
+
{
|
|
1133
|
+
"level": 1,
|
|
1134
|
+
"text": "示例指南"
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
"level": 2,
|
|
1138
|
+
"text": "1. demo01.html:基础配置与交互"
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
"level": 3,
|
|
1142
|
+
"text": "核心要点:"
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
"level": 2,
|
|
1146
|
+
"text": "2. test_loader.html:模型缓存机制"
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
"level": 3,
|
|
1150
|
+
"text": "核心要点:"
|
|
1151
|
+
},
|
|
1152
|
+
{
|
|
1153
|
+
"level": 2,
|
|
1154
|
+
"text": "3. load_tiles.html:GIS 与地球渲染"
|
|
1155
|
+
},
|
|
1156
|
+
{
|
|
1157
|
+
"level": 3,
|
|
1158
|
+
"text": "核心要点:"
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
"level": 2,
|
|
1162
|
+
"text": "4. test_umanager.html:场景组合与解析器"
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
"level": 3,
|
|
1166
|
+
"text": "核心要点:"
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
"level": 2,
|
|
1170
|
+
"text": "5. test_model_animation.html:模型内置动画"
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
"level": 3,
|
|
1174
|
+
"text": "核心要点:"
|
|
1175
|
+
},
|
|
1176
|
+
{
|
|
1177
|
+
"level": 2,
|
|
1178
|
+
"text": "6. test_css_renderer.html:CSS2D / CSS2.5D / CSS3D 渲染器"
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
"level": 3,
|
|
1182
|
+
"text": "核心要点:"
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
"level": 2,
|
|
1186
|
+
"text": "7. test_postprocessing.html:后处理效果"
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
"level": 3,
|
|
1190
|
+
"text": "核心要点:"
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
"level": 2,
|
|
1194
|
+
"text": "8. test_viewer_utils.html:Viewer 工具方法"
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
"level": 3,
|
|
1198
|
+
"text": "核心要点:"
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
"level": 2,
|
|
1202
|
+
"text": "9. test_camera_controls.html:CameraControls 增强方法"
|
|
1203
|
+
},
|
|
1204
|
+
{
|
|
1205
|
+
"level": 3,
|
|
1206
|
+
"text": "核心要点:"
|
|
1207
|
+
},
|
|
1208
|
+
{
|
|
1209
|
+
"level": 2,
|
|
1210
|
+
"text": "10. test_object_manager.html:ObjectManager 增强方法"
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
"level": 3,
|
|
1214
|
+
"text": "核心要点:"
|
|
1215
|
+
},
|
|
1216
|
+
{
|
|
1217
|
+
"level": 2,
|
|
1218
|
+
"text": "11. test_material_effects.html:MaterialEffects 增强效果"
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
"level": 3,
|
|
1222
|
+
"text": "核心要点:"
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
"level": 2,
|
|
1226
|
+
"text": "12. test_selection.html:Selection 选择系统"
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
"level": 3,
|
|
1230
|
+
"text": "核心要点:"
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
"level": 2,
|
|
1234
|
+
"text": "13. test_measure.html:MeasureTool 测量工具"
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
"level": 3,
|
|
1238
|
+
"text": "核心要点:"
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
"level": 2,
|
|
1242
|
+
"text": "14. test_annotation.html:AnnotationManager 标注管理"
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
"level": 3,
|
|
1246
|
+
"text": "核心要点:"
|
|
1247
|
+
},
|
|
1248
|
+
{
|
|
1249
|
+
"level": 2,
|
|
1250
|
+
"text": "15. test_clipping.html:ClippingTool 剖切工具"
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
"level": 3,
|
|
1254
|
+
"text": "核心要点:"
|
|
1255
|
+
},
|
|
1256
|
+
{
|
|
1257
|
+
"level": 2,
|
|
1258
|
+
"text": "16. test_lights.html:LightManager 灯光管理"
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
"level": 3,
|
|
1262
|
+
"text": "核心要点:"
|
|
1263
|
+
}
|
|
1264
|
+
],
|
|
1265
|
+
"content": "# 示例指南\n\n`u-space` 的 `examples/` 目录中包含了大量演示引擎功能的示例。以下是几个关键示例及其所展示的系统特性。\n\n## 1. `demo01.html`:基础配置与交互\n\n该示例演示了通过 WebGPU 渲染 3D 场景所需的最少配置,与 [快速上手](./getting-started.md) 指南中的内容一致。\n\n### 核心要点:\n\n- 将 `Viewer` 注入 DOM 元素。\n- 使用 WebGPU `Color` 设置场景背景。\n- 添加基础几何体(如 `BoxGeometry`)。\n- 通过 `viewer.interactionManager.pointerMoveEventsEnabled` 启用全局交互。\n- 像操作 DOM 元素一样,为 3D 网格原生绑定事件监听(`click`、`pointerenter`、`pointerleave`)。\n\n## 2. `test_loader.html`:模型缓存机制\n\n该示例深入解析了 `u-space` 的模型加载管线,阐明运行时缓存与浏览器持久化缓存之间的区别。\n\n### 核心要点:\n\n- 使用全局 `Model` 类通过 `Model.prototype.loadAsync()` 异步加载 `.glb` 文件。\n- 理解 `cache: true`(将模型节点保留在内存中,可实现即时克隆/实例化)。\n- 理解 `persistent: true`(使用 Service Worker / Cache Storage API 对实际网络请求数据进行持久化缓存)。\n- 演示如何将这些异步加载的资源安全地注册到 `viewer.objectManager`。\n- 提供通过 `Model.clearMemoryCache()` 和 `Model.clearPersistentCache()` 手动清除缓存的示例。\n\n## 3. `load_tiles.html`:GIS 与地球渲染\n\n该示例使用外部对等依赖 `3d-tiles-renderer`,通过 `u-space` 插件安全封装后,渲染大规模 LOD GIS 地球。\n\n### 核心要点:\n\n- 动态实例化复杂插件(`ArcgisTilesRenderer`),并传入核心 viewer 引用。\n- 由于瓦片是异步流式加载并持续更新视口的,需使用 `viewer.frameloop = 'always'`。\n- 通过插件的 `invalidate(lon, lat, zoom)` 方法定位到指定的经纬度位置。\n\n## 4. `test_umanager.html`:场景组合与解析器\n\n该综合示例融合了多种工具,展示如何构建完整的应用程序,而不仅仅是放置单个模型。\n\n### 核心要点:\n\n- 同时初始化多个插件(minimap、tracking、keyboard-controls),并通过 `.enable()` / `.disable()` 切换其状态。\n- 流式传输结构化场景布局,解析场景描述(`SceneLoader`、`TopologiesLoader`)。\n- 使用相机动画(`VisionsLoader` 和 `VisionsParser`)在场景中编排预定义的飞行路径。\n- 获取复杂的节点材质,并自定义 WebGPU 专属的 TSL(Three Shading Language)节点,如 `TSLEffects.fluid()`。\n\n## 5. `test_model_animation.html`:模型内置动画\n\n[在线演示](https://u-space-phi.vercel.app/examples/test_model_animation.html)\n\n该示例演示了如何加载含内置动画的 glTF 模型,并通过 `Model` 类的动画 API 控制播放。\n\n### 核心要点:\n\n- 使用 `Model.loadAsync()` 加载带动画的 `.glb` 文件,动画片段自动初始化。\n- 使用 `viewer.frameloop = 'always'` 开启持续渲染以驱动动画。\n- 监听 `beforeRender` 事件,通过 `model.updateAnimation(e.delta)` 推进动画时间。\n- 使用 `model.playAnimation(name)` 按名称播放单个动画,`model.playAllAnimations()` 播放全部。\n- 使用 `model.stopAnimation()` 停止动画播放。\n\n## 6. `test_css_renderer.html`:CSS2D / CSS2.5D / CSS3D 渲染器\n\n该示例演示了如何在 3D 场景中叠加渲染 HTML 元素,展示三种 CSS 渲染模式的效果差异。\n\n### 核心要点:\n\n- 使用 `viewer.cssRenderer.createCSS2DObject()` 创建始终面向相机、固定屏幕尺寸的 2D 标签。\n- 使用 `viewer.cssRenderer.createCSS25DObject()` 创建面向相机但随距离缩放的 2.5D 精灵。\n- 使用 `viewer.cssRenderer.createCSS3DObject()` 创建具有完整 3D 变换的面板。\n- CSS2.5D 和 CSS3D 对象需要设置 `scale`(通常 `0.01`),因为 HTML 元素的像素尺寸远大于 3D 世界单位。\n- 渲染器采用懒加载,仅在首次创建对应类型对象时初始化。\n\n## 7. `test_postprocessing.html`:后处理效果\n\n该示例演示了 `RenderPipeline` 的内置后处理功能,包括 Bloom、SSGI、TRAA 以及自定义后处理组合器。\n\n### 核心要点:\n\n- 使用 `viewer.renderPipeline.enableBloom()` / `disableBloom()` 运行时切换 Bloom 效果。\n- 使用 `viewer.renderPipeline.updateBloom()` 实时调整 strength、radius、threshold 参数。\n- 使用 `viewer.renderPipeline.enableSSGI()` / `disableSSGI()` 切换屏幕空间全局光照。\n- 使用 `viewer.renderPipeline.updateSSGI()` 实时调整 SSGI 参数(直接修改 uniform,无需重建节点图)。\n- 使用 `viewer.renderPipeline.enableTRAA()` / `disableTRAA()` 切换时间抗锯齿。\n- 使用 `viewer.renderPipeline.setOutputComposer()` 自定义后处理链(示例中实现了灰度滤镜)。\n- 使用 `setOutputComposer(null)` 恢复默认渲染管线。\n\n## 8. `test_viewer_utils.html`:Viewer 工具方法\n\n该示例演示了 `Viewer` 新增的便捷方法:截图导出、背景切换、雾效控制和阴影开关。\n\n### 核心要点:\n\n- 使用 `viewer.screenshot()` 导出当前渲染画面为 PNG 文件。\n- 使用 `viewer.setBackground(color)` 快速切换场景背景颜色。\n- 使用 `viewer.enableFog()` / `viewer.disableFog()` 控制雾效。\n- 使用 `viewer.enableShadow()` / `viewer.disableShadow()` 控制阴影渲染。\n- 使用 `viewer.resize(width, height)` 手动触发尺寸更新。\n\n## 9. `test_camera_controls.html`:CameraControls 增强方法\n\n该示例演示了 `CameraControls` 的飞行定位、视角存取、锁定和二三维切换功能。\n\n### 核心要点:\n\n- 使用 `viewer.controls.flyTo(position, target)` 将相机飞行到指定坐标。\n- 使用 `viewer.controls.getCameraViewpoint()` 获取当前视角数据。\n- 使用 `viewer.controls.setCameraViewpoint(data)` 恢复保存的视角。\n- 使用 `viewer.controls.lock()` / `unlock()` 锁定或解锁相机控制。\n- 使用 `viewer.controls.setViewMode('2d')` / `setViewMode('3d')` 在二三维视图间切换。\n\n## 10. `test_object_manager.html`:ObjectManager 增强方法\n\n该示例演示了 `ObjectManager` 的显隐控制、孤立显示、透明度设置、包围盒查询和过滤功能。\n\n### 核心要点:\n\n- 使用 `viewer.objectManager.show(id)` / `hide(id)` 控制对象可见性。\n- 使用 `viewer.objectManager.isolate(ids)` 孤立显示指定对象。\n- 使用 `viewer.objectManager.setOpacity(id, value)` 设置材质透明度。\n- 使用 `viewer.objectManager.getBoundingBox()` 查询所有对象的包围盒。\n- 使用 `viewer.objectManager.filter(predicate)` 按条件过滤对象。\n\n## 11. `test_material_effects.html`:MaterialEffects 增强效果\n\n该示例演示了材质效果系统的线框、半透明、X 光和淡入淡出功能。\n\n### 核心要点:\n\n- 使用 `MaterialEffects.wireframe(object)` 开启线框渲染模式。\n- 使用 `MaterialEffects.highlightColor(object, { opacity })` 设置半透明效果。\n- 使用 `MaterialEffects.highlightColor(object, { color, opacity, overwrite: true, depthWrite: false })` 实现 X 光透视效果。\n- 使用 `MaterialEffects.fadeOut(object)` / `fadeIn(object)` 执行淡入淡出动画。\n- 使用 `MaterialEffects.removeHighlightColor(object)` 恢复原始材质状态。\n\n## 12. `test_selection.html`:Selection 选择系统\n\n该示例演示了对象选择系统的单选和框选功能。\n\n### 核心要点:\n\n- 创建 `Selection` 实例并监听 `select`、`deselect`、`change` 事件。\n- 使用 `selection.select()` / `deselect()` / `toggle()` / `clear()` 进行程序化选择操作。\n- 使用 `selection.enableBoxSelection()` 开启鼠标框选模式。\n- 框选模式下可配合 `viewer.controls.lock()` 避免框选与相机旋转冲突。\n\n## 13. `test_measure.html`:MeasureTool 测量工具\n\n该示例演示了 3D 场景中的距离、面积和角度测量。\n\n### 核心要点:\n\n- 使用 `measureTool.measureDistance(pointA, pointB)` 测量两点距离。\n- 使用 `measureTool.measureArea(points)` 测量多边形面积。\n- 使用 `measureTool.measureAngle(pointA, vertex, pointC)` 测量夹角。\n- 测量结果以可视化线条渲染到场景中,返回的 `MeasureResult` 包含数值和单位。\n\n## 14. `test_annotation.html`:AnnotationManager 标注管理\n\n该示例演示了 3D 标注的创建、更新和管理,配合 `CSSRenderer` 实现 HTML 浮动标签。\n\n### 核心要点:\n\n- 创建 `AnnotationManager` 实例并通过 `setCSSObjectFactory()` 绑定 `CSSRenderer`。\n- 使用 `annotationManager.add(id, options)` 添加带引线和自定义样式的标注。\n- 使用 `annotationManager.addText(text, position)` 快捷添加纯文本标注。\n- 使用 `updateContent()` 动态更新标注内容,`updatePosition()` 移动标注位置。\n- 使用 `hideAll()` / `showAll()` 批量控制标注显隐。\n\n## 15. `test_clipping.html`:ClippingTool 剖切工具\n\n该示例演示了剖切面的创建和实时调整。\n\n### 核心要点:\n\n- 创建 `ClippingTool` 实例并调用 `attach()` 将场景物体移入 ClippingGroup。\n- 使用 `clippingTool.addPlane(id, options)` 添加剖切面。\n- 使用滑块通过 `clippingTool.setPlaneConstant()` 实时调整剖切位置。\n- 使用 `showHelper()` / `hideHelper()` 切换剖切面可视化辅助。\n\n## 16. `test_lights.html`:LightManager 灯光管理\n\n该示例演示了灯光管理器的灯光预设和 Helper 可视化功能。\n\n### 核心要点:\n\n- 创建 `LightManager` 实例并使用 `applyPreset()` 一键应用灯光预设。\n- 支持 4 种预设:`indoor`(室内)、`outdoor`(室外)、`studio`(摄影棚)、`warehouse`(仓库)。\n- 使用 `showAllHelpers()` / `hideAllHelpers()` 显示或隐藏灯光辅助可视化。\n- 每种预设会自动清除旧灯光并创建新的灯光组合。\n"
|
|
1266
|
+
},
|
|
1267
|
+
{
|
|
1268
|
+
"id": "getting-started",
|
|
1269
|
+
"path": "getting-started.md",
|
|
1270
|
+
"title": "快速上手 u-space",
|
|
1271
|
+
"summary": "`u-space` 是一个基于 Three.js 的 WebGPU 3D 引擎。本指南将向你展示如何搭建一个基础的 `u-space` 应用。 确保已将 `@types/three` 和 `three` 安装为对等依赖。如果你计划使用交互功能,还需要安装 `camera-controls`。 ```bash",
|
|
1272
|
+
"headings": [
|
|
1273
|
+
{
|
|
1274
|
+
"level": 1,
|
|
1275
|
+
"text": "快速上手 u-space"
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
"level": 2,
|
|
1279
|
+
"text": "安装"
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
"level": 2,
|
|
1283
|
+
"text": "基础配置"
|
|
1284
|
+
},
|
|
1285
|
+
{
|
|
1286
|
+
"level": 3,
|
|
1287
|
+
"text": "1. HTML 结构"
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
"level": 3,
|
|
1291
|
+
"text": "2. Import Maps"
|
|
1292
|
+
},
|
|
1293
|
+
{
|
|
1294
|
+
"level": 3,
|
|
1295
|
+
"text": "3. 初始化 Viewer 并添加对象"
|
|
1296
|
+
},
|
|
1297
|
+
{
|
|
1298
|
+
"level": 3,
|
|
1299
|
+
"text": "4. 启用交互"
|
|
1300
|
+
},
|
|
1301
|
+
{
|
|
1302
|
+
"level": 2,
|
|
1303
|
+
"text": "版本信息"
|
|
1304
|
+
},
|
|
1305
|
+
{
|
|
1306
|
+
"level": 2,
|
|
1307
|
+
"text": "下一步"
|
|
1308
|
+
}
|
|
1309
|
+
],
|
|
1310
|
+
"content": "# 快速上手 `u-space`\n\n`u-space` 是一个基于 Three.js 的 WebGPU 3D 引擎。本指南将向你展示如何搭建一个基础的 `u-space` 应用。\n\n## 安装\n\n确保已将 `@types/three` 和 `three` 安装为对等依赖。如果你计划使用交互功能,还需要安装 `camera-controls`。\n\n```bash\npnpm install three camera-controls\n```\n\n## 基础配置\n\n以下是一个最小示例,展示如何初始化 `u-space` 的 `Viewer` 并向场景中添加一个可交互对象。\n\n### 1. HTML 结构\n\n创建一个容纳 3D 查看器的元素。\n\n```html\n<!DOCTYPE html>\n<html lang=\"zh\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>u-space App</title>\n </head>\n <body style=\"margin: 0\">\n <div id=\"app\" style=\"width: 100vw; height: 100vh\"></div>\n <!-- 脚本放这里 -->\n </body>\n</html>\n```\n\n### 2. Import Maps\n\n由于 `u-space` 依赖 Three.js 的 WebGPU 特性,建议配置 Import Map 以解析 Three.js 的 WebGPU 构建版本。\n\n```html\n<script type=\"importmap\">\n {\n \"imports\": {\n \"three\": \"/node_modules/three/build/three.webgpu.js\",\n \"three/webgpu\": \"/node_modules/three/build/three.webgpu.js\",\n \"three/addons/\": \"/node_modules/three/examples/jsm/\",\n \"camera-controls\": \"/node_modules/camera-controls/dist/camera-controls.module.js\",\n \"u-space\": \"path/to/u-space/dist/index.js\"\n }\n }\n</script>\n```\n\n### 3. 初始化 Viewer 并添加对象\n\n初始化 `Viewer` 并向场景中添加一个基础 Three.js 对象。\n\n```html\n<script type=\"module\">\n import { Color, GridHelper, Mesh, BoxGeometry, MeshBasicMaterial } from 'three/webgpu';\n import { Viewer } from 'u-space';\n\n const app = document.getElementById('app');\n\n // 初始化查看器\n const viewer = new Viewer({\n el: app,\n rendererOptions: { forceWebGL: false }, // 优先使用 WebGPU\n });\n await viewer.init();\n\n // 设置背景颜色\n viewer.scene.background = new Color(0x666666);\n\n // 添加网格辅助线\n const gridHelper = new GridHelper(10, 10);\n viewer.scene.add(gridHelper);\n\n // 添加一个立方体\n const geometry = new BoxGeometry(1, 1, 1);\n const material = new MeshBasicMaterial({ color: 0xff0000 });\n const box = new Mesh(geometry, material);\n box.position.set(0, 0.5, 0);\n viewer.scene.add(box);\n\n // 渲染场景\n viewer.render();\n</script>\n```\n\n### 4. 启用交互\n\n`u-space` 内置了 `InteractionManager`,可以轻松为 3D 对象添加事件监听。\n\n```javascript\n// 启用指针移动事件(pointerenter / pointerleave 需要此开关)\nviewer.interactionManager.pointerMoveEventsEnabled = true;\n\n// 添加点击事件\nbox.addEventListener('click', (e) => {\n console.log('点击位置:', e.event.intersect.point);\n material.color.set(Math.random() * 0xffffff);\n viewer.render(); // 请求新一帧渲染\n});\n\n// 添加悬停事件\nbox.addEventListener('pointerenter', (e) => {\n document.body.style.cursor = 'pointer';\n material.color.set(0x00ff00);\n viewer.render();\n});\n\nbox.addEventListener('pointerleave', (e) => {\n document.body.style.cursor = 'default';\n material.color.set(0xff0000);\n viewer.render();\n});\n```\n\n这样就完成了!你现在拥有一个基础的 `u-space` 应用。\n\n## 版本信息\n\n`u-space` 导出了 `version` 常量,同时在 `window.__USPACE__` 上挂载了版本信息,方便调试和版本检查。\n\n```typescript\nimport { version } from 'u-space';\nconsole.log(version); // e.g. '0.0.5'\n\n// 也可以通过全局变量访问\nconsole.log(window.__USPACE__.version);\n```\n\n## 下一步\n\n- 深入了解 [Viewer API](./api-viewer.md)\n- 探索如何 [加载模型与使用对象](./api-objects.md)\n- 理解 [交互系统](./api-interactions.md)\n- 使用 [Managers API](./api-managers.md) 注册和检索对象\n- 通过插件添加 [瓦片地图](./api-plugin-tiles.md)、[小地图](./api-plugin-minimap.md)、[键盘控制](./api-plugin-keyboard-controls.md) 等功能\n- 使用 [Animations API](./api-animations.md) 为属性添加动画\n- 使用 [Effects API](./api-effects.md) 应用视觉特效\n- 浏览 [示例指南](./examples-guide.md)\n"
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
"id": "index",
|
|
1314
|
+
"path": "index.md",
|
|
1315
|
+
"title": "u-space",
|
|
1316
|
+
"summary": "所有插件从 `u-space/plugins/<name>` 导入。",
|
|
1317
|
+
"headings": [
|
|
1318
|
+
{
|
|
1319
|
+
"level": 2,
|
|
1320
|
+
"text": "文档目录"
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
"level": 3,
|
|
1324
|
+
"text": "核心 API"
|
|
1325
|
+
},
|
|
1326
|
+
{
|
|
1327
|
+
"level": 3,
|
|
1328
|
+
"text": "插件"
|
|
1329
|
+
},
|
|
1330
|
+
{
|
|
1331
|
+
"level": 3,
|
|
1332
|
+
"text": "MCP"
|
|
1333
|
+
}
|
|
1334
|
+
],
|
|
1335
|
+
"content": "---\nlayout: home\n\nhero:\n name: u-space\n text: WebGPU-ready 3D Engine\n tagline: 基于 Three.js 的插件化 3D 可视化库,支持 GIS 瓦片、动画、场景管理与交互系统。\n actions:\n - theme: brand\n text: 快速上手\n link: /getting-started\n - theme: alt\n text: API 文档\n link: /api-viewer\n - theme: alt\n text: 在线示例\n link: /examples/\n target: _self\n\nfeatures:\n - title: WebGPU 优先\n details: 基于 Three.js WebGPU 渲染器,支持 TSL(Three Shading Language)着色器节点,同时保持 WebGL 兼容回退。\n - title: 插件化架构\n details: 核心轻量,通过独立插件按需扩展:GIS 瓦片、小地图、键盘控制、场景管理、曲线动画等。\n - title: 交互系统\n details: 内置射线检测与事件冒泡,像操作 DOM 元素一样为 3D 对象添加 click、pointerenter 等事件。\n---\n\n## 文档目录\n\n### 核心 API\n\n| 文档 | 说明 |\n| :--- | :--- |\n| [Viewer](./api-viewer) | 核心类:渲染器、场景、相机、控制器、事件 |\n| [CameraControls](./api-camera-controls) | 相机控制:飞行、视角切换、视点过渡 |\n| [CSSRenderer](./api-css-renderer) | CSS 渲染器:CSS2D / CSS2.5D / CSS3D 叠加 HTML 元素 |\n| [RenderPipeline](./api-render-pipeline) | 后处理管线:Bloom、SSGI、TRAA、自定义后处理 |\n| [Objects](./api-objects) | 3D 对象:模型加载、基础网格、Poi、Topology |\n| [Interactions](./api-interactions) | 交互管理:射线检测、鼠标/触摸事件、框选 |\n| [Managers](./api-managers) | 对象管理、场景管理、灯光管理 |\n| [Animations](./api-animations) | 补间动画:`tweenAnimation`、`Tween`、缓动模式 |\n| [Effects](./api-effects) | 视觉特效:高亮、呼吸、线框、淡入淡出、流动、流体(TSL) |\n| [Tools](./api-tools) | 工具:测量(距离/面积/角度)、剖切(面/盒)、标注管理 |\n\n### 插件\n\n所有插件从 `u-space/plugins/<name>` 导入。\n\n| 插件 | 说明 |\n| :--- | :--- |\n| [keyboard-controls](./api-plugin-keyboard-controls) | WASD / 方向键控制相机移动与旋转 |\n| [minimap](./api-plugin-minimap) | 2D 小地图叠加层 |\n| [tiles](./api-plugin-tiles) | ArcGIS 3D 瓦片 / GIS 地球渲染 |\n| [u-manager](./api-plugin-u-manager) | 场景加载、拓扑、动画、属性、视点管理 |\n| [curve-movement](./api-plugin-curve-movement) | 沿样条曲线移动相机或对象 |\n| [tracking-controls](./api-plugin-tracking-controls) | 相机跟随移动目标 |\n| [atmosphere](./api-plugin-atmosphere) | 天空/大气渲染(开发中) |\n| [object-controls](./api-plugin-object-controls) | 交互式移动、旋转、缩放 3D 对象 |\n| [topology-drawer](./api-plugin-topology-drawer) | 在场景任意表面交互式绘制拓扑路径图 |\n\n### MCP\n\n| 文档 | 说明 |\n| :--- | :--- |\n| [u-space MCP](./mcp) | 面向 Mastra、Claude Desktop、Cursor 等 MCP 客户端的只读文档检索服务器 |\n"
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
"id": "mcp",
|
|
1339
|
+
"path": "mcp.md",
|
|
1340
|
+
"title": "u-space MCP",
|
|
1341
|
+
"summary": "`u-space-mcp` 是面向 `u-space` 文档的 Model Context Protocol(MCP)服务器。它把当前文档打包成只读 MCP 工具,方便 Mastra、Claude Desktop、Cursor 等 MCP 客户端在回答 `u-space` API、插件和示例问题时直接检索官方文档。 推荐通过 `npx` 使用已发布的 npm 包: ```json",
|
|
1342
|
+
"headings": [
|
|
1343
|
+
{
|
|
1344
|
+
"level": 1,
|
|
1345
|
+
"text": "u-space MCP"
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
"level": 2,
|
|
1349
|
+
"text": "安装与启动"
|
|
1350
|
+
},
|
|
1351
|
+
{
|
|
1352
|
+
"level": 2,
|
|
1353
|
+
"text": "Mastra 接入"
|
|
1354
|
+
},
|
|
1355
|
+
{
|
|
1356
|
+
"level": 2,
|
|
1357
|
+
"text": "工具列表"
|
|
1358
|
+
},
|
|
1359
|
+
{
|
|
1360
|
+
"level": 2,
|
|
1361
|
+
"text": "包结构"
|
|
1362
|
+
}
|
|
1363
|
+
],
|
|
1364
|
+
"content": "# u-space MCP\n\n`u-space-mcp` 是面向 `u-space` 文档的 Model Context Protocol(MCP)服务器。它把当前文档打包成只读 MCP 工具,方便 Mastra、Claude Desktop、Cursor 等 MCP 客户端在回答 `u-space` API、插件和示例问题时直接检索官方文档。\n\n## 安装与启动\n\n推荐通过 `npx` 使用已发布的 npm 包:\n\n```json\n{\n \"mcpServers\": {\n \"uSpace\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"u-space-mcp@latest\"]\n }\n }\n}\n```\n\n本地开发文档时,可以通过 `--docs` 指向仓库里的 docs 目录:\n\n```json\n{\n \"mcpServers\": {\n \"uSpace\": {\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"u-space-mcp@latest\",\n \"--docs\",\n \"/Users/jiangqi/Desktop/xunwei/SoonSpace/u-space/docs\"\n ]\n }\n }\n}\n```\n\n也可以使用环境变量:\n\n```bash\nU_SPACE_DOCS_PATH=/path/to/u-space/docs npx -y u-space-mcp@latest\n```\n\n## Mastra 接入\n\n在 Mastra 中通过 `MCPClient` 使用 stdio 形式接入:\n\n```typescript\nimport { MCPClient } from '@mastra/mcp';\n\nexport const uSpaceMcpClient = new MCPClient({\n id: 'u-space-mcp-client',\n servers: {\n uSpace: {\n command: 'npx',\n args: ['-y', 'u-space-mcp@latest'],\n stderr: 'pipe',\n },\n },\n});\n```\n\n然后把工具挂到 Agent 上:\n\n```typescript\nexport const codingAgent = new Agent({\n // ...\n tools: {\n ...(await uSpaceMcpClient.listTools()),\n },\n});\n```\n\n## 工具列表\n\n`u-space-mcp` 只提供只读工具:\n\n| 工具 | 说明 |\n| :--- | :--- |\n| `list_docs` | 列出可用文档页 |\n| `search_docs` | 按关键词、API 名、插件名或概念检索文档 |\n| `get_doc` | 按 path 或 id 读取单篇文档 |\n| `get_api_reference` | 面向 API / 类 / 方法 / 插件的检索 |\n| `find_examples` | 查找示例和用法相关文档 |\n| `get_changelog` | 读取更新日志 |\n\n## 包结构\n\n源码位于 `packages/u-space-mcp`。构建时会从根目录 `docs/*.md` 生成内置文档索引,并编译成可发布的 npm 包:\n\n```bash\npnpm build:mcp\npnpm publish:mcp\n```\n\n发布后的包不依赖本机绝对路径;只有在传入 `--docs` 或设置 `U_SPACE_DOCS_PATH` 时,才会读取本地文档目录。\n"
|
|
1365
|
+
}
|
|
1366
|
+
];
|
|
1367
|
+
//# sourceMappingURL=docs-index.js.map
|