Models Module API Reference
本模块暴露的模型数据契约和辅助工具的综合参考。
ModelEntry
代表运行时中已加载的一个模型。包含对 pointCloud/object3D 的完整引用以及所有元数据。
interface ModelEntry {
id: string; // 唯一标识符(自动生成)
name: string; // 显示名称
visible: boolean; // 渲染可见性标志
pointCloud: PointCloud | DynamicPointCloud | FBXModelWrapper; // 特定格式的数据
pointCount: number; // 总点数/顶点数
isDynamic: boolean; // 对 ONNX 模型为 true
modelType: ModelType; // 格式类型
colorMode?: 'sh' | 'rgb'; // 颜色编码模式
colorChannels?: number; // 颜色通道数
}
说明
pointCloud是必需的,可以是:PointCloud用于静态高斯格式 (PLY, SPZ, KSplat, SPLAT, SOG, Compressed PLY)DynamicPointCloud用于 ONNX 模型FBXModelWrapper用于 FBX 网格文件isDynamic区分流式点云 (ONNX) 和静态资产modelType支持:'ply' | 'spz' | 'ksplat' | 'splat' | 'sog' | 'compressed.ply' | 'onnx' | 'fbx'colorMode和colorChannels允许 UI 一致地显示颜色元数据id由ModelManager.addModel()使用时间戳和随机字符串自动生成
ModelInfo
用于 UI 面板或摘要的轻量级、只读表示。不包含 pointCloud 引用,以避免持有大型对象图。
interface ModelInfo {
id: string;
name: string;
visible: boolean;
pointCount: number;
isDynamic: boolean;
modelType: ModelType;
colorMode?: 'sh' | 'rgb';
colorChannels?: number;
}
说明
- React 安全: 无
pointCloud引用,React 渲染安全 - 可序列化: 可以安全地序列化为 JSON
- UI 列表: 用于模型列表、面板和摘要
- 创建方式:
ModelManager.getModels()返回ModelInfo[]
FBXModelWrapper
Three.js FBX 对象的包装器,支持动画和 Timeline 集成。实现了 ITimelineTarget 接口。
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
);
// 变换
setTransform(transform: Float32Array | number[]): void;
// 可见性
setVisible(visible: boolean): void;
getVisible(): boolean;
// 统计
getVertexCount(): number;
// ITimelineTarget 接口
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;
// 动画管理
switchToClip(clipIndex: number): boolean;
getClipInfo(): Array<{name: string, duration: number}>;
supportsAnimation(): boolean;
// 清理
dispose(): void;
}
FBXLoadOptions
interface FBXLoadOptions {
autoPlay?: boolean; // 自动播放第一个动画 (默认: true)
defaultSpeed?: number; // 默认播放速度 (默认: 1.0)
loop?: boolean; // 循环动画 (默认: false)
blendMode?: 'normal' | 'additive'; // 动画混合模式
}
主要特性
- Three.js 集成: 包装
THREE.Group和THREE.AnimationMixer - 动画控制: 对动画播放、速度和时间的完全控制
- Timeline 集成: 实现
ITimelineTarget以进行时间轴控制 - 变换矩阵: 带有
setTransform()方法的 4x4 变换矩阵 - 多剪辑: 通过
switchToClip()支持多个动画剪辑 - 时间控制: 固定/可变 delta 时间模式、时间缩放和偏移
类型定义
ModelType
所有支持的模型格式的联合类型:
type ModelType =
| 'ply' | 'spz' | 'ksplat' | 'splat' | 'sog' | 'compressed.ply' // 高斯格式
| 'onnx' // 动态 ONNX
| 'fbx'; // FBX 网格
ColorMode
高斯模型的颜色编码模式:
'sh': 球谐函数编码(通常 3 阶为 48 通道)'rgb': RGB 颜色编码(3 通道)
示例
创建一个 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,
};
// 注册到 ModelManager
const modelManager = app.getModelManager();
modelManager.addModel(entry);
创建一个 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,
};
// 注册到 ModelManager
modelManager.addModel(entry);
创建一个 FBX Model Entry
import { ModelEntry, FBXModelWrapper } from 'src/models';
import * as THREE from 'three/webgpu';
// 加载 FBX (通过 FBXLoaderManager)
const fbxGroup = await loadFBX('models/robot.fbx');
const clips = extractAnimationClips(fbxGroup);
// 创建包装器
const wrapper = new FBXModelWrapper(fbxGroup, clips, {
autoPlay: true,
defaultSpeed: 1.0,
loop: true
});
// 创建条目
const entry: ModelEntry = {
id: 'robot',
name: 'Robot',
visible: true,
pointCloud: wrapper,
pointCount: wrapper.getVertexCount(),
isDynamic: false,
modelType: 'fbx',
};
// 注册到 ModelManager
modelManager.addModel(entry);
创建不同的高斯格式
// SPZ 格式
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 格式
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,
};
在 UI 中使用 ModelInfo
// 获取用于 UI 的轻量级信息
const models = modelManager.getModels(); // 返回 ModelInfo[]
// 在 React 组件中使用
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 动画控制
// 获取 FBX 模型条目
const entry = modelManager.getModelWithPointCloud('fbx', 'robot-id');
if (entry && entry.modelType === 'fbx') {
const wrapper = entry.pointCloud as FBXModelWrapper;
// 控制动画
wrapper.startAnimation(1.5); // 以 1.5 倍速播放
wrapper.pauseAnimation();
wrapper.resumeAnimation();
wrapper.stopAnimation();
// Timeline 控制
wrapper.setAnimationTime(5.0); // 跳转到 5 秒
wrapper.setAnimationSpeed(2.0); // 2 倍速
// 切换剪辑
wrapper.switchToClip(1); // 切换到第二个动画剪辑
// 获取剪辑信息
const clips = wrapper.getClipInfo();
console.log('Available clips:', clips);
}
最佳实践
-
内存管理
- 移除模型时,对包装器和动态点云调用
dispose() - 使用
ModelManager.removeModel(),它会处理清理工作 - 对于 FBX:
wrapper.dispose()会清理 Three.js 资源
- 移除模型时,对包装器和动态点云调用
-
类型安全
- 依赖 TypeScript 类型定义和
ModelType联合类型 - 在进行特定格式的操作前,使用类型守卫检查
modelType - 在访问动态特定功能前检查
isDynamic
- 依赖 TypeScript 类型定义和
-
动态模型
- 确保
pointCount反映最大容量 - 对于 ONNX 模型,运行时点数可能会每帧变化
- 使用
DynamicPointCloud.numPoints获取当前点数
- 确保
-
UI 性能
- UI 列表优先使用
ModelInfo,避免持有大型对象图 - 使用返回
ModelInfo[]的ModelManager.getModels() - 仅在需要
pointCloud引用时使用ModelEntry
- UI 列表优先使用
-
格式检测
- 使用
modelType确定可用操作 - 检查
colorMode和colorChannels以进行 UI 显示 - 不同地处理 FBX 模型(使用
FBXModelWrapper方法)
- 使用
-
可扩展性
- 通过联合类型扩展
ModelType以添加新模型类型 - 添加新格式时保留现有契约
- 为需要特殊处理的格式创建包装器
- 通过联合类型扩展