跳转至

IO 模块

IO 模块充当 Visionary 的 统一数据摄入层。它处理多种 3D 高斯泼溅 (Gaussian Splatting) 格式和标准 3D 网格格式的文件加载与数据解析。它提供了一个灵活、可扩展的架构,用于加载各种文件格式并将它们转换为 GPU 就绪的数据结构。

概览

IO 模块是 3D 高斯泼溅管道中所有数据加载操作的入口点。它将原始文件数据转换为针对 WebGPU 渲染优化的结构化格式,将各种文件格式的复杂性抽象为一致的内存布局 (DataSource),应用程序无需了解底层文件结构即可使用。

关键特性

  • 通用文件加载: 自动格式检测并委托给合适的加载器
  • 多种高斯格式: 支持 PLY, SPZ, KSplat, SPLAT, SOG, 和 Compressed PLY
  • Three.js 网格支持: 通过适配器处理 FBX, GLTF, OBJ, STL, 和 Mesh PLY
  • 智能路由: 基于文件扩展名、MIME 类型或二进制“魔数字节 (Magic Bytes)”嗅探自动选择正确的加载器
  • PLY 格式区分: 通过检查头部属性自动检测 PLY 文件是 3DGS 还是网格格式
  • 格式检测: 用于格式识别的辅助函数 (detectGaussianFormat, isGaussianFormat)
  • 进度报告: 带有特定阶段反馈的详细加载进度
  • 内存优化: 使用半精度打包进行高效数据转换
  • 可扩展架构: 带有双注册表(高斯和 Three.js)的插件式加载器注册系统
  • 错误处理: 全面的验证和描述性错误消息
  • 场景保存: 统一的场景导出功能 (saveUnifiedScene)

核心概念

  • 数据源 (Data Sources): 无论源格式如何,数据的标准化接口 (DataSource, GaussianDataSource, ThreeJSDataSource)
  • 加载器注册表: 不同文件格式解析器(高斯和 Three.js)的动态注册系统
  • 双注册表系统: 分别用于高斯泼溅格式和 Three.js 网格格式的注册表
  • 格式检测: 通过扩展名、MIME 类型或魔数自动识别格式
  • 进度回调: 长时间运行的加载操作期间的用户反馈
  • 缓冲区管理: 高效的 CPU 到 GPU 数据传输准备
  • 类型守卫: 安全的类型检查 (isGaussianDataSource, isThreeJSDataSource)

快速开始

基本文件加载 (通用加载器)

import { defaultLoader } from 'src/io';

// 从文件输入加载 - 自动检测格式
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async (event) => {
  const file = event.target.files[0];

  try {
    const data = await defaultLoader.loadFile(file, {
      onProgress: (progress) => {
        console.log(`${progress.stage}: ${progress.progress * 100}%`);
      }
    });

    // 检查是否为高斯数据
    if (isGaussianDataSource(data)) {
      console.log(`Loaded ${data.numPoints()} points`);
      console.log(`SH degree: ${data.shDegree()}`);
    } else if (isThreeJSDataSource(data)) {
      console.log(`Loaded ${data.modelType()} model`);
    }
  } catch (error) {
    console.error('Loading failed:', error);
  }
});

加载不同格式

import { defaultLoader, detectGaussianFormat, isGaussianFormat } from 'src/io';

// 从文件名检测格式
const format = detectGaussianFormat('model.spz');
console.log(`Format: ${format}`); // 'spz'

// 检查文件是否为高斯格式
if (isGaussianFormat('model.ply')) {
  const data = await defaultLoader.loadFile(file);
}

// 加载特定格式
import { SPZLoader } from 'src/io';
const spzLoader = new SPZLoader();
const data = await spzLoader.loadUrl('/models/scene.spz');

从 URL 加载

import { defaultLoader } from 'src/io';

const data = await defaultLoader.loadUrl('/models/scene.ply', {
  isGaussian: true, // 如果格式不明确,显式指定
  onProgress: ({ stage, progress, message }) => {
    updateProgressBar(progress);
    setStatusText(`${stage}: ${message || ''}`);
  }
});

自定义加载器注册

import { createUniversalLoader, LoaderType } from 'src/io';

const loader = createUniversalLoader();

// 注册自定义高斯格式加载器
class CustomGaussianLoader implements ILoader<GaussianDataSource> {
  // ... 实现
}

loader.register(new CustomGaussianLoader(), ['.custom'], LoaderType.GAUSSIAN);

// 注册自定义 Three.js 适配器
loader.register(new CustomThreeJSAdapter(), ['.custom'], LoaderType.THREE);

场景保存

import { saveUnifiedScene } from 'src/io/unified-scene-saver';

// 保存包含模型和关键帧的场景
await saveUnifiedScene({
  scenes: [{
    models: [
      {
        id: 'model-1',
        name: 'MyModel.ply',
        typeTag: 'fileModel',
        trs: [[0, 0, 0], [0, 0, 0, 1], [1, 1, 1]],
        originFile: fileHandle,
        assetName: 'MyModel.ply'
      }
    ],
    keyframes: [
      {
        objectId: 'model-1',
        frame: 0,
        trs: [[0, 0, 0], [0, 0, 0, 1], [1, 1, 1]]
      }
    ]
  }],
  folderHandle: directoryHandle,
  meta: {
    createdAt: new Date().toISOString(),
    author: 'User'
  }
});

模块结构

