OpenUSD file-format plugins that import
3D Gaussian Splatting
assets as standard USD stages: open a trained .ply, a Niantic .spz, or a
PlayCanvas .sog capture directly in usdview or any USD pipeline as OpenUSD
26.05's ParticleField3DGaussianSplat schema.
A Gaussian PLY imported by this plugin and displayed in usdview by a Hydra renderer that supports the OpenUSD particle-field Gaussian schema.
These previews show the three supported input formats displayed through the
OpenUSD hdParticleField example delegate:
| PLY | SOG | SPZ |
|---|---|---|
![]() |
![]() |
![]() |
What it does
- Read-only import of Graphdeco-style Gaussian PLY (ASCII and binary
little-endian, SH degrees 0-3) into
/Asset/Splatwith positions, scales, orientations, opacities, and spherical-harmonic radiance. - Read-only import of Niantic SPZ (container versions 1-3, SH degrees 0-3),
dequantized and converted into the same
/Asset/Splatstage. - Read-only import of PlayCanvas SOG v2 (SH degrees 0-3) in both layouts — the
bundled
.sogZIP archive and an unbundledmeta.jsonwith its companion lossless-WebP property planes — decoded from codebooks and image planes into the same stage. All three formats author the identical hierarchy, schema, and metadata through one shared writer. - Header-only metadata reads (~5 ms at any size), PLY import arguments
(
shDegree,opacityThreshold,scaleMultiplier), and stableGSPLY-****/GSPZ-****/GSSOG-****diagnostics with machine-readable catalogs. - Import only — rendering is owned by the sibling project
hydra-merlin.
What it reads
gaussian-ply — Graphdeco-style .ply:
| Exporter | Status |
|---|---|
| Graphdeco reference (INRIA) | ✅ verified (Mip-NeRF 360 garden, 5.8M Gaussians) |
| Brush | ✅ verified (committed CC0 corpus) |
| Jawset Postshot | ✅ verified (up to 1.9M Gaussians) |
| SuperSplat uncompressed export | ☑ layout-compatible, fixture-covered |
SuperSplat compressed .ply, .splat, .ksplat |
❌ rejected explicitly (details) |
gaussian-spz — Niantic .spz:
| Container | Status |
|---|---|
| SPZ versions 1-3 (gzip) | ✅ decoded, fixture-covered, and verified against a committed CC0 real-asset corpus |
| SPZ version 4 (ZSTD) | ❌ rejected with a specific unsupported-version diagnostic |
gaussian-sog — PlayCanvas .sog / meta.json:
| Container | Status |
|---|---|
SOG v2, bundled .sog (ZIP) |
✅ decoded, fixture-covered, and verified against a committed CC0 real-asset corpus |
SOG v2, unbundled meta.json + .webp planes |
✅ decoded through the asset resolver, fixture-covered |
SOG v1 (per-channel mins/maxs, no version) |
❌ rejected with a specific unsupported-version diagnostic |
Streamed SOG (lod-meta.json, LOD chunks) |
❌ not read; a later SOG milestone |
| Lossy WebP property planes | ❌ rejected rather than decoded approximately |
Full tables: dialect compatibility · capability matrix · performance baselines.
For the shortest package-consumer path, choose the v0.5.1 product archive that
matches the host platform, the cy2026 OpenUSD runtime, and Python 3.13:
usd-3dgs-plugins-0.5.1-cy2026-windows-x86_64-py313-usd-plugin-product.tar.zst
usd-3dgs-plugins-0.5.1-cy2026-macos-arm64-py313-usd-plugin-product.tar.zst
usd-3dgs-plugins-0.5.1-cy2026-linux-x86_64-py313-usd-plugin-product.tar.zst
Extract the target archive, then point PXR_PLUGINPATH_NAME at the extracted
plugin/resources/gaussian-ply, gaussian-spz, and gaussian-sog directories.
Use ; between paths on Windows and : on macOS/Linux; keep the extracted
lib directory on the platform library path. Open one file from each format
with usdcat to check plugin discovery:
$package = "C:\path\to\extracted"
$env:PXR_PLUGINPATH_NAME = "$package\plugin\resources\gaussian-ply;$package\plugin\resources\gaussian-spz;$package\plugin\resources\gaussian-sog"
$env:Path = "$package\lib;$env:Path"
usdcat --flatten --out scene-ply.usda scene.ply
usdcat --flatten --out scene-spz.usda scene.spz
usdcat --flatten --out scene-sog.usda scene.sogThe exact extraction layout can vary between the aggregate product and a
standalone member package; use the corresponding member root for each resource
directory. The detailed activation steps, checksum guidance, and the
unbundled SOG example are in INSTALL.md. Stock
usdview can open the stage and inspect /Asset/Splat, but visible splats
still require a Gaussian-capable Hydra delegate.
Requirements: OpenUSD >=26.05,<27.0 and a C++17 compiler. Build and test
with plain CMake against an OpenUSD installation in that range:
cmake --preset default -DCMAKE_PREFIX_PATH=/path/to/openusd
cmake --build --preset default
ctest --test-dir build/default --output-on-failureThe repo is dual-mode: with
OpenStrata ost 0.22.10 the
same tree gets the full verification ladder, packaging, and viewer tooling —
see BUILDING.md:
ost runtime pull cy2026 --profile usd
ost plugin build plugins/gaussian-ply
ost plugin test plugins/gaussian-ply --up-to 5Open a capture in usdview:
ost plugin view plugins\gaussian-ply "C:\path\to\scene.ply"Seeing the splats needs a Gaussian-capable Hydra renderer. These plugins import; they do not render. Stock
usdviewopens the stage and shows the/Asset/Splathierarchy and its attributes, but draws nothing, because no default Hydra delegate understandsParticleField3DGaussianSplat. For a visual preview today, use the OpenUSDhdParticleFieldexample delegate — that is what the animation above shows. Production rendering is the job of the sibling projecthydra-merlin.
Or convert it to a compact binary USD file:
ost plugin run plugins\gaussian-ply -- usdcat --flatten --skipSourceFileComment --usdFormat usdc --out scene.usd scene.plyInstalling a packaged release into an existing OpenUSD environment is covered in INSTALL.md.
v0.5.1 — release polish and hostile-input hardening — is released. (release record).
v0.4.0 turned the decoder-to-USD seam PLY and SPZ share into a normative,
enforced contract: shared semantic validation and overflow-checked size math, a
stage-free decoder test kit, an
import-statistics seam, and a documented
header/API boundary. It also corrected
authored orientation to RUB / Y-up
(ADR 0001) to match the upAxis every
stage already declared; that is a pre-1.0 change to v0.1.0-v0.3.0 output, so
re-import to update.
v0.5.0 is the first format added on top of that contract: gaussian-sog
reads SOG v2 in both layouts, targets the shared model with no format-specific
USD authoring, and joins the cross-format equivalence triples. Releases are
tag-driven and digest-reproducible
(release records).
.ply -> PlyReader (tinyPLY adapter) -> GaussianPlyDecoder --+
.spz -> SpzReader (miniz DEFLATE/gzip) -> GaussianSpzDecoder --+
.sog \ |
-> SogReader (miniz ZIP + libwebp -> GaussianSogDecoder --+
meta.json/ lossless property planes) |
v
GaussianCloudData (gaussianCore; no USD types)
-> GaussianLayerWriter (libs/gaussian-usd)
-> UsdVolParticleField3DGaussianSplat
The workspace separates format-independent Gaussian modelling
(libs/gaussian-core) and shared USD authoring (libs/gaussian-usd) from
format-specific import (plugins/gaussian-ply, plugins/gaussian-spz,
plugins/gaussian-sog), each independently buildable and testable. It is
built, tested, packaged, and released with OpenStrata's ost CLI
(measured usage: dogfooding reports) and remains
dual-mode with plain CMake. The sibling project
usd-vrm-plugins shares
this layout and process. Policy: DESIGN_POLICY.md.
The minimal development path is in CONTRIBUTING.md; the documentation index is docs/README.md. The normative mapping contracts are PLY_MAPPING.md, SPZ_MAPPING.md, and SOG_MAPPING.md.
Project code is Apache-2.0. SPZ and SOG are implemented from their publishers'
open specifications and MIT-licensed reference toolchains rather than vendored;
only container mechanics use libraries. Third-party retained notices and fixed
source revisions (tinyPLY, miniz, libwebp) are documented in
THIRD_PARTY_NOTICES.md.



