from pathlib import Path import numpy as np import torch from jaxtyping import Float from torch import Tensor SH_C0 = 0.28209479177387814 def export_splat( means: Float[Tensor, "gaussian 3"], scales: Float[Tensor, "gaussian 3"], rotations: Float[Tensor, "gaussian 4"], harmonics: Float[Tensor, "gaussian 3 d_sh"], opacities: Float[Tensor, " gaussian"], path: Path, scale_threshold: float | None = None, ) -> None: """Write the compact 32-byte-per-Gaussian format used by gsplat.js.""" if harmonics.ndim == 3 and harmonics.shape[-1] == 3 and harmonics.shape[-2] != 3: harmonics = harmonics.transpose(-1, -2) if scale_threshold is not None: if scale_threshold <= 0: raise ValueError("scale_threshold must be positive") keep = scales.max(dim=-1).values <= scale_threshold if not keep.any(): raise ValueError( f"No Gaussians remain below scale threshold {scale_threshold:.4f}" ) means = means[keep] scales = scales[keep] rotations = rotations[keep] harmonics = harmonics[keep] opacities = opacities[keep] positions_np = means.detach().float().cpu().contiguous().numpy().astype("