跳转至

Models模块 API 参考

Comprehensive reference for the model data contracts and helpers exposed by the module.

ModelEntry

Represents a loaded model in the runtime. Contains full references to pointCloud/object3D and all metadata.

interface ModelEntry {
  id: string;                                     // Unique identifier (auto-generated)
  name: string;                                   // Display name
  visible: boolean;                               // Render visibility flag
  pointCloud: PointCloud | DynamicPointCloud | FBXModelWrapper;  // Format-specific data
  pointCount: number;                             // Total point/vertex count
  isDynamic: boolean;                             // True for ONNX models
  modelType: ModelType;                           // Format type
  colorMode?: 'sh' | 'rgb';                       // Color encoding mode
  colorChannels?: number;                         // Number of color channels
}

Notes

  • pointCloud is required and can be:
  • PointCloud for static Gaussian formats (PLY, SPZ, KSplat, SPLAT, SOG, Compressed PLY)
  • DynamicPointCloud for ONNX models
  • FBXModelWrapper for FBX mesh files
  • isDynamic distinguishes streaming point clouds (ONNX) from static assets
  • modelType supports: 'ply' | 'spz' | 'ksplat' | 'splat' | 'sog' | 'compressed.ply' | 'onnx' | 'fbx'
  • colorMode and colorChannels allow UI to display color metadata consistently
  • id is auto-generated by ModelManager.addModel() using timestamp and random string

ModelInfo

Lightweight, read-only representation for UI panels or summaries. Does not include pointCloud reference to avoid holding large object graphs.

interface ModelInfo {
  id: string;
  name: string;
  visible: boolean;
  pointCount: number;
  isDynamic: boolean;
  modelType: ModelType;
  colorMode?: 'sh' | 'rgb';
  colorChannels?: number;
}

Notes

  • Safe for React: No pointCloud reference, safe for React rendering
  • Serializable: Can be safely serialized to JSON
  • UI Lists: Use for model lists, panels, and summaries
  • Created by: ModelManager.getModels() returns ModelInfo[]

FBXModelWrapper

Wrapper around a Three.js FBX object with animation support and Timeline integration. Implements ITimelineTarget interface.

class FBXModelWrapper implements ITimelineTarget {
  readonly object3D: THREE.Group;
  readonly mixer: THREE.AnimationMixer;
  readonly clips: THREE.AnimationClip[];
  transform: Float32Array;

  constructor(
    object3D: THREE.Group,
    clips: THREE.AnimationClip[],
    options?: FBXLoadOptions
  );

  // Transform
  setTransform(transform: Float32Array | number[]): void;

  // Visibility
  setVisible(visible: boolean): void;
  getVisible(): boolean;

  // Statistics
  getVertexCount(): number;

  // ITimelineTarget interface
  setAnimationTime(time: number): void;
  setAnimationSpeed(speed: number): void;
  getAnimationSpeed(): number;
  startAnimation(speed?: number): void;
  pauseAnimation(): void;
  resumeAnimation(): void;
  stopAnimation(): void;
  setTimeScale(scale: number): void;
  getTimeScale(): number;
  setTimeOffset(offset: number): void;
  getTimeOffset(): number;
  setTimeUpdateMode(mode: 'fixed_delta' | 'variable_delta'): void;
  getTimeUpdateMode(): 'fixed_delta' | 'variable_delta';
  getCurrentTime(): number;
  update(deltaTime: number): void;

  // Animation management
  switchToClip(clipIndex: number): boolean;
  getClipInfo(): Array<{name: string, duration: number}>;
  supportsAnimation(): boolean;

  // Cleanup
  dispose(): void;
}

FBXLoadOptions

interface FBXLoadOptions {
  autoPlay?: boolean;        // Auto-play first animation (default: true)
  defaultSpeed?: number;      // Default playback speed (default: 1.0)
  loop?: boolean;             // Loop animation (default: false)
  blendMode?: 'normal' | 'additive';  // Animation blend mode
}

Key Features

  • Three.js Integration: Wraps THREE.Group and THREE.AnimationMixer
  • Animation Control: Full control over animation playback, speed, and time
  • Timeline Integration: Implements ITimelineTarget for timeline control
  • Transform Matrix: 4x4 transform matrix with setTransform() method
  • Multiple Clips: Support for multiple animation clips with switchToClip()
  • Time Control: Fixed/variable delta time modes, time scale, and offset

Type Definitions

ModelType

Union type for all supported model formats:

type ModelType = 
  | 'ply' | 'spz' | 'ksplat' | 'splat' | 'sog' | 'compressed.ply'  // Gaussian formats
  | 'onnx'                                                          // Dynamic ONNX
  | 'fbx';                                                          // FBX mesh

ColorMode

Color encoding mode for Gaussian models:

type ColorMode = 'sh' | 'rgb';
  • 'sh': Spherical Harmonics encoding (typically 48 channels for degree 3)
  • 'rgb': RGB color encoding (3 channels)

Examples

Create a PLY Model Entry

