Releases: avala-ai/4dgs
Release list
fourdgs (Rust) 0.1.0
What's changed
The first release of the Rust crate, and the first cut from a tag. It is the decoder and the
production encoder, and it is what the C++ and Swift packages bind to: the C ABI in
include/fourdgs.h is part of this release, not a side effect of it.
fourdgs-cli, which installs the 4dgs tool, is not released here. It is unpublished for a reason
recorded in its manifest.
Fixed and Changed below describe behaviour that changed against the pre-release code in this
repository, which people do vendor from git — not against 0.0.1, which held the name on crates.io
and contained nothing.
Added
- Decoder: TLV container, streamed and indexed readers, both adaptive-precision rules, validity
windows, whole-degree spherical harmonic bands,deflateby default withzstdbehind a feature,
and the audio, camera, metadata, attachment, statistics and summary-offset records. include/fourdgs.h: a C ABI for decoding, and the surface the C++ and Swift packages bind to.
Nothing unwinds across it, every fallible call returns a status, and null is safe to pass.- Conformance runners in
rust/conformance, wired into the shared harness. - The production encoder: error-bounded quantization on the declared grids, the temporal chunk tree,
independent chunks, an index, and deterministic output. It verifies its own claim before returning
a file — every chunk is decoded back and every value checked against the bounds the Quantization
record is about to declare, so a file whose bounds have not been measured never reaches a caller. - C ABI: the rest of the file.
temporal_model, header attributes, metadata records, attachment
names/media types/bytes, camera and keyframes, statistics, summary offsets, a tri-state
summary CRC, a truncated flag, per-chunk load and per-chunk byte prediction, and_exopeners
that force the sequential or indexed path. Strings read from file bytes cross as (pointer,
length), never NUL-terminated, because the format'sstringmay legally contain a NUL. - Structural fuzzing over seeded mutations, covering both read paths and the C ABI, with a counting
allocator and a timer enforcing that no input causes an unbounded allocation or a hang. It found
two allocation bugs and an integer overflow on its first run. rust/encode-roundtrip.sh: the encoder's gate. Re-encodes every corpus variant and requires the
Rust and Python decoders to agree on the result, because an encoder checked only against its own
decoder proves nothing about the format.
Fixed
- A file cut between a chunk and its spherical harmonic band records was refused as malformed
instead of recovering the complete prefix. Bands are whole, so the short trailing chunks are
dropped and everything that arrived intact is kept. - Asking for fewer spherical harmonic bands than were already resident answered from the cache,
handing back a higher degree than requested and transferring nothing — which is exactly what a
band-skipping byte budget measures. - The front-matter probe read 64 KiB, which on a small file was the whole thing. It is 8 KiB now:
the records an indexed open must parse are a few hundred bytes, and everything else in the front
matter is stepped over rather than read.
Changed
- The streamed reader's retained summary run narrowed to Chunk Index, Statistics and Summary Offset,
matching the new spec §4.5. Attachments are no longer retained: their size is unbounded, and
admitting them would have made verifying a checksum cost whatever the payload weighed.
cargo add fourdgs@0.1.0 | crates.io | full changelog
fourdgs (Python) 0.1.0
What's changed
The first release of the Python reference implementation, and the first cut from a tag. It is what
the specification is checked against: where the two disagree, the conformance suite decides which
one is wrong.
Fixed and Changed below describe behaviour that changed against the pre-release code in this
repository, which people do vendor from git — not against 0.0.1, which held the name on PyPI and
contained nothing.
Added
- The reader. Every top-level structure is a length-prefixed record with an opcode, so an
unrecognized record is stepped over rather than fatal. Two read paths, neither an optimization of
the other:read()walks a file front to back in bounded blocks and works on a pipe or a
truncated file, andopen_indexed()reads the index and then only the byte ranges an instant
needs. - Gaussian state at a time
t: per-gaussian birth, velocity, temporal extent and validity window,
the two precision rules recomputed from the sigma bin, smallest-three rotations, the colour
transform, and spherical harmonic bands merged as whole degrees.state_at()is where decoding
ends — nothing here renders. - The writer,
write()withWriteOptions. It optimizes for a file that is easy to reason about
rather than for size or throughput, and verifies its own stated error bounds by decoding what it
wrote. WriteOptions.cutoff, so a file can declare a marginal threshold other than the default. It is
not decoration: the cutoff sets the support constant the per-gaussian velocity grid is derived
from, so encoder and decoder have to agree on it.WriteOptions.record_trailers, which appends bytes to a record's content the way a later minor
revision would add a field. Used by the conformance corpus to write a file that a reader must step
over rather than stop at.- Audio, a camera trajectory, metadata and attachments as front-matter records. On the indexed path
each costs exactly its own bytes to read, throughread_camera,read_metadataand
read_attachments; the streamed reader decodes spherical harmonic bands, verifies the Footer's
summary CRC and collects Summary Offset records. validate(), andfourdgs validateover it: structural validation where every finding names the
record, the field and what was expected. This is what makes a third-party encoder possible —
finding out why a file is wrong without reading this decoder.convert_ply_sequence(), andfourdgs convertover it: a directory of per-frame gaussian splat
.plyfiles becomes one continuous scene, each frame's gaussians taking that frame's slot as
their validity window and velocities fitted across the frames a gaussian appears in.fourdgs infoandfourdgs decode, thin enough over the library that anything the CLI can do a
caller can do.inforeports what seeking costs: the bytes needed to display an instant.- Errors that name the problem —
MalformedFile,TruncatedFile,UnsupportedCodec,
UnsupportedVersionandBoundViolation, all underFourdgsError— so a file that is malformed
is distinguishable from one that is merely newer. - Conformance runners under
python/conformance/, which decode the generated corpus and print the
canonical JSON the suite compares across SDKs.
Fixed
open_indexedraisedValueError— not aFourdgsError— on a footer whosesummary_start
points past the footer itself, sovalidatecould not catch it and a malformed file crashed the
tool meant to diagnose it. It is now aMalformedFilenaming both offsets.open_indexedcould not open a file whose front matter held a record larger than its 64 KiB
probe. An Audio record lives in the front matter, so any scene with a real soundtrack failed — on
the seekable path, on the format's flagship case. The walk now steps over a record by arithmetic
and fetches only what it wants.- A chunk's
compressionfield was parsed and then ignored, so a conforming chunk-compressed file
decoded to garbage instead of either working or failing. It is now honoured, and an unrecognized
codec is refused by name. - The velocity precision grid used the default cutoff rather than the file's own, so any file
declaring a different threshold decoded velocities the encoder did not write.state_athad the
same assumption in its visibility test. - A file whose trailing magic is missing is now reported as truncated rather than as complete.
Changed
- A window index outside the Window Table is refused rather than clamped. Clamping substituted
one gaussian's lifetime for another's in a file that was already corrupt, turning a detectable
fault into plausible wrong output. Files written by this encoder are unaffected; a reader that
relied on the old behaviour will now seeMalformedFile. - A file with no Window Table, or an empty one, reads as a single
(0, 0)window. That was already
the behaviour; it is now the documented one.
pip install fourdgs==0.1.0 | PyPI | full changelog