IO 模块 API 参考手册
本文档涵盖了 IO 模块暴露的所有公共接口。它沿袭了 SparkJS 的风格:介绍概念,展示签名,并解释其如何融入更广泛的高斯泼溅(Gaussian Splatting)管道中。
目录
核心接口
DataSource
任何提供 3D 模型元数据的数据源的标准契约。
interface DataSource {
bbox(): { min: [number, number, number]; max: [number, number, number] };
center?: [number, number, number];
up?: [number, number, number] | null;
kernelSize?: number;
mipSplatting?: boolean;
backgroundColor?: [number, number, number];
}
GaussianDataSource
专门针对高斯泼溅的 DataSource,独立于原始文件格式。
interface GaussianDataSource extends DataSource {
gaussianBuffer(): ArrayBuffer;
shCoefsBuffer(): ArrayBuffer;
numPoints(): number;
shDegree(): number;
}
gaussianBuffer()– 打包的泼溅参数,以半精度浮点数存储(每个点 10 个uint16值)。shCoefsBuffer()– 交错存储的球谐函数系数(每个uint32中存储两个 f16)。numPoints()– 泼溅点总数。shDegree()– 球谐函数阶数;每个通道有(degree + 1)^2个系数。
ThreeJSDataSource
用于加载器的适配器,除了模型数据外,还提供 Three.js 对象。
interface ThreeJSDataSource extends DataSource {
object3D(): any; // THREE.Object3D
modelType(): string;
}
ILoader<T>
通用的文件加载器契约。
interface ILoader<T extends DataSource = DataSource> {
loadFile(file: File, options?: LoadingOptions): Promise<T>;
loadUrl(url: string, options?: LoadingOptions): Promise<T>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<T>;
canHandle(filename: string, mimeType?: string): boolean;
getSupportedExtensions(): string[];
}
LoadingOptions 通常包含进度回调和取消信号。
LoaderRegistry
将文件扩展名映射到加载器的动态注册表。
interface LoaderRegistry {
register<T extends DataSource>(loader: ILoader<T>, extensions: string[]): void;
getLoader(filename: string, mimeType?: string): ILoader | null;
getAllSupportedExtensions(): string[];
}
通用加载器
入口点
createUniversalLoader()– 构建一个独立的注册表实例。defaultLoader– App 层使用的共享单例。
UniversalLoader 表面
class UniversalLoader implements ILoader, LoaderRegistry {
constructor();
// ILoader 接口
loadFile(file: File, options?: LoadingOptions): Promise<DataSource>;
loadUrl(url: string, options?: LoadingOptions): Promise<DataSource>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<DataSource>;
canHandle(filename: string, mimeType?: string, options?: { isGaussian?: boolean }): boolean;
getSupportedExtensions(): string[];
// LoaderRegistry 接口
register<T extends DataSource>(loader: ILoader<T>, extensions: string[], type: LoaderType): void;
getLoader(filename: string, mimeType?: string, options?: { isGaussian?: boolean }): ILoader | null;
getAllSupportedExtensions(): string[];
// 额外方法
async getLoaderForFile(file: File, mimeType?: string): Promise<ILoader | null>;
}
LoaderType 枚举:
格式检测管道
- 检查文件扩展名/MIME 类型。
- 检查显式的
options.isGaussian提示。 - 对于
.ply文件,读取头部以检测 3DGS 属性。 - 检查压缩格式(GZIP, ZIP, KSPL)的魔数(magic bytes)。
- 定位第一个声明支持该格式的已注册加载器。
- 以流的方式传输数据并更新进度(
{ stage, progress, message? })。 - 将结果归一化为
DataSource。
进度报告
LoadingOptions 接受:
interface LoadingOptions {
signal?: AbortSignal;
onProgress?: (progress: LoadingProgress) => void;
debug?: boolean;
isGaussian?: boolean; // 显式格式提示
}
interface LoadingProgress {
stage: 'fetch' | 'parse' | 'pack' | string;
progress: number; // 0..1
message?: string;
}
高斯格式加载器
PLYLoader
处理 ASCII 和二进制 PLY 泼溅数据。
class PLYLoader implements ILoader<PLYGaussianData> {
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string): boolean;
getSupportedExtensions(): string[]; // ['.ply']
}
主要行为:
- 自动检测 ASCII 与二进制负载(小端和大端)。
- 解析高斯特定的顶点属性(位置、不透明度、SH 系数、协方差)。
- 当头部或属性缺失时发出明确的错误。
- 流式处理大文件以避免阻塞主线程。
- 执行归一化、四元数转换和 SH 打包。
CompressedPLYLoader
处理压缩的 PLY 文件。
class CompressedPLYLoader implements ILoader<PLYGaussianData> {
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string): boolean;
getSupportedExtensions(): string[]; // ['.compressed.ply']
}
主要行为:
- 在使用标准 PLY 加载器解析之前进行解压。
- 支持文件和 URL 加载。
SPZLoader
处理 SPZ(基于 GZIP 的容器)格式。
class SPZLoader implements ILoader<PLYGaussianData> {
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string): boolean;
getSupportedExtensions(): string[]; // ['.spz']
}
主要行为:
- GZIP 压缩容器格式。
- 处理量化后的位置/旋转。
- 针对较小的文件大小进行了优化。
KSplatLoader
处理 Luma AI 的 KSplat 格式。
class KSplatLoader implements ILoader<PLYGaussianData> {
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string): boolean;
getSupportedExtensions(): string[]; // ['.ksplat']
}
主要行为:
- 检测 "KSPL" 魔数(前 4 个字节)。
- Luma AI 优化的块格式。
- 快速加载,解析开销极小。
SplatLoader
处理原始二进制 SPLAT 格式。
class SplatLoader implements ILoader<PLYGaussianData> {
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string): boolean;
getSupportedExtensions(): string[]; // ['.splat']
}
主要行为:
- 原始二进制转储格式(每个点 32 字节步长)。
- 加载极快(无解析开销)。
- 格式:
[x, y, z, r, g, b, a, rot_0, rot_1, rot_2, rot_3, scale_0, scale_1, scale_2](均为 float32)。
SOGLoader
处理 SuperOrdered Gaussians (SOG) 格式。
class SOGLoader implements ILoader<PLYGaussianData> {
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string): boolean;
getSupportedExtensions(): string[]; // ['.sog']
}
主要行为:
- SuperOrdered Gaussians 格式。
- 支持原始 (Raw) 和 ZIP 压缩变体。
- 检测 ZIP 魔数 (0x504b0304)。
- 处理分层高斯组织。
UniversalGaussianLoader
仅处理高斯泼溅格式的专用加载器。
class UniversalGaussianLoader implements ILoader<PLYGaussianData> {
constructor();
loadFile(file: File, options?: LoadingOptions): Promise<PLYGaussianData>;
loadUrl(url: string, options?: LoadingOptions): Promise<PLYGaussianData>;
loadBuffer(buffer: ArrayBuffer, options?: LoadingOptions): Promise<PLYGaussianData>;
canHandle(filename: string, mimeType?: string): boolean;
getSupportedExtensions(): string[];
}
主要行为:
- 单一用途:仅限高斯格式。
- 更简单的 API 表面。
- 更快的格式检测(无需查询 Three.js 注册表)。
- 内部管理:PLY, SPZ, KSplat, SPLAT, SOG, Compressed PLY。
Three.js 适配器
ThreeJSModelData
实现 ThreeJSDataSource 接口的包装类。
class ThreeJSModelData implements ThreeJSDataSource {
constructor(object3D: THREE.Object3D, modelType: string = 'unknown');
object3D(): THREE.Object3D;
modelType(): string;
bbox(): { min: [number, number, number]; max: [number, number, number] };
}
GLTFLoaderAdapter
GLTF/GLB 格式适配器。
class GLTFLoaderAdapter extends ThreeJSLoaderAdapter<THREE.Group> {
constructor();
getSupportedExtensions(): string[]; // ['.gltf', '.glb']
// ... 实现 ILoader<ThreeJSModelData>
}
主要行为:
- 包装
THREE.GLTFLoader。 - 保留 GLTF 材质。
- 自动应用阴影设置。
- 支持进度报告。
OBJLoaderAdapter
OBJ 格式适配器。
class OBJLoaderAdapter extends ThreeJSLoaderAdapter<THREE.Group> {
constructor();
getSupportedExtensions(): string[]; // ['.obj']
// ... 实现 ILoader<ThreeJSModelData>
}
主要行为:
- 包装
THREE.OBJLoader。 - 支持 MTL 材质文件。
- 应用阴影设置和回退材质。
FBXLoaderAdapter
FBX 格式适配器。
class FBXLoaderAdapter extends ThreeJSLoaderAdapter<THREE.Group> {
constructor();
getSupportedExtensions(): string[]; // ['.fbx']
// ... 实现 ILoader<ThreeJSModelData>
}
主要行为:
- 包装
THREE.FBXLoader。 - 保留 FBX 材质。
- 应用阴影设置。
STLLoaderAdapter
STL 格式适配器。
class STLLoaderAdapter extends ThreeJSLoaderAdapter<THREE.Mesh> {
constructor();
getSupportedExtensions(): string[]; // ['.stl']
// ... 实现 ILoader<ThreeJSModelData>
}
主要行为:
- 包装
THREE.STLLoader。 - 创建带有回退材质的网格。
- 应用阴影设置。
ThreeJSPLYLoaderAdapter
传统网格 PLY 格式适配器。
class ThreeJSPLYLoaderAdapter extends ThreeJSLoaderAdapter<THREE.Mesh> {
constructor();
getSupportedExtensions(): string[]; // ['.ply']
// ... 实现 ILoader<ThreeJSModelData>
}
主要行为:
- 包装
THREE.PLYLoader。 - 用于不包含 3DGS 属性的 PLY 文件。
- 当 PLY 头部缺少 3DGS 属性时自动检测并使用。
createThreeJSAdapters
创建所有 Three.js 适配器的工厂函数。
返回所有可用的 Three.js 加载器适配器数组。
数据容器
PLYGaussianData
所有高斯加载器返回的 GaussianDataSource 的具体实现。
class PLYGaussianData implements GaussianDataSource {
constructor(args: {
gaussianBuffer: ArrayBuffer;
shBuffer: ArrayBuffer;
numPoints: number;
degree: number;
bbox: { min: [number, number, number]; max: [number, number, number] };
center?: [number, number, number];
up?: [number, number, number] | null;
kernelSize?: number;
mipSplatting?: boolean;
backgroundColor?: [number, number, number];
});
gaussianBuffer(): ArrayBuffer;
shCoefsBuffer(): ArrayBuffer;
numPoints(): number;
shDegree(): number;
bbox(): { min: [number, number, number]; max: [number, number, number] };
}
格式检测工具
GaussianFormat 枚举
enum GaussianFormat {
PLY = 'ply',
SPZ = 'spz',
KSPLAT = 'ksplat',
SPLAT = 'splat',
SOG = 'sog',
COMPRESSED_PLY = 'compressed.ply'
}
detectGaussianFormat
从文件名检测高斯格式。
返回: 格式枚举,如果不是公认的高斯格式则返回 null。
示例:
isGaussianFormat
检查文件名是否具有支持的高斯格式。
返回: 如果文件名以支持的高斯扩展名结尾,则返回 true。
getSupportedGaussianFormats
返回所有支持的高斯格式扩展名。
返回: ['.ply', '.spz', '.ksplat', '.splat', '.sog', '.compressed.ply']
isGaussianDataSource
类型守卫,用于检查数据源是否为高斯数据。
返回: 指示数据是否为 GaussianDataSource 的类型谓词。
isThreeJSDataSource
类型守卫,用于检查数据源是否为 Three.js 模型。
返回: 指示数据是否为 ThreeJSDataSource 的类型谓词。
场景保存
saveUnifiedScene
将场景结构和模型文件保存到目录中。
参数:
interface SaveUnifiedSceneParams {
scenes: SaveUnifiedSceneSceneEntry[];
folderHandle: FileSystemDirectoryHandle;
meta?: any;
cameraParams?: any;
totalFrames?: number;
}
场景条目 (Scene Entry):
interface SaveUnifiedSceneSceneEntry {
models: SaveUnifiedSceneModel[];
keyframes?: SaveUnifiedSceneKeyframe[];
view?: 'left' | 'right' | string;
[k: string]: any;
}
模型 (Model):
interface SaveUnifiedSceneModel {
id: string;
name?: string;
typeTag: string;
trs: [number[], number[], number[]];
type?: string;
gaussianParams?: any;
cameraParams?: any;
params?: Record<string, any>;
originFile?: File | Blob | FileSystemFileHandle;
assetName?: string;
}
关键帧 (Keyframe):
interface SaveUnifiedSceneKeyframe {
objectId: string;
frame: number;
trs: [number[], number[], number[]];
gaussianParams?: any;
cameraParams?: any;
}
主要行为:
- 在保存前验证文件夹句柄权限。
- 在写入前清空目标文件夹内容。
- 复制所有模型文件(按名称去重)。
- 生成包含场景结构的
scene.json。 - 优雅地处理 FileSystem API 错误。
示例:
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() }
});
类型定义
LoadingOptions
interface LoadingOptions {
onProgress?: (progress: LoadingProgress) => void;
signal?: AbortSignal;
debug?: boolean;
isGaussian?: boolean; // 显式格式提示
}
LoadingProgress
interface LoadingProgress {
stage: 'fetch' | 'parse' | 'pack' | string;
progress: number; // 0..1
message?: string;
}
LoaderType
错误处理
IO 模块抛出类型化错误,以便调用者可以提供可操作的反馈。
| 错误 | 描述 | 建议操作 |
|---|---|---|
UnsupportedFormatError |
没有加载器接受该文件扩展名/MIME 类型。 | 提示用户选择支持的格式或安装扩展加载器。 |
MalformedPLYHeaderError |
头部缺少必需的属性。 | 验证资源是否使用 Visionary / Spark 兼容工具导出。 |
PLYStreamError |
二进制负载意外结束。 | 建议重新下载/重新导出资源。 |
AbortError |
通过 AbortController 中止了加载。 |
静默取消;通常由用户发起。 |
FolderHandleError |
FileSystem 文件夹句柄无效或权限被拒绝。 | 请求新的文件夹句柄或检查权限。 |
所有错误都继承自 IOError,它添加了 stage?: ProgressStage 以提供更丰富的遥测数据。
class IOError extends Error {
constructor(message: string, options?: { stage?: ProgressStage; cause?: unknown });
stage?: ProgressStage;
}
集成检查清单
- 在 App 模块内使用
defaultLoader;它已经注册了所有支持的格式。 - 在引导期间尽早注册自定义加载器,以便它们参与检测。
- 加载大型资源时始终提供
onProgress,以保持 UI 响应。 - 当格式不明确时(例如
.ply文件),显式使用isGaussian选项。 - 与预处理共享辅助函数(打包、边界、元数据提取),以避免重复计算。
- 处理
AbortSignal以响应用户发起的取消。 - 使用类型守卫(
isGaussianDataSource,isThreeJSDataSource)进行运行时类型检查。