Models Module Architecture
概览
Models 模块为 Visionary 中的所有模型类型提供数据层。它定义了统一的接口,适用于高斯 Splatting 格式 (PLY, SPZ, KSplat, SPLAT, SOG, Compressed PLY)、ONNX 动态模型和 FBX 网格文件。该模块由接口驱动,并在运行时状态和 UI 友好快照之间进行了清晰的分离。
Model Interfaces (ModelEntry, ModelInfo)
│
├── ModelManager (位于 app/managers) - 注册表, 查找, 可见性
├── FileLoader (位于 app/managers) - IO 管道, 格式检测
├── ONNXManager (位于 app/managers) - ONNX 模型生命周期
└── Wrappers (FBXModelWrapper) - 特定格式的功能
核心接口
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 (静态高斯), DynamicPointCloud (ONNX), 或 FBXModelWrapper (FBX 网格)
- modelType 支持:'ply' | 'spz' | 'ksplat' | 'splat' | 'sog' | 'compressed.ply' | 'onnx' | 'fbx'
- isDynamic 区分流式点云 (ONNX) 和静态资产
- colorMode 和 colorChannels 允许 UI 一致地显示颜色元数据
ModelInfo
用于 UI 层的轻量级、只读快照。不包含 pointCloud 引用,以避免持有大型对象图。
interface ModelInfo {
id: string;
name: string;
visible: boolean;
pointCount: number;
isDynamic: boolean;
modelType: ModelType;
colorMode?: 'sh' | 'rgb';
colorChannels?: number;
}
用例: React 渲染、UI 列表和序列化安全。ModelManager.getModels() 返回 ModelInfo[] 供 UI 使用。
ModelType
所有支持的模型格式的联合类型:
type ModelType =
| 'ply' | 'spz' | 'ksplat' | 'splat' | 'sog' | 'compressed.ply' // 高斯格式
| 'onnx' // 动态 ONNX
| 'fbx'; // FBX 网格
与 Managers 的集成
Models 模块接口被 app/managers 模块中的 managers 使用:
ModelManager 集成
ModelManager (位于 app/managers) 使用 ModelEntry 和 ModelInfo:
- 维护一个
ModelEntry实例数组 - 提供
getModels(): ModelInfo[]供 UI 使用 - 提供
getFullModels(): ModelEntry[]用于调试/测试 - 处理模型注册、移除和查询
- 跟踪可见性、容量限制和统计信息
FileLoader 集成
FileLoader (位于 app/managers) 创建 ModelEntry 实例:
- 加载高斯格式 (PLY, SPZ, KSplat, SPLAT, SOG, Compressed PLY) → 创建带有
PointCloud的ModelEntry - 加载 FBX 文件 → 创建带有
FBXModelWrapper的ModelEntry - 使用
ModelManager.addModel()注册条目
ONNXManager 集成
ONNXManager (位于 app/managers) 创建动态模型条目:
- 加载 ONNX 模型 → 创建带有
DynamicPointCloud的ModelEntry - 将 ONNX 条目设置为
isDynamic: true - 管理 ONNX 生成器生命周期
FBXModelWrapper
FBXModelWrapper 类包装 Three.js FBX 资产并实现 ITimelineTarget 以进行 timeline 集成。
特性
- Three.js 集成: 包装
THREE.Group和THREE.AnimationMixer - 动画支持: 完全的动画控制(播放、暂停、停止、速度、时间)
- Timeline 集成: 实现
ITimelineTarget接口 - 变换支持: 带有
setTransform()方法的 4x4 变换矩阵 - 可见性控制:
setVisible()/getVisible()方法 - 顶点计数:
getVertexCount()用于统计
动画控制
class FBXModelWrapper implements ITimelineTarget {
// Timeline 接口
setAnimationTime(time: number): void;
setAnimationSpeed(speed: number): void;
getAnimationSpeed(): number;
startAnimation(speed?: number): void;
pauseAnimation(): void;
resumeAnimation(): void;
stopAnimation(): void;
setTimeScale(scale: number): void;
setTimeOffset(offset: number): void;
setTimeUpdateMode(mode: 'fixed_delta' | 'variable_delta'): void;
getCurrentTime(): number;
update(deltaTime: number): void;
// 动画管理
switchToClip(clipIndex: number): boolean;
getClipInfo(): Array<{name: string, duration: number}>;
supportsAnimation(): boolean;
}
FBXLoadOptions
interface FBXLoadOptions {
autoPlay?: boolean; // 自动播放第一个动画
defaultSpeed?: number; // 默认播放速度
loop?: boolean; // 循环动画
blendMode?: 'normal' | 'additive'; // 动画混合模式
}
Wrappers (包装器)
- FBXModelWrapper – 加载 FBX 资产,暴露材质、动画和层级实用工具。
- 其他包装器遵循相同的模式用于 GLTF, OBJ, ONNX 派生模型等。
- 包装器可以暴露便捷方法(播放动画、重载纹理),同时保持基本契约不变。
数据流
加载流程
- 文件输入 →
FileLoader.loadFile()或FileLoader.loadSample() - 格式检测 → 检测格式 (Gaussian, ONNX, FBX)
- 数据加载 → 使用 IO 模块的
defaultLoader或FBXLoaderManager - ModelEntry 创建 → 创建带有适当
pointCloud或wrapper的ModelEntry - 注册 →
ModelManager.addModel()注册条目 - UI 更新 →
ModelManager.getModels()返回ModelInfo[]给 UI
ONNX 流程
- ONNX 加载 →
ONNXManager.loadONNXModel() - DynamicPointCloud 创建 → 使用 ONNX 生成器创建
DynamicPointCloud - ModelEntry 创建 → 创建带有
isDynamic: true的ModelEntry - 注册 →
ModelManager.addModel()注册条目 - 动画更新 →
AnimationManager每帧更新动态模型
FBX 流程
- FBX 加载 →
FBXLoaderManager.loadFromFile() - FBXModelWrapper 创建 → 创建带有动画混合器的包装器
- ModelEntry 创建 → 创建带有
FBXModelWrapper的ModelEntry - 注册 →
ModelManager.addModel()注册条目 - 动画控制 → Timeline 或直接动画方法控制播放
可扩展性
添加新格式
- 扩展 ModelType: 在
ModelType联合类型中添加新格式 - 创建 Loader: 在
app/managers中实现加载器(或使用 IO 模块) - 创建 Wrapper (可选): 如果格式需要特殊处理,创建包装器类
- 更新 FileLoader: 添加格式检测和加载逻辑
- 测试: 确保
ModelEntry创建工作正常
示例:添加 GLTF 支持
// 1. 扩展 ModelType
type ModelType = ... | 'gltf' | 'glb';
// 2. 创建 wrapper (如果需要)
class GLTFModelWrapper {
// ... 实现
}
// 3. 更新 ModelEntry pointCloud 类型
pointCloud: PointCloud | DynamicPointCloud | FBXModelWrapper | GLTFModelWrapper;
// 4. 更新 FileLoader 以处理 .gltf/.glb
性能与内存
- ModelEntry 持有完整的
pointCloud引用(用于运行时操作) - ModelInfo 是轻量级的(用于 UI 列表和序列化)
- 销毁: 移除模型时,对包装器和点云调用
dispose() - 容量限制:
ModelManager强制执行最大模型数量(默认 10000) - 统计: 跟踪点数和可见性以进行性能监控
最佳实践
- UI 使用 ModelInfo: React 组件和 UI 列表优先使用
ModelInfo - 操作使用 ModelEntry: 当需要
pointCloud引用时使用ModelEntry - 类型守卫: 访问动态特定功能前检查
isDynamic - 格式检测: 使用
modelType确定可用操作 - 内存管理: 移除模型时务必销毁包装器和点云
此架构使模型摄取保持可预测性,同时保持足够的灵活性以适应复杂的管道(混合格式、动态 ONNX 内容、FBX 动画和编辑器工具)。