Skip to content

Add native .spz Gaussian Splat format support#39

Open
Enndee wants to merge 1 commit intohyperlogic:mainfrom
Enndee:feature/spz-format-support
Open

Add native .spz Gaussian Splat format support#39
Enndee wants to merge 1 commit intohyperlogic:mainfrom
Enndee:feature/spz-format-support

Conversation

@Enndee
Copy link

@Enndee Enndee commented Mar 7, 2026

Add native .spz file loading support

Summary

This PR adds native loading support for the .spz Gaussian Splat format — Niantic's open, compressed binary format for 3D Gaussian Splatting scenes. .spz files are typically ~10× smaller than equivalent .ply files, making them significantly faster to distribute and load.

Motivation

The PLY format used by splatapult is large and uncompressed. For scenes captured with tools such as SHARP, 3DGS, or Gaussian Opacity Fields, the resulting PLY files can be tens to hundreds of MB. The .spz format provides:

  • ~10× compression vs PLY (e.g. a 5.4 KB test file becomes 0.4 KB)
  • MIT-licensed open format with a clean C++ reference implementation
  • Single new dependency: zlib (already present in the vcpkg graph via libpng in most builds)
  • Lossless for all Gaussian attributes: positions, scales, rotations, opacity, DC color, and full SH up to degree 3

Implementation

New dependency: nianticlabs/spz

The PR integrates nianticlabs/spz (MIT license) as a git submodule at third_party/spz. Only three .cc source files are compiled directly into the splatapult executable (load-spz.cc, splat-types.cc, splat-c-types.cc). No separate static/shared library is needed.

Files changed

File Change
.gitmodules Add third_party/spz submodule pointing to nianticlabs/spz
vcpkg.json Add zlib dependency
CMakeLists.txt Find ZLIB, add SPZ source files and include dir, link ZLIB
src/gaussiancloud.h Declare ImportSpz()
src/gaussiancloud.cpp Implement ImportSpz()
src/app.cpp Route .spz extension to ImportSpz(), .ply to ImportPly()

GaussianCloud::ImportSpz() details

  • Uses spz::loadSpz(filename, UnpackOptions) with CoordinateSystem::UNSPECIFIED
    (preserves PLY coordinate space — coordinates are stored as-is by converters such as 3dgsconverter)
  • Supports both BaseGaussianData (SH degree 0) and FullGaussianData (SH degree 3)
  • Handles quaternion reorder: spz stores [x, y, z, w]; splatapult uses [w, x, y, z]
  • Scales are stored as log-scale in spz, same as PLY — expf() applied identically
  • SH coefficient layout mapping: spz uses [coeff, channel] inner ordering; remapped to splatapult's r_sh0/g_sh0/b_sh0 ... r_sh3/g_sh3/b_sh3 layout

File-extension routing in app.cpp

The internal variable plyFilename now accepts any supported extension. A simple case-insensitive extension check dispatches to ImportSpz or ImportPly. All other logic (file watcher, hot-reload, etc.) is unchanged.

How to test

  1. Add the submodule and apply the patch (see HOW_TO_SUBMIT.md in the PR package)
  2. Build with cmake + your generator as usual
  3. Convert any .ply scene file to .spz using 3dgsconverter:
    3dgsconverter -i scene.ply -f spz --force
    
  4. Launch splatapult with the .spz file:
    splatapult.exe scene.spz
    

Backward compatibility

Fully backward-compatible. Existing .ply workflows are completely unaffected. The routing in app.cpp falls through to ImportPly() for any non-.spz extension.

Dependencies

  • zlib — only new vcpkg dependency; very widely available and already present in most builds via libpng
  • nianticlabs/spz — MIT license, C++ only, no GPU/graphics dependencies

Related

Integrates nianticlabs/spz (MIT) as a submodule at third_party/spz.
Adds GaussianCloud::ImportSpz() and routes .spz extension in app.cpp.
Only new vcpkg dependency: zlib (already present in most builds via libpng).
~10x size reduction vs equivalent PLY files.

- CMakeLists.txt: find ZLIB, add SPZ source files and include dir
- vcpkg.json: add zlib dependency
- src/gaussiancloud.h: declare ImportSpz()
- src/gaussiancloud.cpp: implement ImportSpz() with full SH support
- src/app.cpp: route .spz to ImportSpz(), .ply to ImportPly()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant