跳转至

App 模块 API 参考手册

本参考手册列出了 App 模块及其协调的管理器(Managers)所暴露的每一个公共接口。

目录


App 类

App 类是一个轻量级的协调器。它负责连接 UI 回调,将逻辑分发给各个管理器,并拥有渲染循环的生命周期。

constructor()

创建 DOM 绑定、管理器实例和 UI 回调。此时尚未分配 GPU 资源。

已初始化的管理器: - ModelManager (最大支持 10000 个模型) - CameraManager - AnimationManager - RenderLoop - FileLoader (包含加载回调) - ONNXManager - UIController (包含 UI 回调)

init(): Promise

初始化完整的应用程序:

  1. 初始化 ORT (ONNX Runtime) 环境
  2. 通过 initWebGPU_onnx 初始化 WebGPU (包含 ORT 集成回退机制)
  3. 创建 GaussianRenderer 并确保排序器 (sorter) 准备就绪
  4. 初始化相机并设置默认控制器 (FPS)
  5. 绑定 UI 事件处理程序
  6. 设置调整大小 (resize) 处理程序
  7. 使用 GPU 上下文和回调初始化 RenderLoop
  8. 启动渲染循环

抛出异常 当: - 缺少 Canvas 元素 - WebGPU 初始化失败 (此时会显示横幅提示)

回退行为: - 如果 ORT 集成失败,回退到独立的 WebGPU 模式 - 如果 WebGPU 不可用,显示错误横幅并优雅退出

模型加载 (Model Loading)

高斯格式 (统一接口):

  • loadGaussian(input: File | string, options?: LoadOptions): Promise<void> – 所有高斯格式 (PLY, SPZ, KSplat, SPLAT, SOG, compressed PLY) 的统一加载器。自动检测格式或接受 gaussianFormat 选项。

特定格式加载器:

  • loadPLY(input: File | string, options?: LoadOptions): Promise<void> – 加载 PLY 格式 (已弃用,请使用 loadGaussian)。
  • loadSPZ(input: File | string, options?: LoadOptions): Promise<void> – 专门加载 SPZ 格式。
  • loadKSplat(input: File | string, options?: LoadOptions): Promise<void> – 专门加载 KSplat 格式。
  • loadSplat(input: File | string, options?: LoadOptions): Promise<void> – 专门加载 SPLAT 格式。
  • loadSOG(input: File | string, options?: LoadOptions): Promise<void> – 专门加载 SOG 格式。

ONNX 模型:

  • loadONNXModel(modelPath: string, name?: string, staticInference?: boolean): Promise<void> – 通过 ONNXManager 加载 ONNX 模型。staticInference=false 启用每帧 GPU 推理。
  • loadONNXModelPublic(modelPath?: string, name?: string): Promise<void> – 用于集成的公共别名。

示例文件:

  • loadSample(filename: string): Promise<void> – 从 /assets 或配置的 URL 加载资源。自动检测格式。

文件支持:

  • getSupportedFormats(): { gaussian: string[], onnx: string[], models: string[], all: string[] } – 返回所有支持的文件扩展名。
  • isFileSupported(fileName: string): boolean – 检查文件格式是否受支持。

内部 (私有):

  • loadFile(file: File): Promise<void> – 内部方法,检测文件类型并路由至相应的加载器。

LoadOptions 接口:

interface LoadOptions {
  /** 用于验证的预期文件类型 */
  expectedType?: 'gaussian' | 'onnx' | 'model';
  /** 指定的高斯格式 (若未提供则自动检测) */
  gaussianFormat?: GaussianFormat;
  /** ONNX 模型的静态推理开关 */
  staticInference?: boolean;
  /** 启用调试日志 */
  debugLogging?: boolean;
}

注意: ONNX 的摄入故意绕过了 FileLoader;它保持 ONNX 工作流仅在 GPU 上运行。

相机与控制 (Camera & controls)

  • resetCamera(): void
  • switchController(type: 'orbit' | 'fps'): void – 轨道模式 (Orbit) 会在存在可见模型边界时以其为中心。
  • getCameraMatrix(): mat4
  • getProjectionMatrix(): mat4

