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 (Combined WASM + Native)
The ply2splat npm package provides a unified interface that seamlessly combines WebAssembly (WASM) for browser support and high-performance native bindings for Node.js.
Install from npm:
When installed in a Node.js environment, it will attempt to download and use the native bindings (@ply2splat/native) for maximum performance and multi-threading. If the native bindings are unavailable or the platform is unsupported, it gracefully falls back to the WASM implementation.
Usage
CLI
Standard Installation (Rust)
Native CLI via Node.js
You can also run the high-performance Rust CLI directly via Node.js without installing Rust or compiling the binary manually. This uses the pre-compiled native bindings.
# Run once without installing
# Or install globally
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. It automatically selects the best backend (Native or WASM) for your environment.
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, getBackend } from 'ply2splat';
import { readFileSync } from 'fs';
// Initialize (loads native bindings if available, otherwise WASM)
await init();
console.log(`Using backend: ${getBackend()}`); // 'native' or 'wasm'
// 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