NanOxiGs is a training-free, pure-Rust implementation of NanoGS, a Gaussian-splat simplification method. It reduces an activated 3D Gaussian Splat set to a target count without rendering, optimization, learned models, or Python dependencies.
The supported pipeline is Morton-order KNN candidate generation, NanoGS Monte Carlo I-divergence merge cost, stable greedy pair selection, and mass-preserving moment matching (MPMM).
use nanoxigs::core::{GaussianSplat, GaussianSplatView, SimplificationConfig};
use nanoxigs::pipeline::{DefaultPipelineScratch, Simplifier};
let view = GaussianSplatView::new(
&[0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
&[0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
&[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
&[0.5, 0.5],
&[],
0,
)?;
let config = SimplificationConfig {
ratio: 0.5,
..SimplificationConfig::default()
};
let mut scratch = DefaultPipelineScratch::new();
let mut output = GaussianSplat::default();
let mut simplifier = Simplifier::default();
simplifier.simplify(&view, &config, &mut scratch, &mut output)?;
# Ok::<(), nanoxigs::core::Error>(())Inputs must be activated: scales are linear and positive, opacities are in [0, 1], and rotations are unit quaternions in [w, x, y, z] order. Appearance features are optional, packed as N * C contiguous f32 values.
Simplifier::default() uses NanoGS's default geometric and appearance weights (1.0 each). Reuse the same Simplifier and DefaultPipelineScratch across calls to retain allocations. To tune those weights, construct Simplifier with strategies::NanoGsObjective::new(NanoGsConfig { lam_geo, lam_app }), MpmmOperator, and StableGreedySelector.
The default is a complete NanoGS pipeline, but the Rust API is configurable. Simplifier<Topology, Model, Selector> accepts implementations of:
CandidateTopologyto generate candidate merge pairs.MergeObjectiveto score candidate pairs.SplatOperatorto fuse selected pairs.PairSelectorto choose disjoint pairs.
Combine a compatible objective and operator with ModelAdapter<Objective, Operator>, then create matching reusable storage with PipelineScratch<Topology, Model, Selector>. The default composition is MortonTopology + NanoGsObjective + MpmmOperator + StableGreedySelector.
NanOxiGs was evaluated on the LEGO scene at keep ratios 0.1, 0.01, and 0.001 against the NanoGS reference implementation. Both methods produced the same splat count at each ratio. The table reports rendered-image quality; delta is NanOxiGs minus the reference.
| Keep ratio | Output splats | NanOxiGs time | Reference time | Speedup | NanOxiGs PSNR | Delta PSNR | NanOxiGs SSIM | Delta SSIM |
|---|---|---|---|---|---|---|---|---|
0.1 |
20,507 | 1.37 s | 14.78 s | 10.8x | 31.081 dB | -0.009 dB | 0.954357 | -0.000186 |
0.01 |
2,051 | 1.40 s | 16.44 s | 11.8x | 26.908 dB | +0.080 dB | 0.916788 | +0.000921 |
0.001 |
206 | 2.13 s | 37.49 s | 17.6x | 23.215 dB | -0.247 dB | 0.870135 | -0.003772 |
NanOxiGs simplified this scene 10.8x to 17.6x faster while remaining close to the reference's rendered-image quality. These results are specific to this evaluation and are not a guarantee for every scene or renderer configuration.
The optional CLI reads and writes standard 3DGS PLY files:
cargo run --release --features cli -- input.ply --ratio 0.3| Flag | Default | Description |
|---|---|---|
-r, --ratio |
0.5 |
Fraction of splats to keep |
-o, --output |
derived | Output PLY path |
--opacity-threshold |
0.1 |
Opacity pruning floor |
--lam-geo |
1.0 |
NanoGS geometric-cost weight |
--lam-app |
1.0 |
Appearance-distance weight |
cli: builds the native PLY CLI and enablesparallel.parallel: enables Rayon parallelism for native edge scoring. Leave it off for Wasm.
Apache-2.0.