渲染状态 (Rendering state)

  • setGaussianScale(scale: number): void
  • setBackgroundColor(color: [number, number, number, number]): void
  • getGaussianScale(): number
  • getBackgroundColor(): [number, number, number, number]

模型与诊断 (Models & Diagnostics)

模型查询:

  • getModels(): ModelInfo[] – 返回用于 UI 显示的轻量级元数据 (React 渲染安全)。
  • getFullModels(): ModelEntry[] – 返回包含完整 pointCloud 引用的所有模型条目 (用于调试/测试)。
  • getModelWithPointCloud(modelType: 'ply' | 'onnx' | 'fbx', id?: string): ModelEntry | null – 获取带有完整 pointCloud 引用的特定模型条目。

调试信息:

  • getDebugInfo(): any – 返回跨所有管理器的聚合快照:
{
  app: { initialized, canvas, supportedFormats },
  models: { count, capacity, totalPoints, visiblePoints },
  camera: CameraManager.getDebugInfo(),
  animation: AnimationManager.getDebugInfo(),
  renderLoop: RenderLoop.getDebugInfo(),
  onnx: { hasModels, modelCount, performanceStats }
}

动态动画控制 (Dynamic Animation Control)

  • controlDynamicAnimation(action: 'start' | 'pause' | 'resume' | 'stop', speed?: number): void – 所有动态模型的全局控制。
  • setDynamicAnimationTime(time: number): void – 设置动态模型的动画时间。
  • getDynamicPerformanceStats(): Array<{ modelName: string, stats: any }> – 获取动态模型的性能统计信息。

管理器访问 (高级用法)

直接访问管理器实例以用于高级用例:

  • getModelManager(): ModelManager – 访问模型存储和跟踪。
  • getONNXManager(): ONNXManager – 访问 ONNX 模型管理。
  • getCameraManager(): CameraManager – 访问相机和控制器管理。
  • getAnimationManager(): AnimationManager – 访问动画和动态更新逻辑。
  • getRenderLoop(): RenderLoop – 访问渲染循环和帧周期。

注意: 这些方法仅供高级用例使用。大多数操作应通过 App 公共 API 进行。


管理器类 (Manager Classes)

App 模块使用基于管理器的架构。虽然大多数操作应通过 App 类进行,但在高级用例中可以直接访问管理器。

ModelManager

所有已加载 3D 内容的中央存储库。

路径: src/app/managers/model-manager.ts

关键方法:

  • addModel(model: Omit<ModelEntry, 'id'>): ModelEntry – 注册模型,分配唯一 ID。如果达到容量 (默认 10000) 则抛出异常。
  • removeModel(id: string): boolean – 按 ID 移除模型。
  • getModels(): ModelInfo[] – 返回简化元数据 (UI/React 渲染安全)。
  • getFullModels(): ModelEntry[] – 返回包含完整 pointCloud 引用的所有模型条目。
  • getModelWithPointCloud(modelType: 'ply' | 'onnx' | 'fbx', id?: string): ModelEntry | null – 获取特定模型条目。
  • getModelsByType(modelType: 'ply' | 'onnx' | 'fbx'): ModelEntry[] – 按类型获取模型。
  • getVisibleModels(): ModelEntry[] – 仅获取可见模型。
  • setModelVisibility(id: string, visible: boolean): void – 设置模型可见性。
  • getModelCount(): number – 获取模型总数。
  • getRemainingCapacity(): number – 获取剩余模型容量。
  • getTotalPoints(): number – 获取所有模型的总点数。
  • getTotalVisiblePoints(): number – 获取可见点总数。
  • isAtCapacity(): boolean – 检查是否达到模型限制。

ModelEntry 接口:

interface ModelEntry {
  id: string;
  name: string;
  visible: boolean;
  pointCloud: PointCloud | DynamicPointCloud;
  pointCount: number;
  isDynamic: boolean;
  modelType: 'ply' | 'onnx' | 'fbx' | 'spz' | 'ksplat' | 'splat' | 'sog';
  colorMode?: string;
  colorChannels?: number;
}

FileLoader

包装了 IO 模块的统一资源加载器。

