SplatMesh is a small Wolfram Language paclet for importing, manipulating, and exporting Gaussian splatting meshes (.spz files). It provides a compact in-memory representation of splats (centers, scales, orientations, color and opacity data) using SPZ format, extends default Import, Export expressions, allows bulk operations, simple transformations, and a lightweight preview using Wolfram Standard Library.
- Mathematica (no 3D render, only point clouds)
 - WolframScript Freeware!
 - WLJS Notebook (requires >= 2.8.7) Freeware!
 
This paclet is intentionally tiny and designed to integrate with open-source Spark.js β¨ library for GPU-based rendering in browser contexts. Since WLJS Notebook is a web-based app, you can fully render and integrate Gaussian splats with your Graphics3D routies
Plot3D[x y, {x,-1,1}, {y,-1,1}, Epilog->{SplatMesh[<...>]}]This also means, that Scale, GeometricTransform, Translate and etc expressions can be applied on SplatMesh primitives in the context of Graphics3D.
Captured on iPhone and imported directly to WLJS
See online demo 1 πΉοΈ See online demo 2 πΉοΈ
Kernel/SplatMesh.wlβ Core Wolfram Language definitions and API.Kernel/Parser.wlβ SPZ import/export helpers and parser utilities.Examples/β Example.spzfiles (butterfly.spz,hornedlizard.spz).
Relevant only for WLJS Notebook users: These assets are loaded automatically to the runtime once paclet has required:
Assets/Spark/β Spark.js runtime helpers for rendering.Assets/Bundle/bundle.jsβ Bundled JavaScript for embedding notebooks with splats (it will be used automatically upon export).
-  
.spz -  
.ply 
SplatMesh: An immutable symbolic representation of a Gaussian splatting mesh. Internally it stores either a packed (gzip-compressed binary) or unpacked (Association-based) representation.
Copy the paclet folder into one of the paclet directories or add the project to your Wolfram Language search path.
git clone https://github.com/JerryI/wl-splatmesh
cd wl-splatmeshPacletDirectoryLoad["path to library"]
Needs["CoffeeLiqueur`Workshop`SplatMesh`"]LPM is unofficial package manager used to install libraries locally from Github repositories. Drop this snippet and evaluate it:
LPMRepositories[{
    "Github" -> "https://github.com/JerryI/wl-splatmesh" -> "master"
}];
Needs["CoffeeLiqueur`Workshop`SplatMesh`"]or as a paclet
LPMRepositories[{
   "https://github.com/JerryI/wl-splatmesh/releases/download/v1.0.0/CoffeeLiqueur__SplatMesh-1.0.0.paclet"
}];
Needs["CoffeeLiqueur`Workshop`SplatMesh`"]Using native WL's PacletInstall
PacletInstall["https://github.com/JerryI/wl-splatmesh/releases/download/v1.0.0/CoffeeLiqueur__SplatMesh-1.0.0.paclet"]Import a file and preview it:
		mesh = Import["path/to/model.spz", "SPZ"]Show properties available for an object:
		mesh["Properties"]Get raw data or a specific property (centers, RGB, Opacities, Scales, Quaternions):
		centers = mesh["Centers"]
		rgb = mesh["RGB"]Convert between packed and unpacked representations:
		unpacked = SplatMeshUnpack[mesh]
		packed = SplatMeshPack[unpacked]Note: unpacking/packing occurs automatically when you apply any transformations on packed (default) splats. Unpack manually if you want to apply many transformations in series
Apply a matrix transform to all centers (unpacked or packed is handled):
		mesh2 = TransformedSplat[mesh, matrix3]Apply a matrix + translation:
		mesh3 = TransformedSplat[mesh, {matrix3, translationVector}]Apply a custom per-splat function:
		f[idx_, center_, scale_, quat_, opacity_, rgb_] := {center + {0.0,0.0,1.0}, scale*1.1, quat, opacity*0.95, rgb};
		mesh4 = TransformedSplat[mesh, f]Append new splats (unpacked or packed supported):
		new = {{x,y,z},{sx,sy,sz},{qx,qy,qz,qw},opacity,{r,g,b}}
		mesh5 = Append[mesh, new]Or append multiple splats at once by passing a list of splats.
Export back to .spz:
		Export["out.spz", mesh, "SPZ"]All API functions below are defined in Kernel/SplatMesh.wl. You can see them by evaluating:
