u-space 0.0.3 → 0.0.7

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.
Files changed (74) hide show
  1. package/dist/index.cjs +1 -2074
  2. package/dist/index.js +1077 -1509
  3. package/dist/plugins/u-manager/flows/ComponentFlowParser.d.ts +8 -0
  4. package/dist/plugins/u-manager/flows/FlowParser.d.ts +48 -0
  5. package/dist/plugins/u-manager/flows/edges/index.d.ts +9 -0
  6. package/dist/plugins/u-manager/flows/index.d.ts +4 -0
  7. package/dist/plugins/u-manager/flows/nodes/ColorNode.d.ts +8 -0
  8. package/dist/plugins/u-manager/flows/nodes/ConditionNode.d.ts +9 -0
  9. package/dist/plugins/u-manager/flows/nodes/DataExtractionNode.d.ts +8 -0
  10. package/dist/plugins/u-manager/flows/nodes/DataFilterNode.d.ts +8 -0
  11. package/dist/plugins/u-manager/flows/nodes/DelayNode.d.ts +8 -0
  12. package/dist/plugins/u-manager/flows/nodes/EmissiveNode.d.ts +8 -0
  13. package/dist/plugins/u-manager/flows/nodes/FlyToNode.d.ts +8 -0
  14. package/dist/plugins/u-manager/flows/nodes/HideNode.d.ts +10 -0
  15. package/dist/plugins/u-manager/flows/nodes/HighlightNode.d.ts +8 -0
  16. package/dist/plugins/u-manager/flows/nodes/MeshNode.d.ts +8 -0
  17. package/dist/plugins/u-manager/flows/nodes/MeshesNode.d.ts +8 -0
  18. package/dist/plugins/u-manager/flows/nodes/ModelNode.d.ts +8 -0
  19. package/dist/plugins/u-manager/flows/nodes/ModelsNode.d.ts +8 -0
  20. package/dist/plugins/u-manager/flows/nodes/Node.d.ts +52 -0
  21. package/dist/plugins/u-manager/flows/nodes/NumberNode.d.ts +8 -0
  22. package/dist/plugins/u-manager/flows/nodes/OpacityNode.d.ts +8 -0
  23. package/dist/plugins/u-manager/flows/nodes/POINode.d.ts +8 -0
  24. package/dist/plugins/u-manager/flows/nodes/POISNode.d.ts +8 -0
  25. package/dist/plugins/u-manager/flows/nodes/PathNode.d.ts +8 -0
  26. package/dist/plugins/u-manager/flows/nodes/PathsNode.d.ts +8 -0
  27. package/dist/plugins/u-manager/flows/nodes/RotateNode.d.ts +8 -0
  28. package/dist/plugins/u-manager/flows/nodes/ScaleNode.d.ts +8 -0
  29. package/dist/plugins/u-manager/flows/nodes/ShowNode.d.ts +10 -0
  30. package/dist/plugins/u-manager/flows/nodes/SpaceNode.d.ts +8 -0
  31. package/dist/plugins/u-manager/flows/nodes/SpacesNode.d.ts +8 -0
  32. package/dist/plugins/u-manager/flows/nodes/StartNode.d.ts +7 -0
  33. package/dist/plugins/u-manager/flows/nodes/TranslateNode.d.ts +8 -0
  34. package/dist/plugins/u-manager/flows/nodes/UnEmissiveNode.d.ts +10 -0
  35. package/dist/plugins/u-manager/flows/nodes/UnHighlightNode.d.ts +10 -0
  36. package/dist/plugins/u-manager/flows/nodes/UnOpacityNode.d.ts +8 -0
  37. package/dist/plugins/u-manager/flows/nodes/UserDataNode.d.ts +8 -0
  38. package/dist/plugins/u-manager/flows/nodes/clip-animation/ClipAnimationNode.d.ts +8 -0
  39. package/dist/plugins/u-manager/flows/nodes/clip-animation/UnClipAnimationNode.d.ts +8 -0
  40. package/dist/plugins/u-manager/flows/nodes/clip-animation/index.d.ts +2 -0
  41. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/ComponentTweenAnimationNode.d.ts +8 -0
  42. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/UnComponentTweenAnimationNode.d.ts +8 -0
  43. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/index.d.ts +2 -0
  44. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/utils.d.ts +5 -0
  45. package/dist/plugins/u-manager/flows/nodes/index.d.ts +34 -0
  46. package/dist/plugins/u-manager/flows/nodes/tween-animation/TweenAnimationNode.d.ts +8 -0
  47. package/dist/plugins/u-manager/flows/nodes/tween-animation/UnTweenAnimationNode.d.ts +8 -0
  48. package/dist/plugins/u-manager/flows/nodes/tween-animation/index.d.ts +2 -0
  49. package/dist/plugins/u-manager/flows/nodes/tween-animation/utils.d.ts +5 -0
  50. package/dist/plugins/u-manager/flows/types.d.ts +81 -0
  51. package/dist/plugins/u-manager/flows/utils.d.ts +14 -0
  52. package/dist/plugins/u-manager/index.cjs +59 -59
  53. package/dist/plugins/u-manager/index.d.ts +1 -0
  54. package/dist/plugins/u-manager/index.js +9718 -8616
  55. package/dist/src/effects/MaterialEffects.d.ts +10 -3
  56. package/dist/src/index.d.ts +8 -0
  57. package/dist/src/objects/Model.d.ts +14 -1
  58. package/dist/src/objects/Poi.d.ts +4 -0
  59. package/dist/src/viewers/CSSRenderer.d.ts +19 -0
  60. package/dist/src/viewers/CameraControls.d.ts +7 -0
  61. package/dist/src/viewers/RenderPipeline.d.ts +30 -2
  62. package/dist/src/viewers/Viewer.d.ts +6 -0
  63. package/dist/src/viewers/index.d.ts +2 -0
  64. package/docs/api-css-renderer.md +43 -0
  65. package/docs/api-effects.md +49 -11
  66. package/docs/api-objects.md +58 -0
  67. package/docs/api-render-pipeline.md +114 -0
  68. package/docs/api-viewer.md +37 -4
  69. package/docs/examples-guide.md +40 -0
  70. package/docs/getting-started.md +12 -0
  71. package/docs/index.md +6 -0
  72. package/package.json +1 -1
  73. package/dist/index.cjs.map +0 -1
  74. package/dist/index.js.map +0 -1
