acron.sog¶
Gaussian-splat bundles: SOG v2 — “Spatially Ordered Gaussians”, the
compressed format written by PlayCanvas’s splat-transform tool and served
by the splat hosts built on it — read as they are, and the 3DGS .ply a
trainer writes, packed into the same shape on load. SogBundle is the
package’s splat representation whatever the source; read_splats()
picks the reader by extension.
A .sog is a stored ZIP of a meta.json and webp images (“planes”), or
the same files in a directory. Every plane is one W×H image with splat i
at texel (i % W, i // W), rows counted from the TOP of the image; the
splats are Morton-ordered, so the first k of them are a spatial chunk,
not a sample (SogBundle.decimate() gives a sample).
The planes, all RGBA8 (v2):
means_l/means_u— low and high bytes of a 16-bit position per axis, linear in a log-transformed spacesign(x)·log(1+|x|)betweenmeta.means.mins/maxs.quats— “smallest three”: the largest-magnitude component of the unit quaternion is dropped,acarries252 + its indexin wxyz order andrgbthe other three as(v/√2 + 0.5)·255.scales— three indices intometa.scales.codebook(log scales).sh0— three indices intometa.sh0.codebook(the DC spherical-harmonic term; colour is0.5 + c·SH_C0) and the opacity ina.shN_labels/shN_centroids— a 64K-entry k-means palette of the higher SH bands (view-dependent colour): a 16-bit label per splat into a centroid image of 64 entries per row, each entrycoeffstexels of codebook indices (one per colour channel). Read withwith_sh=True;acron.splatsevaluates them per update. (A bundle built from a PLY has no k-means palette: every splat is its own entry, the label is 24-bit and the palette row holds as many entries as a texture row fits —SogBundle.sh_entries_per_row; the shader reads both layouts.)
No numpy. The array work is native: acron.gsplat.GSplatBundle
(C++, acron/src/gsplat) reads the .sog (Acron’s ZipArchive + a
built-in lossless-webp codec — Acron and the engine’s thirdparty set have no
webp, so the module carries a dependency-free VP8L decoder/encoder) and the
.ply, packs arrays into planes, decodes them on the CPU and writes both
formats. A C++ game uses that class directly; this module is its Python face.
The planes stay in Acron arrays and go to the GPU as they are
(acron.splats decodes them in GLSL); Python sees them through
read-only memoryviews over the native storage (CPTA_uchar: no copy, and
no way to resize or overwrite what the native decode reads). SogBundle.positions(),
quaternions(), scales(),
colors() and sh_coefficients() are the CPU
decode — for sorting, tests and tools — and return a SplatArray: a
float32 buffer with a shape (a memoryview over the native array; with numpy,
np.asarray(a) / np.frombuffer(a.data, np.float32) wraps it without a
copy). The array arguments of the encoders take a SplatArray, any
buffer (array('f'), a numpy array) or nested sequences.
|
A splat bundle: the native |
|
A float32 array with a shape, over a native buffer — what the CPU decode returns. |
Global Functions
- bundle_from_arrays(positions, quaternions, scales, colors, sh=None, *, name: str = 'arrays', palette: str = 'auto') SogBundle¶
A bundle in memory from plain arrays — the encoder’s first half, the inverse of the decode.
quaternionsare (x, y, z, w);scalesare linear;colorslinear rgb + opacity;sh, if given, is (n, 3 | 8 | 15, 3) higher-order coefficients. Each argument is aSplatArray, a buffer or nested sequences of rows.palette— how the SH palette is laid out:"sog"(64 entries per row, 16-bit labels: what a .sog file holds; needs n ≤ 65536),"direct"(one entry per splat, as many per row as a texture row fits, 24-bit labels — any n a texture can hold), or"auto"("sog"when it fits, else"direct").
- decode_webp(data: bytes) PNMImage¶
A lossless webp as a 4-channel
PNMImage(the native codec; lossy webp, a malformed file or one overwebp_max_pixels()pixels is refused with aValueError).
- encode_webp(image, width: int | None = None, height: int | None = None) bytes¶
A lossless webp of a
PNMImage, or of RGBA8 texels (row 0 = top): an (H, W, 4) buffer such as a :attr:`SogBundle.planes` entry, or a flat one withwidth/height.
- floats(values) PointerToArray_float¶
valuesas a flatPTA_float(aSplatArray/PTA_floatis passed through; any float32 buffer is copied once; other buffers and nested sequences are converted).
- read_ply(path, *, with_sh: bool = True, name: str | None = None) SogBundle¶
A 3DGS
.ply(the trainer’s output: per-vertexx y z,f_dc_0..2,opacityas a logit,scale_0..2as logs,rot_0..3as (w, x, y, z), andf_rest_0..44channel-major) as a bundle. Binary (either endianness) and ASCII files are read;with_shkeeps the higher bands (a direct palette: 15 texels per splat, so 400 MB of texture for a 6.8 M scan).
- read_sog(path, *, with_sh: bool = False) SogBundle¶
Read a
.sogbundle (a stored ZIP) or a directory holding its files.
- read_splats(path, *, with_sh: bool = True, **kw) SogBundle¶
A bundle from a
.sog(file or directory) or a 3DGS.ply, by extension.
- set_webp_max_pixels(pixels: int) None¶
Raise or lower the webp decoder’s pixel cap (process-wide; 0 restores the default). A plane over the cap is refused before anything is allocated.
- write_bundle(path, b: SogBundle) None¶
Serialise an in-memory bundle as a .sog (stored ZIP of webp planes). A direct (wide) SH palette is not a .sog layout and is refused.
- write_ply(path, positions, quaternions, scales, colors, sh=None) None¶
A 3DGS
.plyfrom plain arrays (binary little-endian) — the inverse ofread_ply(), for tests and tools. Arguments asbundle_from_arrays().
- write_sog(path, positions, quaternions, scales, colors, sh=None) None¶
Write a v2 bundle from plain arrays — the inverse of the decode, for tests and tools (lossless webp, linear 256-entry codebooks). Arguments as
bundle_from_arrays(); withshthe file’s palette holds one entry per splat, so n ≤ 65536.