路径: src/app/managers/file-loader.ts

支持格式:

  • Gaussian: .ply, .spz, .ksplat, .splat, .sog, .compressed.ply
  • Mesh: .fbx

关键方法:

  • loadFile(file: File, device: GPUDevice): Promise<ModelEntry | null> – 直接从 File 对象加载。
  • loadSample(filename: string, device: GPUDevice, expectedType?: string): Promise<ModelEntry | null> – 从 URL 加载。包含对 Blob URL 的特殊处理。
  • validateFile(file: File): boolean – 检查大小限制 (默认 1GB) 和格式支持。
  • getSupportedExtensions(): string[] – 返回所有支持的文件扩展名。

LoadingCallbacks 接口:

interface LoadingCallbacks {
  onProgress?: (show: boolean, text?: string, pct?: number) => void;
  onError?: (message: string) => void;
}

ONNXManager

处理神经网络驱动的点云的生命周期。

路径: src/app/managers/onnx-manager.ts

关键方法:

  • loadONNXModel(device: GPUDevice, modelPath: string, cameraMatrix: Float32Array, projMatrix: Float32Array, name?: string, options?: ONNXLoadOptions): Promise<ModelEntry> – 创建 ONNXGenerator (ONNX Runtime Session) 和 DynamicPointCloud。如果 staticInference=false,则将生成器连接到点云以进行实时更新。
  • disposeModel(id: string): void – 清理与模型关联的 GPU 缓冲区和 ORT 会话。
  • getONNXPerformanceStats(): object – 返回活动生成器和点云的数量。
  • hasONNXModels(): boolean – 检查是否加载了任何 ONNX 模型。
  • getONNXModels(): ModelEntry[] – 返回所有 ONNX 模型条目。

ONNXLoadOptions 接口:

interface ONNXLoadOptions {
  staticInference?: boolean;  // 如果为真,运行一次推理;如果为假,每帧运行。
  maxPoints?: number;         // 手动覆盖缓冲区分配。
  precisionConfig?: object;   // ONNX Runtime 的 FP16/FP32 精度设置。
  debugLogging?: boolean;     // 启用调试日志。
}

CameraManager

管理相机矩阵和用户输入控制器。

路径: src/app/managers/camera-manager.ts

关键方法:

  • initCamera(canvas: HTMLCanvasElement): void – 设置默认透视相机 (45度 FOV)。
  • switchController(type: 'orbit' | 'fps'): void – 切换相机控制器。切换到 Orbit 时,根据场景内容计算目标中心,以防止围绕空空间旋转。切换期间保留相机位置/旋转。
  • setupCameraForPointCloud(pc: PointCloud): void – 自动调整相机以适应给定点云的边界框 (Bounding Box)。
  • update(dt: number): void – 更新活动控制器 (Orbit/FPS) 逻辑。
  • resize(canvas: HTMLCanvasElement): void – 处理画布调整大小。
  • resetCamera(): void – 将相机重置为默认位置。
  • getCameraMatrix(): mat4 – 获取当前视图矩阵。
  • getProjectionMatrix(): mat4 – 获取当前投影矩阵。
  • getController(): CameraController – 获取活动相机控制器。
  • setOrbitCenter(center: vec3): void – 设置 Orbit 控制器的旋转中心。
  • getDebugInfo(): object – 返回相机调试信息。

AnimationManager

驱动动态内容的更新。

路径: src/app/managers/animation-manager.ts

关键方法:

  • updateDynamicPointClouds(view: mat4, proj: mat4, time: number): Promise<void>节流 (Throttling): 如果上一次更新仍在处理中 (_frameUpdating 标志),则防止重入。遍历所有可见的动态模型并调用其 update() 方法。
  • controlDynamicAnimation(action: 'start' | 'pause' | 'resume' | 'stop', speed?: number): void – 所有动态模型的全局控制。
  • setUpdateInterval(ms: number): void – 限制更新频率 (例如,限制物理/推理 FPS 以独立于渲染 FPS)。
  • setDynamicAnimationTime(time: number): void – 设置动态模型的动画时间。
  • getDynamicPerformanceStats(): Array<{ modelName: string, stats: AnimationStats }> – 返回动态模型的性能统计信息。
  • getDebugInfo(): object – 返回动画调试信息。

