库用法
splat-transform 提供编程 API,场景通过惰性分块 ChunkSource 流转,常驻内存按块大小而非场景规模限制,也是 CLI 处理亿级数据的管线。
API 参考
本页概述主要入口,完整 TypeDoc 见 API 参考。
基本导入
import {
readFile,
writeSource,
getInputFormat,
getOutputFormat,
createChunkDataPool,
processSourceBridged
} from '@playcanvas/splat-transform';
主要导出
主要 API 为分块源管线:
| 导出 | 说明 |
|---|---|
readFile | 惰性读取为 ChunkSource |
readFileInfo | 仅读头部元数据,不解码验证检查 |
getInputFormat | 从文件名检测输入格式 |
getOutputFormat | 检测输出格式 |
ChunkSource | 单场景分块/聚集读取约定 |
createChunkDataPool | 管线共享读取缓冲池 |
processSource, processSourceBridged | 顺序应用处理操作 |
selectLod, stackLods, concatSource, bakeTransform | 结构组合器,惰性视图 |
decimateSource | 原生分块、受内存预算限制,统一比例到精确数量,对应 --decimate |
decimateSourceAdaptive | 按局部误差分配,对应 --decimate-adaptive |
sortMortonInterleaved, sortMortonColumns | 根据交错或列式位置,将索引按 Morton Z 序排序 |
isSplatModel, resolveSplatModel | 验证合并 ChunkSourceMetadata.model 的抗锯齿/2DGS 标记 |
writeSource | 流式写任意单场景格式 |
writeLodSource | 多 LOD 源写流式 SOG 索引与分块 |
writeImage | GPU 渲染无损 WebP 或轨迹帧序列 |
loadCameraTrack | 从编辑器 document.json、Viewer settings.json 或帧列表创建轨迹 |
computeStats | 流式逐 LOD 逐列统计 |
次要 DataTable 兼容 API,每项都会将完整场景实体化到内存:
| 导出 | 说明 |
|---|---|
DataTable, Column | 旧式全场景表 |
combine | 合并多个表 |
processDataTable | 应用处理操作 |
dataTableToChunkSource, materializeToDataTable | 两种模型桥接 |
writeVoxel | 写稀疏体素八叉树 |
写其他格式时,先 dataTableToChunkSource,再 writeSource。
子路径 @playcanvas/splat-transform/viewer-settings 重导出 HTML 内置 Viewer 的设置类型、默认与验证,让配置匹配精确版本,无需独立 Viewer 依赖。
文件系统抽象
使用抽象接口以保持灵活:
读取:
- UrlReadFileSystem:浏览器/Node URL。
- MemoryReadFileSystem:内存。
- ZipReadFileSystem:ZIP。
写入:
- MemoryFileSystem:内存。
- ZipFileSystem:ZIP。
示例:读取处理
import { Vec3 } from 'playcanvas';
import {
readFile,
writeSource,
getInputFormat,
getOutputFormat,
createChunkDataPool,
processSourceBridged,
UrlReadFileSystem,
MemoryFileSystem
} from '@playcanvas/splat-transform';
// Read a PLY file from a URL as a lazy, chunked source
const fileSystem = new UrlReadFileSystem('https://example.com/');
const [source] = await readFile({
filename: 'scene.ply',
inputFormat: getInputFormat('scene.ply'),
fileSystem
});
// Apply actions: transforms compose lazily, filters stream chunk-by-chunk
const pool = createChunkDataPool();
const processed = await processSourceBridged(source, [
{ kind: 'scale', value: 0.5 },
{ kind: 'translate', value: new Vec3(0, 1, 0) },
{ kind: 'filterNaN' }
], pool);
// Stream the result to an in-memory PLY
const memFs = new MemoryFileSystem();
await writeSource({
filename: 'output.ply',
outputFormat: getOutputFormat('output.ply', {}),
source: processed,
pool,
options: {}
}, memFs);
await processed.close();
// Get the output data
const outputBuffer = memFs.results.get('output.ply');
旧 DataTable 使用者可用 materializeToDataTable(source, pool) 与 dataTableToChunkSource(dataTable) 双向桥接,均实体化全场景,大输入应优先保留源管线。
处理操作
processSource、processSourceBridged 与兼容 processDataTable 接收操作数组:
type ProcessAction =
| { kind: 'translate'; value: Vec3 }
| { kind: 'rotate'; value: Vec3 } // Euler angles in degrees
| { kind: 'scale'; value: number }
| { kind: 'filterNaN' }
| { kind: 'filterByValue'; columnName: string; comparator: 'lt'|'lte'|'gt'|'gte'|'eq'|'neq'; value: number }
| { kind: 'filterBands'; value: 0|1|2|3 }
| { kind: 'filterBox'; min: Vec3; max: Vec3 }
| { kind: 'filterSphere'; center: Vec3; radius: number }
| { kind: 'filterFloaters'; voxelResolution?: number; opacityCutoff?: number; minContribution?: number } // GPU
| { kind: 'filterCluster'; voxelResolution?: number; seed?: Vec3; opacityCutoff?: number; minContribution?: number } // GPU
| { kind: 'decimate'; count: number | null; percent: number | null }
| { kind: 'param'; name: string; value: string }
| { kind: 'stats'; format?: 'text' | 'json' }
| { kind: 'info'; format?: 'text' | 'json' }
| { kind: 'mortonOrder' };
备注
filterFloaters、filterCluster 需要 GPU,通过 ProcessOptions 传 createDevice。processSource 流式处理,遇需桥接的 decimate/GPU 体素过滤会抛错;Bridged 处理全部,仅将必要部分实体化。decimate 操作统一移除;自适应直接调 decimateSourceAdaptive。
自定义日志
按环境配置日志:
import { logger, TextRenderer } from '@playcanvas/splat-transform';
// Route status output (scopes, progress bars, messages) to stderr and
// pipeable output (e.g. JSON stats) to stdout
logger.setRenderer(new TextRenderer({
write: process.stderr.write.bind(process.stderr),
output: process.stdout.write.bind(process.stdout)
}));
logger.setVerbosity('quiet'); // 'quiet' | 'normal' | 'verbose'