"The int_hyper of 3D" — extends conformance-is-a-hash to the last missing modality.
A Gaussian splat is N Gaussians × 14 attributes (pos[3], scale[3], rot[4], color[3],
opacity); the SOTA splat codecs (SOG / self-organizing Gaussians) decode through a
FLOAT network, so the reconstructed cloud — and its hash — drift between machines.
Here the synthesis is integer (the int_hyper machinery, 14 channels instead of RGB's
3) over a per-channel factorized-rANS latent, all i64 — so the decoded attribute
tensor is byte-identical on every machine (NeuralIntegerExact; splat-equivalence, a
portable cloud hash). The float rasterizer stays sink-supplied presentation; the
attributes are the conformance contract.
- src/int_splat.rs (feature splat_int = ["neural_int"]): factorized rANS-decode the
per-channel latent (y_q = s·2^afrac + median_q) → integer synthesis g_s (reuses
int_hyper_synth run_net) → [14,S,S] attribute tensor → round-half-up u8. Pure i64,
wasm-ready, self-contained b64.
- tools/wai_int_splat_export.py: a synthetic structured Gaussian cloud → Morton-sorted
[14,S,S] attribute image → learned transform codec (Conv2d+GDN / ConvTranspose2d+
IGDN) → PTQ g_s to WHM1 → integer reference decode mirroring the Rust → attr hash.
Reuses the int_hyper 2D integer ops + the world tool's WHM1/PTQ helpers.
- capability wai.splat.int_codec registered (Lossy tier, NeuralIntegerExact; nie set
now {int_synth, int_hyper, video.int_hyper, audio.int_codec, splat.int_codec}).
SPEC row added.
- tests/int_splat.rs never-skips: the committed tiny vector (1024 gaussians × 14
attrs) decodes to the committed attr_hash 5a94ebc9f0399a35. Rust == Python.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
18 lines
933 B
Rust
18 lines
933 B
Rust
//! Decode a learned-splat dir (`splat_gs.bin` + `splat.json`, from
|
||
//! `tools/wai_int_splat_export.py`) → the integer attribute tensor; print the FNV-1a
|
||
//! attribute hash. Proves the Rust integer decode reproduces the Python integer
|
||
//! reference byte-for-byte (splat-equivalence).
|
||
//!
|
||
//! cargo run --release --example int_splat_decode --features splat_int -- <dir>
|
||
|
||
use wai::int_hyper_synth::IntModel;
|
||
use wai::int_splat::decode;
|
||
|
||
fn main() {
|
||
let dir = std::env::args().nth(1).expect("usage: int_splat_decode <dir>");
|
||
let gs = IntModel::from_bytes(&std::fs::read(format!("{dir}/splat_gs.bin")).unwrap()).unwrap();
|
||
let bs: serde_json::Value =
|
||
serde_json::from_slice(&std::fs::read(format!("{dir}/splat.json")).unwrap()).unwrap();
|
||
let clip = decode(&gs, &bs).expect("decode");
|
||
println!("{} gaussians × {} attrs ({}²) attr_hash {:016x}", clip.s * clip.s, clip.n_attr, clip.s, clip.attr_hash());
|
||
}
|