3dtiled-to-3dtiles
Reference notes

SparkJS ExtSplats

ExtSplats is the Spark 2.0 preview extended splat container using 32 bytes per splat (vs 16 for PackedSplats), stored across two Uint32Array

Source: https://sparkjs.dev/2.0.0-preview/docs/ext-splats/ Version: Spark 2.0 preview

ExtSplats is the Spark 2.0 preview extended splat container using 32 bytes per splat (vs 16 for PackedSplats), stored across two Uint32Arrays.

Byte Layout (32 bytes = 2 × uvec4 = 8 × uint32)

extArrays[0] (bytes 0–15):

OffsetFieldSizeDescription
0–3center.x4Bfloat32 bits (uintBitsToFloat)
4–7center.y4Bfloat32 bits
8–11center.z4Bfloat32 bits
12–13opacity2Bfloat16
14–15reserved2Bunused

extArrays[1] (bytes 16–31):

OffsetFieldSizeDescription
16–17color.r2Bfloat16
18–19color.g2Bfloat16
20–21color.b2Bfloat16
22–23ln(scale.x)2Bfloat16 (decoded with exp)
24–25ln(scale.y)2Bfloat16
26–27ln(scale.z)2Bfloat16
28–31quaternion4Bpacked oct+angle (10/10/12 bits)

Total: 32 bytes/splat

Key differences vs PackedSplats

PropertyPackedSplatsExtSplats
Size16 B/splat32 B/splat
centerfloat16float32 (higher precision)
opacityuint8float16
RGB coloruint8 (sRGB)float16
scalesuint8 log (e^-12..e^9)float16 log
quaternionoct88 + u8 angleoct10/10 + 12-bit angle

Creating

const extSplats = new ExtSplats({
  url?: string,           // .ply, .spz, .splat, .ksplat, .rad
  fileBytes?: Uint8Array,
  extArrays?: [Uint32Array, Uint32Array],
  numSplats?: number,
  construct?: (splats) => void,
  lod?: boolean | number,
  lodSplats?: ExtSplats,
});

Encoding / Decoding

import { utils } from "@sparkjsdev/spark";

utils.encodeExtSplat(extSplats.extArrays, index, x, y, z, sx, sy, sz, qx, qy, qz, qw, opacity, r, g, b);
const { center, scales, quaternion, color, opacity } = utils.decodeExtSplat(extSplats.extArrays, index);

extSplats.forEachSplat((index, center, scales, quaternion, opacity, color) => { ... });

SH Layout (extra property)

SH3 split into sh3a + sh3b (different from PackedSplats):

BufferWords/splatCoefficients
sh14 (16B)sh1_0, sh1_1, sh1_2, sh2_0 (4th word reused by SH2)
sh24 (16B)sh2_1..sh2_4
sh3a4 (16B)sh3_0..sh3_3
sh3b4 (16B)sh3_4..sh3_6

Each RGB coefficient: 8-bit magnitude per channel + 5-bit shared exponent + 3 sign bits = 4 bytes/coefficient.

On this page