Library Usage
splat-transform exposes a programmatic API for reading, processing, and writing Gaussian splat data. Scenes flow through lazy, chunked ChunkSources, so resident memory is bounded by chunk size rather than scene size — the same pipeline the CLI uses to process scenes of hundreds of millions of Gaussians.
This page is an overview of the main entry points. The full TypeDoc reference for every export lives at api.playcanvas.com/splat-transform.
Basic Import
import {
readFile,
writeSource,
getInputFormat,
getOutputFormat,
createChunkDataPool,
processSourceBridged
} from '@playcanvas/splat-transform';
Key Exports
Chunk-source pipeline (the primary API):
| Export | Description |
|---|---|
readFile | Read a splat file as lazy ChunkSources |
readFileInfo | Header-only structural metadata (validate/inspect without decoding) |
getInputFormat | Detect input format from filename |
getOutputFormat | Detect output format from filename |
ChunkSource | The streaming contract: chunked/gathered reads over one scene |
createChunkDataPool | Pooled read buffers shared across a pipeline |
processSource, processSourceBridged | Apply a sequence of processing actions to a source |
selectLod, stackLods, concatSource, bakeTransform | Structural combinators (lazy views) |
decimateSource | Chunk-native, memory-bounded decimation to an exact target count |
writeSource | Stream a source to any single-scene output format |
writeLodSource | Write streamed SOG (lod-meta.json + chunked units) from a multi-LOD source |
computeStats | Streaming per-LOD, per-column statistics for a source or table |
DataTable compat (secondary; every entry materializes the whole scene in memory):
| Export | Description |
|---|---|
DataTable, Column | Legacy whole-scene table |
combine | Merge multiple DataTables into one |
processDataTable | Apply processing actions to a DataTable |
dataTableToChunkSource, materializeToDataTable | Bridges between the DataTable and chunk-source worlds |
writeFile | Write a DataTable to any output format |
writeVoxel | Write sparse voxel octree files |
writeImage | Render a camera view to a lossless WebP image (requires GPU) |
File System Abstractions
The library uses abstract file system interfaces for maximum flexibility:
Reading:
UrlReadFileSystem- Read from URLs (browser/Node.js)MemoryReadFileSystem- Read from in-memory buffersZipReadFileSystem- Read from ZIP archives
Writing:
MemoryFileSystem- Write to in-memory buffersZipFileSystem- Write to ZIP archives
Example: Reading and Processing
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');
Consumers still on the DataTable API can bridge in either direction with materializeToDataTable(source, pool) and dataTableToChunkSource(dataTable) — both materialize the full scene, so prefer staying on sources for large inputs.
Processing Actions
processSource / processSourceBridged (and the compat processDataTable) accept an array of actions:
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 and filterCluster require a GPU device — pass createDevice via the ProcessOptions argument. processSource streams and throws on actions that need the DataTable bridge (decimate, mortonOrder, the GPU voxel filters); processSourceBridged handles every action, materializing only those runs.
Custom Logging
Configure the logger for your environment:
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'