import { ModelEntry } from 'src/models';
import { PointCloud } from 'src/point_cloud';

const entry: ModelEntry = {
  id: 'museum-lobby',
  name: 'Museum Lobby',
  visible: true,
  pointCloud: new PointCloud(device, plyData),
  pointCount: plyData.numPoints(),
  isDynamic: false,
  modelType: 'ply',
  colorMode: 'sh',
  colorChannels: 48,
};

// Register with ModelManager
const modelManager = app.getModelManager();
modelManager.addModel(entry);

Create an ONNX Model Entry

import { ModelEntry } from 'src/models';
import { DynamicPointCloud } from 'src/point_cloud';

const entry: ModelEntry = {
  id: 'animated-gaussian',
  name: 'Animated Gaussian',
  visible: true,
  pointCloud: new DynamicPointCloud(device, onnxGenerator, buffers),
  pointCount: buffers.maxPoints,
  isDynamic: true,
  modelType: 'onnx',
  colorMode: 'rgb',
  colorChannels: 3,
};

// Register with ModelManager
modelManager.addModel(entry);

Create an FBX Model Entry

import { ModelEntry, FBXModelWrapper } from 'src/models';
import * as THREE from 'three/webgpu';

// Load FBX (via FBXLoaderManager)
const fbxGroup = await loadFBX('models/robot.fbx');
const clips = extractAnimationClips(fbxGroup);

// Create wrapper
const wrapper = new FBXModelWrapper(fbxGroup, clips, {
  autoPlay: true,
  defaultSpeed: 1.0,
  loop: true
});

// Create entry
const entry: ModelEntry = {
  id: 'robot',
  name: 'Robot',
  visible: true,
  pointCloud: wrapper,
  pointCount: wrapper.getVertexCount(),
  isDynamic: false,
  modelType: 'fbx',
};

// Register with ModelManager
modelManager.addModel(entry);

Create Different Gaussian Formats

// SPZ format
const spzEntry: ModelEntry = {
  id: 'model-spz',
  name: 'SPZ Model',
  visible: true,
  pointCloud: new PointCloud(device, spzData),
  pointCount: spzData.numPoints(),
  isDynamic: false,
  modelType: 'spz',
  colorMode: 'sh',
  colorChannels: 48,
};

// KSplat format
const ksplatEntry: ModelEntry = {
  id: 'model-ksplat',
  name: 'KSplat Model',
  visible: true,
  pointCloud: new PointCloud(device, ksplatData),
  pointCount: ksplatData.numPoints(),
  isDynamic: false,
  modelType: 'ksplat',
  colorMode: 'sh',
  colorChannels: 48,
};

Using ModelInfo for UI

// Get lightweight info for UI
const models = modelManager.getModels(); // Returns ModelInfo[]

// Use in React component
function ModelList() {
  const models = modelManager.getModels();

  return (
    <ul>
      {models.map(model => (
        <li key={model.id}>
          {model.name} ({model.pointCount.toLocaleString()} points)
          {model.isDynamic && <span>Dynamic</span>}
        </li>
      ))}
    </ul>
  );
}

FBX Animation Control

// Get FBX model entry
const entry = modelManager.getModelWithPointCloud('fbx', 'robot-id');
if (entry && entry.modelType === 'fbx') {
  const wrapper = entry.pointCloud as FBXModelWrapper;

  // Control animation
  wrapper.startAnimation(1.5);  // Play at 1.5x speed
  wrapper.pauseAnimation();
  wrapper.resumeAnimation();
  wrapper.stopAnimation();

  // Timeline control
  wrapper.setAnimationTime(5.0);  // Jump to 5 seconds
  wrapper.setAnimationSpeed(2.0);  // 2x speed

  // Switch clips
  wrapper.switchToClip(1);  // Switch to second animation clip

  // Get clip info
  const clips = wrapper.getClipInfo();
  console.log('Available clips:', clips);
}

Best Practices

  1. Memory Management
  2. Call dispose() on wrappers and dynamic point clouds when removing models
  3. Use ModelManager.removeModel() which handles cleanup
  4. For FBX: wrapper.dispose() cleans up Three.js resources

  5. Type Safety

  6. Rely on TypeScript typings and ModelType union type
  7. Use type guards to check modelType before format-specific operations
  8. Check isDynamic before accessing dynamic-specific features

  9. Dynamic Models

  10. Ensure pointCount reflects the maximum capacity
  11. Runtime point counts may vary per frame for ONNX models
  12. Use DynamicPointCloud.numPoints for current point count

  13. UI Performance

  14. Prefer ModelInfo for UI lists to avoid holding large object graphs
  15. Use ModelManager.getModels() which returns ModelInfo[]
  16. Only use ModelEntry when you need pointCloud reference

  17. Format Detection

  18. Use modelType to determine available operations
  19. Check colorMode and colorChannels for UI display
  20. Handle FBX models differently (use FBXModelWrapper methods)

  21. Extensibility

  22. New model types can extend ModelType via union types
  23. Preserve existing contracts when adding new formats
  24. Create wrappers for formats that need special handling