AnimationStats 接口:

interface AnimationStats {
  updateCount: number;
  averageUpdateTime: number;
  lastUpdateTime: number;
}

RenderLoop

应用程序的“心跳”。

路径: src/app/managers/render-loop.ts

工作流:

  1. init(gpu, renderer, canvas): 使用 GPU 上下文、渲染器和画布进行初始化。
  2. start(): 启动 requestAnimationFrame
  3. frame() 循环:
  4. 计算 dt (Delta Time)。
  5. CameraManager.update(dt)
  6. AnimationManager.updateDynamicPointClouds(...)
  7. FPS 计数: 更新内部计数器。
  8. renderer.renderMulti(...): 提交 GPU 绘制命令。

关键方法:

  • start() / stop(): void – 控制渲染循环生命周期。
  • setGaussianScale(scale: number): void – 更新全局渲染 Uniform 变量。
  • getGaussianScale(): number – 获取当前高斯缩放比例。
  • setBackgroundColor(color: [number, number, number, number]): void – 设置背景颜色。
  • getBackgroundColor(): [number, number, number, number] – 获取当前背景颜色。
  • getPerformanceInfo(): object – 返回实时 FPS 和帧时间。
  • setCallbacks(callbacks: FPSCallbacks): void – 设置 FPS 和点数更新回调。
  • getState(): AppState – 获取当前渲染状态。
  • getDebugInfo(): object – 返回渲染循环调试信息。

FPSCallbacks 接口:

interface FPSCallbacks {
  onFPSUpdate?: (fps: number) => void;
  onPointCountUpdate?: (count: number) => void;
}

AppState 接口:

interface AppState {
  background: [number, number, number, number];
  gaussianScale: number;
  animationId: number;
  lastTime: number;
  frames: number;
  fpsAccumStart: number;
}

GaussianModel

一个 THREE.Object3D 包装器,用于保持高斯泼溅模型与 GPU 状态同步。

constructor(entry: ModelEntry)

属性

  • modelName: string
  • pointCloud: PointCloud | DynamicPointCloud
  • autoSyncEnabled: boolean
  • gaussianScale: number

方法

  • syncTransformToGPU(): void
  • enableAutoSync(): void
  • disableAutoSync(): void
  • getModelEntry(): ModelEntry
  • isDynamic(): boolean
  • updateDynamicData(): void

GaussianThreeJSRenderer

连接 Visionary 与 Three.js,使高斯点 (Splat) 和网格 (Mesh) 几何体可以在同一个 WebGPU 设备上渲染。

constructor(renderer: THREE.WebGPURenderer, scene: THREE.Scene, gaussianModels: GaussianModel[])

属性

  • renderer: GaussianRenderer
  • gaussianModels: GaussianModel[]
  • autoDepthMode: boolean

方法

  • onResize(width: number, height: number): void
  • onBeforeRender(renderer: THREE.WebGPURenderer, scene: THREE.Scene, camera: THREE.Camera): void
  • addGaussianModel(model: GaussianModel): void
  • removeGaussianModel(model: GaussianModel): void
  • setAutoDepthMode(enabled: boolean): void
  • getSceneDepthTexture(): THREE.DepthTexture | null
  • dispose(): void

WebGPU 辅助函数

initWebGPU_onnx(canvas, opts?): Promise<WebGPUContext | null> 协商共享的 WebGPU 设备和画布上下文。它首选复用 ONNX Runtime 设备;传递 dummyModelUrl 可强制创建设备。

type WebGPUContext = {
  device: GPUDevice;
  context: GPUCanvasContext;
  format: GPUTextureFormat;
};

支持的选项:

  • preferShareWithOrt?: boolean
  • dummyModelUrl?: string | null
  • adapterPowerPreference?: GPURequestAdapterOptions['powerPreference']
  • allowOwnDeviceWhenOrtPresent?: boolean

UIController 与 DOMElements

