Repository navigation
Compressed PLY files
extensions/scan/compressed_ply.mojo reads compressed PLY files, PlayCanvas's packed Gaussian splats, into a ScanScene. SuperSplat writes this format, often as .compressed.ply. The reader decodes each field as readPly in @playcanvas/splat-transform 3.10.1 does. So a compressed file gives the splats of the PLY file that splat-transform writes from it, to the bit.
A scanned building can be a compressed PLY file. examples/scan_parts.mojo takes the path of one, and cuts it into parts.
var scene = read_compressed_ply("scan.compressed.ply")
var splats = scene.geometry.copy() # the splats and their bands
var model = scene.model # SPLAT_DEFAULT, from the commentsparse_compressed_ply(bytes) reads the bytes of a file. is_compressed_ply(bytes) tells a compressed file from a plain splat PLY by its header. extensions/scan/files.mojo calls both when it reads a file of any format; see Scan files.
A compressed PLY file is a binary little-endian PLY file with two or three elements:
| Element | Rows | What a row holds |
|---|---|---|
chunk |
One for each 256 splats | The least and the most of the chunk's centers and scale logarithms, and of its colors when it has them |
vertex |
One for each splat | Four 32-bit words: packed_position, packed_rotation, packed_scale and packed_color
|
sh |
One for each splat, or none | 9, 24 or 45 bytes, f_rest_0 and on |
- Centers and scales. A word holds 11, 10 and 11 bits for x, y and z, from the top bit down. Each is a fraction of the way from the chunk's least to its most.
-
Rotations. The top two bits name the largest of w, x, y and z. The other three are 10-bit numbers, each
(n / 1023 - 0.5) * sqrt(2). The largest makes the rotation a unit. -
Colors. A byte each for red, green, blue and opacity, from the top byte down. A color byte is a fraction
cof 255, or of the chunk's color range when the chunk has one. The zeroth band is(c - 0.5) / SH_C0. The opacity's logit is-ln(1 / a - 1), so a byte of 0 gives no opacity and 255 gives full opacity. -
Harmonics. A byte
bis(n - 0.5) * 8, withn0 for 0, 1 for 255, and(b + 0.5) / 256for the others.
The reader rounds each field to Float32 where splat-transform does. It uses splat-transform's own constants: its SH_C0 is one unit in the last place from three.js's.
The header's comments name the splat model, as extensions/scan/scene.mojo reads them. Brush writes SplatRenderMode: default, mip or 2dgs. Postshot writes antialiased 0 or 1.
- A header that is not PLY, that has a list property, or that counts more than 4,294,967,295 rows.
- A file whose
vertexelement has nopacked_position. Read a plain splat PLY withloaders.gaussian_splat_ply. - A format other than binary little-endian.
- A file with no
chunkelement, or with a missingpackedword, chunk bound or color bound. - A
packedword that is not auint, and anshbyte that is not auchar. - A count of chunks that is not one for each 256 splats.
- A count of
shbytes that is not 0, 9, 24 or 45, and anshelement with another count of rows. - No splats, and a file shorter than its header says.
The reader keeps byte ranges of the header, and no text. The WebAssembly build of the C ABI's splat app has no strings, so this is what lets a browser read a compressed scan. See C ABI and hosts.
read_scan(path) reads a scan file of any format into a ScanScene, and parse_scan(bytes, format) reads its bytes. scan_format(name, bytes) tells the formats apart:
| Format | How it is told | Reader |
|---|---|---|
SCAN_SOG |
PK, 3 and 4: a ZIP file |
SOG files |
SCAN_SOG_FOLDER |
A name that ends in meta.json
|
SOG files |
SCAN_COMPRESSED_PLY |
ply, and packed_position in its header |
This page |
SCAN_PLY |
ply |
loaders.gaussian_splat_ply |
SCAN_SPZ |
gzip's 31 and 139, or NGSP
|
loaders.spz |
SCAN_KSPLAT |
A name that ends in .ksplat
|
loaders.ksplat |
SCAN_SPLAT |
A name that ends in .splat
|
loaders.splat |
The first bytes come before the name. Every format but SPZ holds the axes of the Gaussian splatting training code: x to the right, y down and z forward. ScanFormat.y_down says which, so that a viewer can stand a scan up.
assets/compressed_ply/make_compressed_ply.mjs writes the test files with splat-transform 3.10.1, and reads each one back into a _restored.ply file. It writes degree 3 over three chunks, degree 2, 1 and 0, and a degree 1 file without the chunks' color bounds. tests/test_scan_compressed_ply.mojo requires the same centers, covariances, color bytes and harmonics bytes from each pair. assets/fixture-manifest.json records the files' sums and the commands that write them.
Tutorials
How-to
- Install
- Run the checks
- GPU backend
- Coverage
- Measure examples
- Add a feature
- Add a scanned building
- Write documentation
Reference
- Scene graph
- Rotations
- Cameras
- Geometry
- Geometry addons
- Lofts and clipping groups
- Sculptor
- Procedural generators
- Meshes and assets
- Lines
- Points and sprites
- Helpers
- Scene objects
- Animated objects
- Raycasting
- Curves and paths
- Animation
- Skinning
- Materials
- Node materials
- TSL functions
- Lights
- Lighting addons
- Fog
- Textures
- Renderer
- Renderer hooks and material flags
- Rasterization
- GPU backend
- Render target
- Post-processing
- GPU computation
- Compute nodes
- Progressive light map
- Gaussian splats
- Voxel global illumination
- SVG renderer
- Image files
- Image decode queue
- Model files
- More model files
- Exporters
- Scene JSON
- Windowing and controls
- C ABI and hosts
- Math
- Norm consumers
- Math addons
- Units
- Coverage tool
- Commands
- Examples
- Benchmarks
- Extensions
- Shared physics
- Physics query snapshots
- Continuous collision
- Tick force restoration
- Water
- Warp drives
- Vegetation
- Village
- Streamline
- Animals
-
Buildings
- Numerics
- Building topology
- Building model
- IFC exchange
- Procedural towers
- Floor plans and interiors
- Frame analysis
- Shell analysis
- Building energy
- Construction kits
- Bearing walls
- Scanned buildings
- SOG files
- Compressed PLY files
- Scan parts
- Cleaning and orienting scans
- Walking through a scan
- Virtual scans
- Castle
- CARLA
- Femur
- Tibia
- Fibula
- Patella
- Knee
- Muscles
- Vessels
- Lymph
- Nerves
- Integument
- Leg
- Foot
- Pelvis
- Torso
- Arm
- Hand
- Head
- Genome
- Game humanoid
- Humanoid fidelity
- Mixamo animations
- Audio-aligned game faces
- Converted assets
- Mesh quality
- Garments
- Outfits and armor
- Cloth and spring bones
- Attire estimates
- Segment inertia
- Process chemistry
- Thermochemical data
- Chemical equilibrium
- Process maps
- Rates and transport
- Electrolysis and film color
- Binary solutions
- Flowsheets and routes
- Materials and coatings
- Crystals and figures
Explanation
- Software rasterizer
- Scene graph as an array
- Linear color
- Normals are not colors
- Perspective correction
- Fixed-point coverage
- Per-fragment shading
- Mipmaps
- Sorted transparency
- Types and checks
- Render hooks as a trait
- Shared CPU and GPU code
- Bands and threads
- PNG structure
- Extensions beside the port
- Process temperatures
- Scans as building models
- CUDA teardown hang
- Mojo compiler hang