@@ -1,10 +1,17 @@
1
1
  import { type Object3D, type ColorRepresentation } from 'three/webgpu';
2
- export interface HighlightOptions {
3
- enabled?: boolean;
2
+ export interface HighlightColorOptions {
4
3
  opacity?: number;
5
4
  color?: ColorRepresentation;
6
5
  overwrite?: boolean;
7
6
  }
7
+ export interface BreatheColorOptions {
8
+ color?: ColorRepresentation;
9
+ speed?: number;
10
+ intensity?: number;
11
+ }
8
12
  export declare class MaterialEffects {
9
- static highlight(object: Object3D, options?: HighlightOptions): void;
13
+ static highlightColor(object: Object3D | Object3D[], options?: HighlightColorOptions): void;
14
+ static removeHighlightColor(object: Object3D | Object3D[]): void;
15
+ static breatheColor(object: Object3D | Object3D[], options?: BreatheColorOptions): void;
16
+ static removeBreatheColor(object: Object3D | Object3D[]): void;
10
17
  }
@@ -7,3 +7,11 @@ export * from './effects';
7
7
  export * from './animations';
8
8
  export * from './interfaces';
9
9
  export * from './types';
10
+ export declare const version: string;
11
+ declare global {
12
+ interface Window {
13
+ __USPACE__: {
14
+ version: string;
15
+ };
16
+ }
17
+ }
@@ -1,4 +1,4 @@
1
- import { type Object3D } from 'three/webgpu';
1
+ import { type Object3D, AnimationMixer, type AnimationAction, type AnimationClip } from 'three/webgpu';
2
2
  import { type InteractionEventMap } from '../interactions';
3
3
  import { BaseGroup } from './BaseGroup';
4
4
  export interface ModelParameters {
@@ -6,12 +6,25 @@ export interface ModelParameters {
6
6
  cache?: boolean;
7
7
  persistent?: boolean;
8
8
  }
9
+ export interface PlayAnimationOptions {
10
+ loop?: boolean;
11
+ repetitions?: number;
12
+ timeScale?: number;
13
+ clampWhenFinished?: boolean;
14
+ }
9
15
  export declare class Model extends BaseGroup<InteractionEventMap> {
10
16
  readonly isModel = true;
11
17
  type: string;
12
18
  private static memoryCache;
19
+ mixer: AnimationMixer | null;
20
+ animations: AnimationClip[];
21
+ private actions;
13
22
  constructor();
14
23
  loadAsync(parameters: ModelParameters): Promise<Object3D<import("three").Object3DEventMap> | null>;
24
+ playAnimation(nameOrIndex?: string | number, options?: PlayAnimationOptions): AnimationAction | null;
25
+ playAllAnimations(options?: PlayAnimationOptions): AnimationAction[];
26
+ stopAnimation(nameOrIndex?: string | number): void;
27
+ updateAnimation(delta: number): void;
15
28
  static clearMemoryCache(): void;
16
29
  static clearPersistentCache(): Promise<void>;
17
30
  }
@@ -21,11 +21,15 @@ export interface PoiParameters {
21
21
  borderRadius?: number;
22
22
  /** Text position relative to the icon */
23
23
  textPosition?: 'top' | 'bottom' | 'left' | 'right';
24
+ /** Scale factor for mapping canvas pixels to world units */
25
+ scaleFactor?: number;
24
26
  }
25
27
  export declare class Poi extends BaseSprite<InteractionEventMap> {
26
28
  readonly isPoi = true;
27
29
  type: string;
28
30
  parameters: Required<PoiParameters>;
31
+ private _canvas;
32
+ private _lastParametersJSON;
29
33
  constructor(parameters?: PoiParameters);
30
34
  /**
31
35
  * Update the POI with new parameters
@@ -0,0 +1,19 @@
1
+ import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
2
+ import { CSS3DRenderer, CSS3DObject, CSS3DSprite } from 'three/addons/renderers/CSS3DRenderer.js';
3
+ import type { Scene, Camera } from 'three/webgpu';
4
+ export { CSS2DObject, CSS3DObject, CSS3DSprite };
5
+ declare class CSSRenderer {
6
+ el: HTMLElement;
7
+ css2dRenderer: CSS2DRenderer | null;
8
+ css3dRenderer: CSS3DRenderer | null;
9
+ constructor(el: HTMLElement);
10
+ private initCSS2DRenderer;
11
+ private initCSS3DRenderer;
12
+ createCSS2DObject(element: HTMLElement): CSS2DObject;
13
+ createCSS25DObject(element: HTMLElement): CSS3DSprite;
14
+ createCSS3DObject(element: HTMLElement): CSS3DObject;
15
+ render(scene: Scene, camera: Camera): void;
16
+ resize(width: number, height: number): void;
17
+ dispose(): void;
18
+ }
19
+ export { CSSRenderer };
@@ -1,5 +1,6 @@
1
1
  import CameraControlsBase from 'camera-controls';
2
2
  import { Box3, type Object3D } from 'three/webgpu';
3
+ import type { IVector3 } from '../interfaces';
3
4
  export interface FlyToBoxOptions {
4
5
  viewpoint?: 'current' | 'top' | 'bottom' | 'front' | 'back' | 'left' | 'right' | 'frontTop' | 'backTop' | 'leftTop' | 'rightTop' | 'leftFrontTop' | 'rightFrontTop' | 'leftBackTop' | 'rightBackTop';
5
6
  enableTransition?: boolean;
@@ -8,6 +9,11 @@ export interface FlyToBoxOptions {
8
9
  }
9
10
  export interface FlyToObjectOptions extends FlyToBoxOptions {
10
11
  }
12
+ export interface CameraViewpointData {
13
+ position: IVector3;
14
+ target: IVector3;
15
+ zoom: number;
16
+ }
11
17
  export declare class CameraControls extends CameraControlsBase {
12
18
  constructor(...args: ConstructorParameters<typeof CameraControlsBase>);
13
19
  /**
@@ -16,4 +22,5 @@ export declare class CameraControls extends CameraControlsBase {
16
22
  absoluteRotations(): void;
17
23
  flyToBox(box: Box3, options?: FlyToBoxOptions): Promise<boolean>;
18
24
  flyToObject(object: Object3D, options?: FlyToObjectOptions): Promise<boolean>;
25
+ setCameraViewpoint(viewpoint: CameraViewpointData, enableTransition?: boolean): Promise<[void, void]>;
19
26
  }
@@ -1,17 +1,45 @@
1
- import { type Scene, type Camera, RenderPipeline as RenderPipelineBase, type Node } from 'three/webgpu';
1
+ import { type Scene, type Camera, type PassNode, RenderPipeline as RenderPipelineBase, type Node } from 'three/webgpu';
2
+ export interface BloomConfig {
3
+ strength?: number;
4
+ radius?: number;
5
+ threshold?: number;
6
+ }
7
+ export interface SSGIConfig {
8
+ sliceCount?: number;
9
+ stepCount?: number;
10
+ aoIntensity?: number;
11
+ giIntensity?: number;
12
+ radius?: number;
13
+ thickness?: number;
14
+ }
15
+ export type OutputNodeComposer = (scenePass: PassNode) => Node;
2
16
  type Args = [ConstructorParameters<typeof RenderPipelineBase>[0], Scene, Camera];
3
17
  export declare class RenderPipeline extends RenderPipelineBase {
4
18
  #private;
5
19
  scene: Scene;
6
20
  camera: Camera;
7
- currentOutputNode: Node;
21
+ scenePass: PassNode;
8
22
  needsUpdateOutputNode: boolean;
9
23
  constructor(...args: Args);
24
+ /** @deprecated Use `scenePass` instead */
25
+ get currentOutputNode(): PassNode;
10
26
  addOverlayPass(pass: Node): void;
11
27
  removeOverlayPass(pass: Node): void;
12
28
  setCamera(camera: Camera): void;
29
+ /** @deprecated Use `setOutputComposer` instead */
13
30
  setCurrentOutputNode(node: Node): void;
31
+ /** @deprecated Use `setOutputComposer(null)` instead */
14
32
  resetCurrentOutputNode(): void;
33
+ setOutputComposer(composer: OutputNodeComposer | null): void;
34
+ enableBloom(config?: BloomConfig): void;
35
+ disableBloom(): void;
36
+ updateBloom(config: Partial<BloomConfig>): void;
37
+ enableSSGI(config?: SSGIConfig): void;
38
+ disableSSGI(): void;
39
+ updateSSGI(config: Partial<SSGIConfig>): void;
40
+ enableTRAA(): void;
41
+ disableTRAA(): void;
15
42
  render(): void;
43
+ dispose(): void;
16
44
  }
17
45
  export {};
@@ -5,6 +5,7 @@ import { RenderPipeline } from './RenderPipeline';
5
5
  import { CameraControls } from './CameraControls';
6
6
  import { RoomEnvironment } from './RoomEnvironment';
7
7
  import { ViewerHelper } from './ViewerHelper';
8
+ import { CSSRenderer } from './CSSRenderer';
8
9
  import { Info } from './Info';
9
10
  type ViewerRendererOptions = ConstructorParameters<typeof WebGPURenderer>['0'];
10
11
  export interface ViewerOptions {
@@ -14,15 +15,19 @@ export interface ViewerOptions {
14
15
  export interface ViewerEventMap {
15
16
  beforeControlsUpdate: {
16
17
  time: number;
18
+ delta: number;
17
19
  };
18
20
  afterControlsUpdate: {
19
21
  time: number;
22
+ delta: number;
20
23
  };
21
24
  beforeRender: {
22
25
  time: number;
26
+ delta: number;
23
27
  };
24
28
  afterRender: {
25
29
  time: number;
30
+ delta: number;
26
31
  };
27
32
  cameraChange: {
28
33
  camera: PerspectiveCamera | OrthographicCamera;
@@ -41,6 +46,7 @@ declare class Viewer extends EventDispatcher<ViewerEventMap> {
41
46
  interactionManager: InteractionManager;
42
47
  objectManager: ObjectManager;
43
48
  viewerHelper: ViewerHelper;
49
+ cssRenderer: CSSRenderer;
44
50
  frameCount: number;
45
51
  frameloop: 'always' | 'demand';
46
52
  constructor({ el, rendererOptions }: ViewerOptions);
@@ -1,3 +1,5 @@
1
1
  export * from './Viewer';
2
+ export * from './RenderPipeline';
3
+ export * from './CSSRenderer';
2
4
  export * from './RoomEnvironment';
3
5
  export * from './CameraControls';
@@ -0,0 +1,43 @@
1
+ # CSSRenderer API
2
+
3
+ `viewer.cssRenderer` 用于在 3D 场景中叠加渲染 HTML 元素。支持三种模式:
4
+
5
+ | 模式 | 方法 | 返回类型 | 说明 |
6
+ | :--- | :--- | :------- | :--- |
7
+ | CSS2D | `createCSS2DObject(element)` | `CSS2DObject` | HTML 元素始终面向相机,屏幕尺寸固定不随距离缩放。适合标签、工具提示。 |
8
+ | CSS2.5D | `createCSS25DObject(element)` | `CSS3DSprite` | HTML 元素面向相机,但尺寸随距离缩放(近大远小)。 |
9
+ | CSS3D | `createCSS3DObject(element)` | `CSS3DObject` | HTML 元素具有完整的 3D 变换,可旋转、缩放,参与透视投影。适合面板、信息板。 |
10
+
11
+ 底层渲染器采用**懒加载**:首次调用对应 `create` 方法时才初始化 `CSS2DRenderer` 或 `CSS3DRenderer`,不使用则无开销。
12
+
13
+ 创建的对象是标准 Three.js `Object3D`,直接添加到场景中即可:
14
+
15
+ ```typescript
16
+ // CSS2D 标签
17
+ const labelEl = document.createElement('div');
18
+ labelEl.textContent = '标签';
19
+ labelEl.style.cssText = 'background:rgba(0,0,0,0.7);color:#fff;padding:4px 8px;border-radius:4px;font-size:13px;';
20
+ const label = viewer.cssRenderer.createCSS2DObject(labelEl);
21
+ label.position.set(0, 2, 0);
22
+ viewer.scene.add(label);
23
+
24
+ // CSS2.5D 精灵(需设置 scale,通常 0.01 左右)
25
+ const spriteEl = document.createElement('div');
26
+ spriteEl.textContent = '精灵';
27
+ const sprite = viewer.cssRenderer.createCSS25DObject(spriteEl);
28
+ sprite.position.set(3, 2, 0);
29
+ sprite.scale.setScalar(0.01);
30
+ viewer.scene.add(sprite);
31
+
32
+ // CSS3D 面板(需设置 scale,通常 0.01 左右)
33
+ const panelEl = document.createElement('div');
34
+ panelEl.innerHTML = '<h3>面板</h3><p>3D 空间中的 HTML</p>';
35
+ const panel = viewer.cssRenderer.createCSS3DObject(panelEl);
36
+ panel.position.set(0, 1.5, -3);
37
+ panel.scale.setScalar(0.01);
38
+ viewer.scene.add(panel);
39
+ ```
40
+
41
+ > `CSSRenderer` 的生命周期(渲染、缩放、销毁)已自动集成到 `Viewer` 中,无需手动调用。
42
+
43
+ 同时从 `u-space` 包中导出了 `CSS2DObject`、`CSS3DObject`、`CSS3DSprite` 类型,供直接使用。
@@ -1,40 +1,78 @@
1
1
  # Effects API
2
2
 
3
- `u-space` 提供了两个基于 Three.js 着色语言(TSL/WebGPU 节点)的静态特效工具:`MaterialEffects` 用于为对象应用高亮状态,`TSLEffects` 用于生成动态颜色节点模式。
3
+ `u-space` 提供了两个基于 Three.js 着色语言(TSL/WebGPU 节点)的静态特效工具:`MaterialEffects` 用于为对象应用高亮、呼吸等材质特效,`TSLEffects` 用于生成动态颜色节点模式。
4
4
 
5
5
  ## `MaterialEffects`
6
6
 
7
- 静态工具类,将基于 TSL 的视觉特效直接应用于对象的材质。适用于任何 `Object3D`,会自动遍历所有子网格。
7
+ 静态工具类,将基于 TSL 的视觉特效直接应用于对象的材质。适用于任何 `Object3D`(支持单个或数组),会自动遍历所有子网格。
8
8
 
9
- ### `MaterialEffects.highlight(object, options?)`
9
+ 特性:
10
+ - **效果可叠加**:高亮和呼吸效果可同时作用于同一对象,呼吸在高亮结果之上混合
11
+ - **共享材质安全**:按材质跟踪引用计数,多个 Mesh 共享材质时互不干扰
12
+ - **完整还原**:移除效果时自动恢复材质原始的 `colorNode`、`opacityNode` 和 `transparent` 状态
10
13
 
11
- 为对象中所有网格应用颜色/透明度高亮。使用 `userData` 和 TSL 节点图,多个对象可共享同一节点图实例,各自保持独立状态。
14
+ ### `MaterialEffects.highlightColor(object, options?)`
15
+
16
+ 为对象中所有网格应用颜色/透明度高亮。
12
17
 
13
18
  ```typescript
14
19
  import { MaterialEffects } from 'u-space';
15
20
 
16
21
  // 以 50% 透明度高亮为红色
17
- MaterialEffects.highlight(myModel, {
18
- enabled: true,
22
+ MaterialEffects.highlightColor(myModel, {
19
23
  color: 0xff0000,
20
24
  opacity: 0.5,
21
25
  overwrite: false, // false = 叠加(相乘),true = 完全替换颜色
22
26
  });
23
27
 
24
- // 禁用高亮
25
- MaterialEffects.highlight(myModel, { enabled: false });
28
+ // 支持数组
29
+ MaterialEffects.highlightColor([model1, model2], { color: 0x00ff00 });
26
30
  ```
27
31
 
28
- ### `HighlightOptions`
32
+ #### `HighlightColorOptions`
29
33
 
30
34
  | 属性 | 类型 | 默认值 | 说明 |
31
35
  | :---------- | :-------------------- | :---------- | :--------------------------------------------------------------------------- |
32
- | `enabled` | `boolean` | `true` | 启用或禁用高亮特效。 |
33
36
  | `color` | `ColorRepresentation` | `0xff0000` | 高亮颜色。 |
34
37
  | `opacity` | `number` | `0.5` | 高亮时材质的透明度。 |
35
38
  | `overwrite` | `boolean` | `false` | `false` = 与原始颜色相乘(叠加);`true` = 完全替换颜色。 |
36
39
 
37
- > **注意:** `highlight` 会在所有受影响的网格上设置 `material.transparent = true`,并注入 `colorNode`/`opacityNode`。目前不可逆,若需恢复须手动重置这些节点。
40
+ ### `MaterialEffects.removeHighlightColor(object)`
41
+
42
+ 移除高亮效果。当对象上所有效果都被移除后,材质将完整恢复到原始状态。
43
+
44
+ ```typescript
45
+ MaterialEffects.removeHighlightColor(myModel);
46
+ ```
47
+
48
+ ### `MaterialEffects.breatheColor(object, options?)`
49
+
50
+ 为对象应用呼吸灯效果,颜色在材质原色与目标颜色之间随时间脉冲变化。需要 `viewer.frameloop = 'always'`。
51
+
52
+ ```typescript
53
+ MaterialEffects.breatheColor(myModel, {
54
+ color: 0x00ff00,
55
+ speed: 1.0,
56
+ intensity: 2.0,
57
+ });
58
+ viewer.frameloop = 'always';
59
+ ```
60
+
61
+ #### `BreatheColorOptions`
62
+
63
+ | 属性 | 类型 | 默认值 | 说明 |
64
+ | :---------- | :-------------------- | :---------- | :--------------------------------- |
65
+ | `color` | `ColorRepresentation` | `0x00ff00` | 呼吸目标颜色。 |
66
+ | `speed` | `number` | `1.0` | 振荡速度。 |
67
+ | `intensity` | `number` | `2.0` | 控制峰值的锐度。 |
68
+
69
+ ### `MaterialEffects.removeBreatheColor(object)`
70
+
71
+ 移除呼吸效果。
72
+
73
+ ```typescript
74
+ MaterialEffects.removeBreatheColor(myModel);
75
+ ```
38
76
 
39
77
  ---
40
78
 
@@ -66,6 +66,64 @@ const model3 = new Model();
66
66
  model3.loadAsync({ url: 'model.glb', cache: true, persistent: true });
67
67
  ```
68
68
 
69
+ ### 动画
70
+
71
+ `Model` 在加载含内置动画的模型(如 glTF/FBX)后,会自动初始化 `AnimationMixer` 并收集 `AnimationClip`。
72
+
73
+ **属性:**
74
+
75
+ | 属性 | 类型 | 说明 |
76
+ | :----------- | :-------------------------- | :----------------------------------------- |
77
+ | `mixer` | `AnimationMixer \| null` | 动画混合器,加载含动画模型后自动创建。 |
78
+ | `animations` | `AnimationClip[]` | 模型内置的动画片段列表。 |
79
+
80
+ #### `playAnimation(nameOrIndex?, options?)`
81
+
82
+ 播放指定动画。不传参时播放第一个动画。
83
+
84
+ ```typescript
85
+ // 按名称播放
86
+ model.playAnimation('Walk');
87
+
88
+ // 按索引播放
89
+ model.playAnimation(0);
90
+
91
+ // 带选项
92
+ model.playAnimation('Run', {
93
+ loop: true, // 是否循环(默认 true)
94
+ repetitions: 3, // 循环次数(默认 Infinity)
95
+ timeScale: 1.5, // 播放速度(默认 1)
96
+ clampWhenFinished: true, // 播放结束后停留在最后一帧(默认 false)
97
+ });
98
+ ```
99
+
100
+ #### `playAllAnimations(options?)`
101
+
102
+ 播放模型所有内置动画。参数同 `playAnimation`。
103
+
104
+ ```typescript
105
+ model.playAllAnimations({ timeScale: 2 });
106
+ ```
107
+
108
+ #### `stopAnimation(nameOrIndex?)`
109
+
110
+ 停止指定动画。不传参时停止所有动画。
111
+
112
+ ```typescript
113
+ model.stopAnimation('Walk'); // 停止指定动画
114
+ model.stopAnimation(); // 停止所有动画
115
+ ```
116
+
117
+ #### `updateAnimation(delta)`
118
+
119
+ 推进动画时间,需在渲染循环中调用。`delta` 为帧间隔时间(秒),可从 Viewer 事件的 `delta` 属性获取。
120
+
121
+ ```typescript
122
+ viewer.addEventListener('beforeRender', (e) => {
123
+ model.updateAnimation(e.delta);
124
+ });
125
+ ```
126
+
69
127
  ### 清除缓存
70
128
 
71
129
  可通过 `Model` 类的静态方法手动清除内部缓存:
@@ -0,0 +1,114 @@
1
+ # RenderPipeline API(后处理管线)
2
+
3
+ `viewer.renderPipeline` 管理渲染后处理链,内置 Bloom、SSGI、TRAA 支持,并提供自定义后处理覆盖机制。
4
+
5
+ ## 渲染节点图
6
+
7
+ ```
8
+ Stage 1: pass(scene, camera) + MRT(按需配置 output/emissive/normal/velocity)
9
+
10
+ Stage 2: 后处理链(二选一)
11
+ ├─ 内置模式: SSGI → Bloom(按启用状态组合)
12
+ └─ 自定义模式: outputComposer(scenePass) → Node
13
+
14
+ Stage 3: TRAA 时间抗锯齿
15
+
16
+ Stage 4: Overlay Passes(blendColor 叠加 ViewerHelper 等)
17
+
18
+ outputNode = 最终结果
19
+ ```
20
+
21
+ ## 属性
22
+
23
+ | 属性 | 类型 | 说明 |
24
+ | :--- | :--- | :--- |
25
+ | `scenePass` | `PassNode` | 场景渲染通道节点,`pass(scene, camera)` 的返回值。 |
26
+ | `needsUpdateOutputNode` | `boolean` | 标记输出节点需要在下一帧重建。 |
27
+
28
+ ## Bloom
29
+
30
+ 基于 emissive MRT 通道的泛光效果。
31
+
32
+ ```typescript
33
+ // 开启 Bloom
34
+ viewer.renderPipeline.enableBloom({ strength: 1.5, radius: 0.4, threshold: 0.2 });
35
+
36
+ // 运行时更新参数
37
+ viewer.renderPipeline.updateBloom({ strength: 2.0 });
38
+
39
+ // 关闭 Bloom
40
+ viewer.renderPipeline.disableBloom();
41
+ ```
42
+
43
+ ### `BloomConfig`
44
+
45
+ | 属性 | 类型 | 默认值 | 说明 |
46
+ | :--- | :--- | :----- | :--- |
47
+ | `strength` | `number` | `1` | 泛光强度 |
48
+ | `radius` | `number` | `0` | 泛光扩散半径 |
49
+ | `threshold` | `number` | `0` | 亮度阈值,低于此值不产生泛光 |
50
+
51
+ ## SSGI(屏幕空间全局光照)
52
+
53
+ > 仅支持 `PerspectiveCamera`,使用 `OrthographicCamera` 时会自动跳过并输出警告。
54
+
55
+ ```typescript
56
+ // 开启 SSGI
57
+ viewer.renderPipeline.enableSSGI({ aoIntensity: 1, giIntensity: 10 });
58
+
59
+ // 运行时更新参数(直接修改 uniform,不重建节点图)
60
+ viewer.renderPipeline.updateSSGI({ giIntensity: 20, radius: 8 });
61
+
62
+ // 关闭 SSGI
63
+ viewer.renderPipeline.disableSSGI();
64
+ ```
65
+
66
+ ### `SSGIConfig`
67
+
68
+ | 属性 | 类型 | 默认值 | 范围 | 说明 |
69
+ | :--- | :--- | :----- | :--- | :--- |
70
+ | `sliceCount` | `number` | `1` | 1–4 | 半球切片数 |
71
+ | `stepCount` | `number` | `12` | 1–32 | 每切片采样步数 |
72
+ | `aoIntensity` | `number` | `1` | 0–4 | 环境光遮蔽强度 |
73
+ | `giIntensity` | `number` | `10` | 0–100 | 间接漫反射强度 |
74
+ | `radius` | `number` | `12` | 1–25 | 世界空间采样半径 |
75
+ | `thickness` | `number` | `1` | 0.01–10 | 物体厚度(世界单位) |
76
+
77
+ ## TRAA(时间抗锯齿)
78
+
79
+ 基于运动向量的时间分辨率抗锯齿。
80
+
81
+ ```typescript
82
+ // 开启 TRAA
83
+ viewer.renderPipeline.enableTRAA();
84
+
85
+ // 关闭 TRAA
86
+ viewer.renderPipeline.disableTRAA();
87
+ ```
88
+
89
+ ## 自定义后处理(OutputComposer)
90
+
91
+ 使用 `setOutputComposer` 可完全覆盖内置后处理链,接收 `scenePass` 返回自定义的 TSL 节点。
92
+
93
+ ```typescript
94
+ import { luminance, vec4 } from 'three/tsl';
95
+
96
+ // 灰度滤镜
97
+ viewer.renderPipeline.setOutputComposer((scenePass) => {
98
+ const color = scenePass.getTextureNode();
99
+ const gray = luminance(color.rgb);
100
+ return vec4(gray, gray, gray, 1.0);
101
+ });
102
+
103
+ // 恢复默认(清除自定义后处理)
104
+ viewer.renderPipeline.setOutputComposer(null);
105
+ ```
106
+
107
+ ## Overlay Passes
108
+
109
+ 用于叠加辅助渲染层(如 ViewerHelper),始终在后处理链之后执行。
110
+
111
+ ```typescript
112
+ viewer.renderPipeline.addOverlayPass(overlayNode);
113
+ viewer.renderPipeline.removeOverlayPass(overlayNode);
114
+ ```
@@ -34,6 +34,7 @@ new Viewer(options: ViewerOptions)
34
34
  | `interactionManager` | `InteractionManager` | 管理对象的指针事件和射线检测。 |
35
35
  | `objectManager` | `ObjectManager` | 用于按 ID 或名称注册和检索对象的工具。 |
36
36
  | `frameloop` | `'always'` \| `'demand'` | 设置渲染模式。默认为 `'demand'`(仅在需要时渲染)。设置为 `'always'` 可开启持续渲染。 |
37
+ | `cssRenderer` | `CSSRenderer` | CSS 渲染器,支持在 3D 场景中叠加 HTML 元素(CSS2D / CSS2.5D / CSS3D)。 |
37
38
  | `frameCount` | `number` | 待渲染帧的内部计数器,调用 `render()` 时递增。 |
38
39
 
39
40
  ## 方法
@@ -100,6 +101,36 @@ const camera = viewer.createOrthographicCamera();
100
101
  viewer.setCamera(camera);
101
102
  ```
102
103
 
104
+ ### `controls.setCameraViewpoint(viewpoint, enableTransition?)`
105
+
106
+ 将相机平滑过渡到指定的位置、目标和缩放。
107
+
108
+ ```typescript
109
+ await viewer.controls.setCameraViewpoint({
110
+ position: { x: 10, y: 5, z: 10 },
111
+ target: { x: 0, y: 0, z: 0 },
112
+ zoom: 1.0,
113
+ });
114
+
115
+ // 禁用过渡动画,立即跳转
116
+ await viewer.controls.setCameraViewpoint(viewpoint, false);
117
+ ```
118
+
119
+ **参数:**
120
+
121
+ | 参数 | 类型 | 默认值 | 说明 |
122
+ | :----------------- | :--------------------- | :------ | :---------------------------------- |
123
+ | `viewpoint` | `CameraViewpointData` | — | 包含 `position`、`target`、`zoom`。 |
124
+ | `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |
125
+
126
+ #### `CameraViewpointData`
127
+
128
+ | 属性 | 类型 | 说明 |
129
+ | :--------- | :--------- | :------------------- |
130
+ | `position` | `IVector3` | 相机位置。 |
131
+ | `target` | `IVector3` | 相机注视目标位置。 |
132
+ | `zoom` | `number` | 相机缩放值。 |
133
+
103
134
  ## 调试工具
104
135
 
105
136
  ### Info
@@ -158,8 +189,10 @@ viewer.dispose();
158
189
 
159
190
  Viewer 继承自 `EventDispatcher`,会触发以下事件:
160
191
 
161
- - `beforeControlsUpdate`:在 `CameraControls` 更新之前触发,提供 `{ time: number }`。
162
- - `afterControlsUpdate`:在 `CameraControls` 更新之后触发,提供 `{ time: number }`。
163
- - `beforeRender`:在 `renderer.render` 调用之前立即触发,提供 `{ time: number }`。
164
- - `afterRender`:在 `renderer.render` 完成之后立即触发,提供 `{ time: number }`。
192
+ - `beforeControlsUpdate`:在 `CameraControls` 更新之前触发,提供 `{ time: number; delta: number }`。
193
+ - `afterControlsUpdate`:在 `CameraControls` 更新之后触发,提供 `{ time: number; delta: number }`。
194
+ - `beforeRender`:在 `renderer.render` 调用之前立即触发,提供 `{ time: number; delta: number }`。
195
+ - `afterRender`:在 `renderer.render` 完成之后立即触发,提供 `{ time: number; delta: number }`。
165
196
  - `cameraChange`:调用 `setCamera` 时触发,提供 `{ camera: Camera }`。
197
+
198
+ 其中 `delta` 为上一帧到当前帧的时间间隔(秒),可用于动画更新等场景。
@@ -46,3 +46,43 @@
46
46
  - 流式传输结构化场景布局,解析场景描述(`SceneLoader`、`TopologiesLoader`)。
47
47
  - 使用相机动画(`VisionsLoader` 和 `VisionsParser`)在场景中编排预定义的飞行路径。
48
48
  - 获取复杂的节点材质,并自定义 WebGPU 专属的 TSL(Three Shading Language)节点,如 `TSLEffects.fluid()`。
49
+
50
+ ## 5. `test_model_animation.html`:模型内置动画
51
+
52
+ [在线演示](https://u-space-phi.vercel.app/examples/test_model_animation.html)
53
+
54
+ 该示例演示了如何加载含内置动画的 glTF 模型,并通过 `Model` 类的动画 API 控制播放。
55
+
56
+ ### 核心要点:
57
+
58
+ - 使用 `Model.loadAsync()` 加载带动画的 `.glb` 文件,动画片段自动初始化。
59
+ - 使用 `viewer.frameloop = 'always'` 开启持续渲染以驱动动画。
60
+ - 监听 `beforeRender` 事件,通过 `model.updateAnimation(e.delta)` 推进动画时间。
61
+ - 使用 `model.playAnimation(name)` 按名称播放单个动画,`model.playAllAnimations()` 播放全部。
62
+ - 使用 `model.stopAnimation()` 停止动画播放。
63
+
64
+ ## 6. `test_css_renderer.html`:CSS2D / CSS2.5D / CSS3D 渲染器
65
+
66
+ 该示例演示了如何在 3D 场景中叠加渲染 HTML 元素,展示三种 CSS 渲染模式的效果差异。
67
+
68
+ ### 核心要点:
69
+
70
+ - 使用 `viewer.cssRenderer.createCSS2DObject()` 创建始终面向相机、固定屏幕尺寸的 2D 标签。
71
+ - 使用 `viewer.cssRenderer.createCSS25DObject()` 创建面向相机但随距离缩放的 2.5D 精灵。
72
+ - 使用 `viewer.cssRenderer.createCSS3DObject()` 创建具有完整 3D 变换的面板。
73
+ - CSS2.5D 和 CSS3D 对象需要设置 `scale`(通常 `0.01`),因为 HTML 元素的像素尺寸远大于 3D 世界单位。
74
+ - 渲染器采用懒加载,仅在首次创建对应类型对象时初始化。
75
+
76
+ ## 7. `test_postprocessing.html`:后处理效果
77
+
78
+ 该示例演示了 `RenderPipeline` 的内置后处理功能,包括 Bloom、SSGI、TRAA 以及自定义后处理组合器。
79
+
80
+ ### 核心要点:
81
+
82
+ - 使用 `viewer.renderPipeline.enableBloom()` / `disableBloom()` 运行时切换 Bloom 效果。
83
+ - 使用 `viewer.renderPipeline.updateBloom()` 实时调整 strength、radius、threshold 参数。
84
+ - 使用 `viewer.renderPipeline.enableSSGI()` / `disableSSGI()` 切换屏幕空间全局光照。
85
+ - 使用 `viewer.renderPipeline.updateSSGI()` 实时调整 SSGI 参数(直接修改 uniform,无需重建节点图)。
86
+ - 使用 `viewer.renderPipeline.enableTRAA()` / `disableTRAA()` 切换时间抗锯齿。
87
+ - 使用 `viewer.renderPipeline.setOutputComposer()` 自定义后处理链(示例中实现了灰度滤镜)。
88
+ - 使用 `setOutputComposer(null)` 恢复默认渲染管线。
@@ -119,6 +119,18 @@ box.addEventListener('pointerleave', (e) => {
119
119
 
120
120
  这样就完成了!你现在拥有一个基础的 `u-space` 应用。
121
121
 
122
+ ## 版本信息
123
+
124
+ `u-space` 导出了 `version` 常量,同时在 `window.__USPACE__` 上挂载了版本信息,方便调试和版本检查。
125
+
126
+ ```typescript
127
+ import { version } from 'u-space';
128
+ console.log(version); // e.g. '0.0.5'
129
+
130
+ // 也可以通过全局变量访问
131
+ console.log(window.__USPACE__.version);
132
+ ```
133
+
122
134
  ## 下一步
123
135
 
124
136
  - 深入了解 [Viewer API](./api-viewer.md)