Simple little-endian binary format for Gaussian splat clouds.
Layout
magic: "GSPL" (4 bytes)
version: u16 LE = 1
flags: u16 LE (bit0 = has SH rest coeffs count in header)
count: u64 LE
sh_rest: u16 LE (number of f_rest floats per Gaussian; 0 if none)
records: count × recordEach record:
position: 3 × f32
color: 3 × f32 (f_dc)
opacity: f32
scale: 3 × f32
rotation: 4 × f32 (w, x, y, z)
sh_rest: sh_rest × f32 (optional)
Summary
Functions
Decodes a GSPL version 1 payload into a Gaussian cloud.
Encodes a Gaussian cloud in the GSPL version 1 binary format.
Returns an enumerable over Gaussians in a GSPL payload.
Functions
@spec decode( binary(), keyword() ) :: {:ok, ExCodecs.Spatial.GaussianCloud.t()} | {:error, ExCodecs.Error.t()}
Decodes a GSPL version 1 payload into a Gaussian cloud.
The decoder reads the header and declared record count described by
encode/2. When the shared SH-rest count is nonzero, each decoded
Gaussian's sh is [[r, g, b] | Enum.chunk_every(rest, 3)]; otherwise it
is nil. Trailing bytes and unknown flag bits are currently ignored.
Decoded cloud metadata contains %{"format" => "gsplat", "version" => 1}.
Arguments
data(binary()) — a complete GSPL payload.opts(keyword()) — reserved and currently ignored.
Returns
{:ok, %GaussianCloud{}}{:error, %ExCodecs.Error{reason: :invalid_data, codec: :gsplat}}when the magic/header is invalid or too short, the version is not 1, a declared 14-float record is truncated, or its declared SH-rest values are truncated.
Raises / exceptions
The external payload failures above are returned. opts is ignored, and
non-binary input is handled by the catch-all clause as :invalid_data; this
function does not intentionally raise for external payloads.
Examples
iex> alias ExCodecs.Spatial.{Gaussian, GaussianCloud}
iex> {:ok, bin} = ExCodecs.Spatial.Codec.Gsplat.encode(GaussianCloud.new([Gaussian.new({1.0, 0.0, 0.0})]))
iex> {:ok, %GaussianCloud{gaussians: [g]}} = ExCodecs.Spatial.Codec.Gsplat.decode(bin)
iex> elem(g.position, 0)
1.0
@spec encode( ExCodecs.Spatial.GaussianCloud.t(), keyword() ) :: {:ok, binary()} | {:error, ExCodecs.Error.t()}
Encodes a Gaussian cloud in the GSPL version 1 binary format.
The 18-byte header contains "GSPL", version u16 little-endian, flags
u16 little-endian, Gaussian count u64 little-endian, and a shared
spherical-harmonic-rest count u16 little-endian. Each record contains 14
little-endian f32 values: position XYZ, DC color RGB, opacity, scale XYZ,
and quaternion rotation (w, x, y, z), followed by the shared number of
little-endian f32 SH-rest values.
The shared SH count is the longest flattened rest coefficient list in the
cloud; shorter lists are padded with zero. The DC coefficient is represented
by Gaussian.color. Gaussian metadata and cloud-level metadata are not
stored.
Arguments
data(GaussianCloud.t()) — a cloud of valid%Gaussian{}structs. Each Gaussian has position/color/scale 3-tuples, a rotation 4-tuple, numeric opacity, and optional SH data shaped as[dc | rest](nested rest lists are flattened).opts(keyword()) — reserved and currently ignored.
Returns
{:ok, payload}wherepayloadis a GSPLbinary().{:error, %ExCodecs.Error{reason: :invalid_data, codec: :gsplat}}whendatais not a%GaussianCloud{}.
Raises / exceptions
A wrong top-level type is returned as :invalid_data, and opts is ignored.
Manually malformed cloud/Gaussian structs can raise FunctionClauseError,
MatchError, ArgumentError, ArithmeticError, or a bitstring construction
exception for invalid SH shapes, tuple shapes, counts, or non-numeric values.
Examples
iex> alias ExCodecs.Spatial.{Gaussian, GaussianCloud}
iex> cloud = GaussianCloud.new([Gaussian.new({0, 0, 0}, opacity: 0.75)])
iex> {:ok, <<"GSPL", 1::little-16, _flags::little-16, 1::little-64,
...> 0::little-16, _record::binary>>} =
...> ExCodecs.Spatial.Codec.Gsplat.encode(cloud)
iex> true
true
@spec stream_decode( binary(), keyword() ) :: Enumerable.t()
Returns an enumerable over Gaussians in a GSPL payload.
Arguments
data(binary()) — a complete GSPL payload.opts(keyword()) — reserved and currently ignored.
Returns
An Enumerable.t() that yields decoded %Gaussian{} structs after the
complete cloud has been materialized. If decode/2 fails, it yields exactly
one {:error, %ExCodecs.Error{reason: :invalid_data, codec: :gsplat}}
element.
Raises / exceptions
Raises FunctionClauseError when data is not a binary because this public
function is guarded. opts is ignored. Binary validation failures are
delayed as the single error element rather than raised.
Examples
iex> alias ExCodecs.Spatial.{Gaussian, GaussianCloud}
iex> {:ok, bin} = ExCodecs.Spatial.Codec.Gsplat.encode(GaussianCloud.new([Gaussian.new({0, 0, 0})]))
iex> [%Gaussian{opacity: 1.0}] =
...> ExCodecs.Spatial.Codec.Gsplat.stream_decode(bin) |> Enum.to_list()