ExCodecs.Spatial.Codec.Gsplat (ex_codecs v0.2.1)

Copy Markdown View Source

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 × record

Each 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

decode(data, opts \\ [])

@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

encode(data, opts \\ [])

@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} where payload is a GSPL binary().
  • {:error, %ExCodecs.Error{reason: :invalid_data, codec: :gsplat}} when data is 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

stream_decode(data, opts \\ [])

@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()