ply2splat
A Rust crate and CLI tool for converting Gaussian Splatting .ply files to the .splat format.
Available on crates.io for Rust, PyPI for Python, and npm for JavaScript/TypeScript.
Workspace Architecture
This repository is organized as a Cargo workspace:
. # Core library (ply2splat) and CLI
├── bindings/
│ ├── ply2splat-wasm/ # WASM bindings for browser/Node.js
│ ├── ply2splat-napi/ # Native Node.js bindings via NAPI-RS
│ └── ply2splat-python/ # Python bindings via PyO3
└── packages/
└── ply2splat/ # Unified npm package (WASM + optional native)
Features
- High Performance: Utilizes parallel processing (via
rayon) for conversion and sorting. - Fast I/O: Uses zero-copy serialization and large buffers for maximum throughput.
- Correctness: Implements the standard conversion logic including Spherical Harmonics (SH) to color conversion and geometric transformations.
- Python Bindings: Use the library directly from Python via PyO3.
- WebAssembly Support: Run in browsers and Node.js via the npm package.
- Native Node.js Bindings: For maximum performance via NAPI-RS.
Installation
Rust Crate
Add ply2splat to your Cargo.toml:
[]
= "0.2"
CLI
Install the CLI tool directly from crates.io:
Or build from source:
The binary will be available at target/release/ply2splat.
Python Package
Install from PyPI:
Or install from source using maturin:
Or build a wheel:
npm Package (WebAssembly)
Install from npm:
Usage
CLI
Python
# Convert a PLY file to SPLAT format
=
# Convert without sorting (faster, but may affect rendering quality)
=
# Load PLY file and access individual splats
=
# Access splats by index
=
=
# Load existing SPLAT file
=
# Get raw bytes for custom processing
=
# Load and convert to bytes (for in-memory processing)
, =
JavaScript/TypeScript (Browser/Node.js)
The npm package provides full TypeScript support with helper functions for working with various input types.
Browser Usage
import { init, convertFromFile, convertFromUrl, downloadSplat } from 'ply2splat';
// Initialize the WASM module
await init();
// Convert from a File input
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
fileInput.addEventListener('change', async (e) => {
const file = fileInput.files![0];
const result = await convertFromFile(file);
console.log(`Converted ${result.count} splats`);
// Get typed Splat objects
const splats = result.toSplats();
console.log(splats[0].position); // [x, y, z]
// Download the result
downloadSplat(result.data, 'output.splat');
});
// Convert from a URL
const result = await convertFromUrl('https://example.com/model.ply');
Node.js Usage
import { init, convertFromBuffer } from 'ply2splat';
import { readFileSync } from 'fs';
// Initialize the WASM module
await init();
// Convert from a Node.js Buffer
const plyBuffer = readFileSync('model.ply');
const result = convertFromBuffer(plyBuffer);
console.log(`Converted ${result.count} splats`);
// Get typed splat data
const splats = result.toSplats();
The package includes full TypeScript definitions. See the API documentation for detailed type information and all available helper functions.
Development
Requirements
- Rust (latest stable)
- Nix (optional, for reproducible environment)
- wasm-pack (for WASM builds)
Running Tests
# Test the entire workspace
# Test a specific crate
Building WASM
# Install wasm-pack
# Build for web (browsers)
# Build for bundlers (webpack, etc.)
Building the npm Package
# Build WASM first
# Build TypeScript
Fuzzing
The crate includes fuzzing targets to ensure stability against malformed inputs.
# Install cargo-fuzz
# Run fuzzing target
Development Environment
This project supports both Nix and Devcontainers for a reproducible development environment.
- Nix:
nix developwill enter a shell with Rust and dependencies configured. - Devcontainer: Open the folder in VS Code and accept the prompt to reopen in container.
License
MIT