UIController 拥有 DOM 事件绑定,而 App 提供回调。DOMElements 暴露了 UI 层使用的类型化选择器。

interface UICallbacks {
  onFileLoad(file: File): Promise<void>;
  onSampleLoad(filename: string): void;
  onResetCamera(): void;
  onGaussianScaleChange(scale: number): void;
  onBackgroundColorChange(color: [number, number, number, number]): void;
  onControllerSwitch(type: 'orbit' | 'fps'): void;
}

UnifiedModelLoader

针对 PLY, ONNX, FBX, GLTF, OBJ, STL 等格式的统一加载器。

constructor(renderer: THREE.WebGPURenderer, scene: THREE.Scene)
interface UnifiedLoadOptions {
  type?: ModelType;
  name?: string;
  isGaussian?: boolean;
  cameraMatrix?: Float32Array;
  projectionMatrix?: Float32Array;
  gaussianOptions?: GaussianLoadOptions;
  fbxOptions?: FBXLoadOptions;
  sourceFile?: File;
  onProgress?: (progress: number) => void;
  onError?: (error: Error) => void;
}

方法

  • loadModel(input: File | string, options?: UnifiedLoadOptions): Promise<LoadResult>
  • loadModels(inputs: (File | string)[], options?: UnifiedLoadOptions): Promise<LoadResult[]>

便捷包装器:

async function loadUnifiedModel(
  renderer: THREE.WebGPURenderer,
  scene: THREE.Scene,
  input: File | string | (File | string)[],
  options?: UnifiedLoadOptions
): Promise<LoadResult | LoadResult[]>

TransformTracker

跟踪模型变换和源元数据,用于保存/加载管道。

constructor()

方法

  • install(app: App): void
  • uninstall(): void
  • getTransform(modelId: string): ModelTransform | null
  • getSource(modelId: string): ModelSource | null
  • updateSource(modelId: string, newSource: ModelSource): void
  • getAllTrackedModels(): Array<{ modelId: string; source: ModelSource; transform: ModelTransform }>
  • cleanupRemovedModels(currentModelIds: string[]): void
interface ModelSource {
  kind: 'relative' | 'url';
  path?: string;
  url?: string;
  originalName?: string;
}

interface ModelTransform {
  position?: [number, number, number];
  rotationEulerRad?: [number, number, number];
  scale?: [number, number, number];
}

SceneFS

基于文件系统访问 API (File System Access API) 和 scene.json 清单的目录式场景管理器。

constructor()

方法

  • pickFolderRead(): Promise<void>
  • pickFolderWrite(): Promise<void>
  • loadScene(app: App): Promise<void>
  • saveScene(app: App): Promise<void>
  • getRootHandle(): FileSystemDirectoryHandle | null
interface SceneManifest {
  version: 1;
  meta?: {
    app?: string;
    createdAt?: string;
    unit?: 'meter' | 'centimeter' | string;
  };
  env?: {
    bgColor?: [number, number, number, number];
    gaussianScale?: number;
    camera?: {
      position: [number, number, number];
      target: [number, number, number];
      up: [number, number, number];
      fov: number;
    } | null;
  };
  assets: AssetEntry[];
}

interface AssetEntry {
  name: string;
  type: AssetType; // 'ply' | 'onnx' | 'fbx'
  path: string;
  dynamic?: boolean;
  transform?: {
    position?: [number, number, number];
    rotationEulerRad?: [number, number, number];
    scale?: [number, number, number];
  };
  extras?: {
    urlFallback?: string;
  };
}

Three.js 引导启动

initThreeContext(canvasElement) 为 Three.js 构建一个共享的 WebGPU 渲染器。

async function initThreeContext(
  canvasElement: HTMLCanvasElement
): Promise<THREE.WebGPURenderer | null>

当 WebGPU 或 ORT 集成无法建立时返回 null


重要说明

  • 渲染器会对每个可见模型进行批处理,执行一次全局基数排序 (radix sort),并在每帧发出单个间接绘制调用 (indirect draw call)。
  • 动态 ONNX 模型暴露了一个 GPU 侧的计数缓冲区 (count buffer);预处理过程会尊重实时实例计数,而无需重新分配内存。