Names["CoffeeLiqueur`Workshop`SplatMesh`*"]- 
SplatMesh::usage- Represents a SplatMesh object. Constructed by importers or returned by functions in this paclet.
 
 - 
SplatMeshPack[s_SplatMesh]- Input: 
_SplatMeshin unpacked form. - Output: Packed 
_SplatMeshcontaining gzip-compressed binary data suitable for export. - Errors: Returns 
$Failedfor invalid input. 
 - Input: 
 - 
SplatMeshUnpack[s_SplatMesh]- Input: 
_SplatMeshin packed form. - Output: Unpacked 
_SplatMeshwith anAssociationof arrays: "Centers", "Scales", "Quaternions", "Opacities", "RGB", plus SH1/SH2/SH3 (spherical harmonics) where present. 
 - Input: 
 - 
SplatMeshPackedQ[s_SplatMesh]- Returns True when the mesh is in packed form, False otherwise.
 
 - 
SplatMeshResample[s_SplatMesh, n_Integer]- Returns downsampled 
SplatMeshwithnsplats in total using basic binned method 
 - Returns downsampled 
 - 
TransformedSplat[s_SplatMesh, transform]- transform can be:
- a 3x3 numeric matrix β multiplies centers by matrix
 {matrix, vector}β applies matrix then translates by vector- a function with signature 
(index, center, scale, quaternion, opacity, rgb)returning{center, scale, quaternion, opacity, rgb} 
 - Works for packed meshes by unpacking and repacking automatically.
 - Returns 
$Failedand emitsTransformedSplat::badfunctionif the supplied function doesn't return the expected shape. 
 - transform can be:
 - 
SplatMeshFilter[s_SplatMesh, criFunction]criFunctioncan be:- a function with signature 
(index, center, scale, quaternion, opacity, rgb)returningTrueorFalse 
- a function with signature 
 - Works for packed meshes by unpacking and repacking automatically.
 - Returns a filtered mesh of splats
 
 - 
Append[s_SplatMesh, data]- Overloaded 
Appendhandler on the SplatMesh head. Append[s, splat]accepts a single splat or a list of splats in the shape: {center, scale, quaternion, opacity, rgb} where- center: 
{x,y,z} - scale: 
{sx,sy,sz} - quaternion: 
{qx,qy,qz,qw} - opacity: numeric 
0->1 - rgb: 
{r,g,b} 
- center: 
 - Returns a new SplatMesh with the splats appended. For packed meshes the operation will unpack and repack automatically.
 - If input is malformed, 
Appendwill return$Failedand emitappendSplats::badsplats. 
 - Overloaded 
 - 
SplatMesh[...][property_String]Read-only- Use the bracket syntax to query properties:
["Centers"]β Nx3 array of centers["Scales"]β Nx3 array of scales["Quaternions"]β Nx4 array of quaternions["Opacities"]β length-N list of opacities["RGB"]β Nx3 array of RGB values["RawData"]β the underlying ByteArray (for packed meshes) or raw association["Format"]β "Packed" or "Unpacked"["Container"]β always "SPZ"["Size"]β Quantity representing the raw byte size when available["Preview"]β generates 3D preview approximating clouds with points reduced to 300 groups of 3000 samples of splats["PreviewGeometry"]- generates 3D preview and returns primitives["Properties"]β list of available property keys
 
 - Use the bracket syntax to query properties:
 
If you want to update one of these properties use the following syntax:
SplatMesh[old_SplatMesh, property -> newValue]Load an example and preview it in a notebook:
		mesh = Import[FileNameJoin[{"Examples","butterfly.spz"}], "SPZ"]
		meshanother example:
        mesh = Import[FileNameJoin[{"Examples","tap.spz"}], "SPZ"]Transform and export:
		rotated = TransformedSplat[mesh, RotationMatrix[Pi/2, {0,0,1}] // N]
		Export["butterfly_rotated.spz", rotated, "SPZ"]Append splats programmatically:
		newSplat = {{0,0,0},{0.01,0.01,0.01},{0,0,0,1},1.,{1,0,0}} // N;
		mesh2 = Append[mesh, newSplat]- 3D model 
tap.spzwas scanned by @JerryI in a shower, PD - 3D model 
butterfly.spz: Spark.js, MIT - 3D rendering Javascript library 
spark.js: Spark.js, MIT 
The rest of source code is licensed under MIT β see PacletInfo.wl for metadata.