src/io/
├── index.ts                      # 接口、类型和导出
├── universal_loader.ts           # 通用加载器 (高斯 + Three.js)
├── universal_gaussian_loader.ts  # 仅高斯加载器
├── ply_loader.ts                 # PLY 格式实现
├── spz_loader.ts                 # SPZ 格式实现
├── ksplat_loader.ts              # KSplat 格式实现
├── splat_loader.ts               # SPLAT 格式实现
├── sog_loader.ts                 # SOG 格式实现
├── compressed_ply_loader.ts      # 压缩 PLY 实现
├── GaussianData.ts               # PLYGaussianData 类
├── threejs_adapters.ts           # Three.js 网格格式适配器
└── unified-scene-saver.ts        # 场景保存功能

数据流

  1. 文件输入 → 通用加载器检测格式
  2. 格式检测 → 选择合适的加载器(高斯或 Three.js 注册表)
  3. PLY 格式区分 → 对于 .ply 文件,检查头部以确定是 3DGS 还是网格
  4. 解析 → 解析原始数据并报告进度
  5. 处理 → 将数据转换为 GPU 格式
  6. 输出 → 准备好进行渲染的 GaussianDataSourceThreeJSDataSource

支持的格式

高斯泼溅格式

格式 扩展名 加载器类 描述
标准 PLY .ply PLYLoader 标准 3DGS 格式 (ASCII/Binary)。执行归一化和 SH 打包。通过检查头部中的 3DGS 属性自动检测。
压缩 PLY .compressed.ply CompressedPLYLoader 使用基于分块的量化压缩的 PLY 格式。位置、旋转、缩放和颜色使用量化打包。通过 .compressed.ply 扩展名检测。
SPZ .spz SPZLoader 带有量化位置/旋转的基于 GZIP 的容器。
SOG .sog SOGLoader SuperOrdered Gaussians。支持原始 (Raw) 和 ZIP 压缩变体。通过 ZIP 魔数 (0x504b0304) 检测。
Splat .splat SplatLoader 原始二进制转储格式(32 字节步长)。加载极快。
KSplat .ksplat KSplatLoader Luma AI 优化的块格式。通过 "KSPL" 魔数检测。

网格格式 (Three.js 适配器)

格式 扩展名 适配器类 描述
FBX .fbx FBXLoaderAdapter 包装 THREE.FBXLoader。保留材质并应用阴影设置。
GLTF/GLB .gltf, .glb GLTFLoaderAdapter 包装 THREE.GLTFLoader。保留材质并应用阴影设置。
OBJ .obj OBJLoaderAdapter 包装 THREE.OBJLoader。支持 MTL 材质。
STL .stl STLLoaderAdapter 包装 THREE.STLLoader
网格 PLY .ply ThreeJSPLYLoaderAdapter 用于包含传统三角网格的 PLY 文件(当 3DGS 属性缺失时检测到)。

加载器类型

UniversalLoader

处理高斯泼溅和 Three.js 网格格式的主加载器。它维护两个独立的注册表,并根据格式检测智能路由文件。

特性:

  • 双注册表系统(高斯和 Three.js)
  • 自动 PLY 格式区分(3DGS 与网格)
  • 压缩格式的魔数检测
  • 运行时加载器注册

UniversalGaussianLoader

仅处理高斯泼溅格式的专用加载器。当您知道只处理高斯数据时很有用。

特性:

  • 单一用途:仅限高斯格式
  • 更简单的 API 表面
  • 更快的格式检测(无需查询 Three.js 注册表)

格式检测

IO 模块提供了几个用于格式检测的工具:

import { 
  detectGaussianFormat, 
  isGaussianFormat, 
  GaussianFormat,
  isGaussianDataSource,
  isThreeJSDataSource 
} from 'src/io';

// 从文件名检测格式
const format = detectGaussianFormat('model.spz'); // 返回 GaussianFormat.SPZ

// 检查文件是否为高斯格式
if (isGaussianFormat('model.ply')) {
  // 处理高斯文件
}

// 用于运行时类型检查的类型守卫
if (isGaussianDataSource(data)) {
  const points = data.numPoints();
}

if (isThreeJSDataSource(data)) {
  const obj = data.object3D();
}

PLY 格式区分

该模块通过检查头部是否包含必需的 3DGS 属性,自动检测 .ply 文件是 3D 高斯泼溅文件还是传统网格文件:

  • property float opacity
  • property float scale_0, scale_1, scale_2
  • property float rot_0, rot_1, rot_2, rot_3

如果所有这些属性都存在,文件将被视为 3DGS 文件;否则,它将被路由到 Three.js PLY 加载器。

性能特征

  • 加载速度: 针对大型数据集(>100万点)进行了优化
  • 内存使用: 高效的半精度打包将 GPU 内存减少了 50%
  • 进度粒度: 亚秒级更新,实现响应式 UI
  • 错误恢复: 优雅地处理格式错误的文件
  • 流式处理: 大文件增量处理以避免阻塞

集成点

IO 模块与以下模块集成:

  • App 模块: 被 FileLoader 管理器使用,用于统一资源加载
  • Point Cloud 模块: 为 GPU 缓冲区创建提供数据
  • Renderer: 提供预处理的高斯参数
  • Utils: 半精度转换和数学工具

相关文档

  • 架构 – 加载器注册表图表、缓冲区布局契约和预处理移交。
  • API 参考手册 – 加载器类、检测辅助工具和进度回调的完整列表。