SplatTransform

repository·main·Indexed 22 days ago

https://github.com/playcanvas/splat-transform

An open-source library and CLI tool for converting, editing, and optimizing 3D Gaussian Splatting data. It supports a wide variety of input/output formats (including .ply, .sog, .spz, and .glb), and provides tools for decimation, filtering, LOD generation, and voxelization for collision detection. It also includes a GPU rasterizer for rendering WebP images from splat data.

Tokens
11.5K
Snippets
14
Records
105
Agent score
78%

What's inside @playcanvas/splat-transform

  1. Handling Antialiased and 2DGS Scenes

    main

    SplatTransform preserves tags for scenes trained with antialiasing or as 2DGS (2D Gaussian Splatting) where the output format supports it.

    Detection (On Read):

    • PLY: Uses header comments (e.g., SplatRenderMode: default | mip | 2dgs or antialiased 0 | 1).
    • SPZ: Uses an antialiased header bit.
    • SOG: Uses the "model" entry in meta.json.
    • 2DGS Detection: A PLY with scale_0/scale_1 but no scale_2 is automatically read as 2DGS.

    Preservation (On Write):

    • .ply / .compressed.ply: Carries comment SplatRenderMode: mip | 2dgs.
    • .sog / meta.json: Carries "model": "antialiased" | "2dgs".
    • .spz: Sets its antialiased bit (Note: cannot represent 2DGS and will warn).
    • Other formats: Tags are dropped silently.

    Note: Combining inputs with different models will trigger a warning and the result will be written untagged.

  2. Compare uniform and adaptive decimation methods

    main

    The project provides two distinct decimation strategies for reducing Gaussian Splat size. The choice depends on your scene content:

    • Uniform Decimation (--decimate-uniform / decimateSourceUniform()): Uses KL-style pairwise cost with a full-SH colour term. It performs a uniform 50% matching per level, meaning every region loses the same fraction of Gaussians. It has lower memory requirements and is better for scenes with uniformly-sized Gaussians, such as uniform textures, single objects, or snow.
    • Adaptive Decimation (--decimate / decimateSource()): Uses field-L2 cost with a scale-free colour term and re-costed selection. Removal follows local error, allowing redundant regions to collapse deeper than distinct ones. It is superior for mixed-scale content and skies, but has a higher memory cost.
  3. Generate voxel collision meshes

    main

    The voxel format stores sparse voxel octree data for collision detection, consisting of .voxel.json (metadata) and .voxel.bin (binary data). You can also emit a .collision.glb mesh using the --collision-mesh flag.

    Interior scenes (rooms, indoor scans): Use --voxel-external-fill to seal the void and --voxel-carve to hollow out the navigable space. A --seed-pos (walkable point) is required.

    splat-transform room.ply --filter-cluster --seed-pos 0,1,0 --voxel-external-fill --voxel-carve --collision-mesh room.voxel.json

    Exterior scenes (outdoor objects, terrain): Use --voxel-floor-fill to fill the ground beneath surfaces.

    splat-transform terrain.ply --filter-cluster --seed-pos 0,0,0 --voxel-floor-fill --collision-mesh terrain.voxel.json
    # Voxelize with custom resolution and opacity threshold
    splat-transform --voxel-size 0.1 --voxel-opacity 0.3 input.ply output.voxel.json
    
    # Custom carve capsule (height, radius)
    splat-transform --seed-pos 1,0,0 --voxel-carve 2.0,0.3 input.ply output.voxel.json
    
    # Watertight voxel-face collision mesh
    splat-transform --collision-mesh faces input.ply output.voxel.json
  4. Render splat scenes to images

    main

    Render a splat scene to a lossless WebP image using GPU acceleration. Supports custom camera positioning, field of view, resolution, and advanced effects like defocus blur and motion blur.

    Key Options:

    • --camera-pos <x,y,z> / --camera-target <x,y,z>: Set camera view.
    • --resolution <WxH>: Set output resolution.
    • --background <r,g,b,a>: Set background color.
    • --f-stop <n>: Enable defocus blur.
    • --projection <equirect|perspective>: Set projection type (e.g., equirect for panoramas).
    • --motion-samples <n> / --shutter <n>: Enable camera motion blur.
  5. Perform basic format conversions with splat-transform CLI

    main

    Use the splat-transform CLI to convert between various Gaussian splat formats including .ply, .splat, .ksplat, and the SOG bundled/unbundled formats. The tool also supports converting to compressed PLY and standalone HTML viewers.

    Common conversion tasks:

    • Standard formats: Convert between .ply, .splat, and .ksplat.
    • Compression: Convert .ply to compressed .ply or uncompress it back.
    • SOG format: Convert to SOG bundled (.sog) or unbundled (meta.json folder) formats, and back to .ply.
    • HTML Viewers: Generate a single-file HTML viewer or an unbundled version with separate assets.
    # Simple format conversion
    splat-transform input.ply output.csv
    
    # Convert from .splat format
    splat-transform input.splat output.ply
    
    # Convert to compressed PLY
    splat-transform input.ply output.compressed.ply
    
    # Convert to SOG bundled format
    splat-transform input.ply output.sog
    
    # Convert to standalone HTML viewer (bundled, single file)
    splat-transform input.ply output.html
    
    # Convert to unbundled HTML viewer (separate CSS, JS, and SOG files)
    splat-transform --unbundled input.ply output.html
  6. Use the SplatTransform CLI

    main

    The CLI follows a specific pattern where input files form a working set, actions are applied in order, and the last file specified is the output. Actions can be placed after any input or output file.

    Command Syntax:

    splat-transform [GLOBAL] input [ACTIONS] ... output [ACTIONS]

    Key Usage Rules:

    • Input files: Become the working set.
    • Actions: Applied in the order they appear.
    • Output file: The last file in the command is the output. Actions appearing after the output file modify the final result.
    • Discarding output: Use null as the output filename if you want to discard the file (useful when using --stats for analysis only).
    splat-transform [GLOBAL] input [ACTIONS]  ...  output [ACTIONS]
  7. Generate statistics for splat data

    main

    Generate per-column statistics (min, max, median, mean, stdDev, nanCount, infCount, and histograms) for data analysis or automated quality gating. The fillRatio metric is particularly useful for detecting degenerate scenes that might overwhelm a GPU.

    Use --stats with the following targets:

    • <filename>: Print stats and write the processed file.
    • null: Print stats only (discard output).
    • json: Print stats in JSON format for scripting.
    # Print stats, then write output
    splat-transform input.ply --stats output.ply
    
    # Print stats without writing a file (discard output)
    splat-transform input.ply --stats null
    
    # Print stats as JSON for scripting
    splat-transform input.ply --stats json null
  8. Verify decimation parity with tools/decimate-parity.mjs

    main

    If you are modifying the uniform decimation logic and need to ensure it remains bit-for-bit compatible with the reference binary, use the tools/decimate-parity.mjs tool. This tool chains halvings through a reference binary and the current implementation, compares them byte-for-byte, and reports PSNR. It will exit with a non-zero code if any byte mismatch is found.

    To run parity checks on specific scenes:

    node tools/decimate-parity.mjs sky --ref splat-transform
    node tools/decimate-parity.mjs snow --ref splat-transform
  9. Install SplatTransform CLI or Library

    main

    You can install SplatTransform as a global CLI tool for command-line conversions, or as a dependency for programmatic use in Node.js or browser environments.

    To install the CLI globally:

    npm install -g @playcanvas/splat-transform

    To install as a library dependency:

    npm install @playcanvas/splat-transform
  10. Apply transformations and filters via CLI

    main

    You can modify the geometry and content of a splat scene using transformations (scale, translate, rotate) and filters (NaN removal, opacity filtering, harmonic stripping, or decimation).

    Transformations:

    • -s <value>: Scale.
    • -t <x,y,z>: Translate.
    • -r <x,y,z>: Rotate (degrees).

    Filtering:

    • --filter-nan: Removes entries containing NaN or Inf.
    • -V <column>,<op>,<value>: Filter by value (e.g., opacity,gt,0.5).
    • --filter-harmonics <n>: Strips spherical harmonic bands higher than n.
    • --decimate <count|percentage>: Simplifies the scene (e.g., 50000 or 25%).
    # Scale and translate
    splat-transform bunny.ply -s 0.5 -t 0,0,10 bunny_scaled.ply
    
    # Rotate by 90 degrees around Y axis
    splat-transform input.ply -r 0,90,0 output.ply
    
    # Filter by opacity values (keep only splats with opacity > 0.5)
    splat-transform input.ply -V opacity,gt,0.5 output.ply
    
    # Simplify to 25% of original splat count
    splat-transform input.ply -d 25% output.ply
  11. Configure SOG compression settings

    main

    When writing .sog, meta.json, lod-meta.json, or .html outputs, you can tune the Spherical Harmonics (SH) compression and parallelism using these options:

    • -i, --sh-iterations <n>: Number of iterations for SH compression. Higher values improve quality. Default is 10.
    • --max-workers <n>: Number of worker threads for SOG encoding. Setting this to 0 runs the process inline/serially. Default is 4.
  12. Configure Voxel output for collision detection

    main

    When writing .voxel.json (a sparse voxel octree for collision detection), use these options to tune the voxelization and volume filling:

    • --voxel-size <n>: Voxel size. Default is 0.05.
    • --voxel-opacity <n>: Voxel opacity threshold. Default is 0.1.
    • --voxel-external-fill [size]: Seals exterior voxels via boundary flood fill (useful for interior scenes). [size] is the dilation distance. Default size is 1.6.
    • --voxel-floor-fill [size]: Fills columns upward from the bottom until hitting solid geometry (useful for exterior scenes). [size] limits the XZ area patched. Default size is 1.6.
    • --voxel-carve [h,r]: Carves navigable space using capsule flood fill from a seed. Default is height=1.6, radius=0.2.
    • --seed-pos <x,y,z>: Seed position for voxel fill/carve and --filter-cluster. Default is 0,0,0.
    • --collision-mesh [smooth|faces]: Generates a .collision.glb mesh. Default is smooth.