manifold-rust 0.11.0

Pure Rust port of the Manifold 3D geometry library
Documentation

manifold-rust

crates.io docs.rs license

Demo

Support the Project

manifold-rust is open-source and free to use, maintained in spare time as a labor of love. Friends James Smith and Dan Ruskin help out from time to time too.

If you find it useful, here are a few ways to help keep development going:

  • Donations: Buy Me a Coffee — every coffee helps.
  • Star the repo: Costs nothing and helps others find the project.
  • Report issues: Open an issue for bugs or feature ideas.
  • Contribute: PRs welcome — open an issue first to discuss larger changes.

Pure Rust port of Manifold — a geometry library for 3D boolean operations on triangle meshes.

Part of the rust-apps suite — a collection of Rust graphics and geometry libraries by Lars Brubaker.

Status: Port complete. All 18 phases of the C++ engine (v3.5.0) are implemented and every C++ test is ported or covered — 630 tests passing, 0 failing (the handful of #[ignore]d tests are debug-build-speed only and pass in release). Heavy boolean/CSG workloads run at parity with the sequential C++ build, and the optional parallel feature roughly doubles them. See PORTING_PLAN.md for the full record. Beyond the port, the library now also includes a robust boolean engine that accepts non-manifold input — see Robust booleans on non-manifold input.

What is Manifold?

Manifold is a high-performance C++ library for 3D solid modeling. It supports:

  • Boolean operations (union, intersection, difference) on triangle meshes
  • Mesh constructors (sphere, cube, cylinder, extrude, revolve)
  • Cross-section (2D polygon) operations
  • Smooth subdivision and SDF-based mesh generation
  • Convex hull
  • Minkowski sum/difference

This Rust port targets exact numerical match with the C++ implementation — same algorithms, same floating-point results, same triangle topology. Exactness is validated by instrumented, boolean-by-boolean trace comparison against a locally built C++ reference (see validate-reference.ps1), down to the tie-breaking order of symbolic-perturbation predicates.

Beyond the port, it adds one capability the C++ library does not have: a second, robust boolean engine that accepts closed non-manifold meshes (shared edges/vertices, disconnected shells, internal voids) — common in real-world scan and Thingiverse geometry that the strict pipeline rejects. See Robust booleans on non-manifold input.

Why

MatterHackers uses 3D mesh boolean operations extensively in production for 3D printing workflows. A pure Rust implementation avoids FFI overhead and integrates cleanly with Rust tooling including WASM compilation.

Installation

Available on crates.io:

cargo add manifold-rust

API documentation: https://docs.rs/manifold-rust

Usage

use manifold_rust::manifold::Manifold;
use manifold_rust::linalg::Vec3;

// Constructors
let cube = Manifold::cube(Vec3::new(1.0, 1.0, 1.0), true);
let sphere = Manifold::sphere(0.6, 32);

// Guaranteed-manifold booleans (also available as + - operators)
let difference = cube.difference(&sphere);
assert_eq!(difference.status(), manifold_rust::types::Error::NoError);

// Measure
println!("volume = {}", difference.volume());
println!("area   = {}", difference.surface_area());
println!("genus  = {}", difference.genus());

// Mesh I/O via MeshGL
let mesh = difference.get_mesh_gl(0);
let round_tripped = Manifold::from_mesh_gl(&mesh);

Enable parallel execution (results stay bit-identical to the sequential build — only determinism-preserving sites are parallelized):

[dependencies]

manifold-rust = { version = "0.11", features = ["parallel"] }

Robust booleans on non-manifold input

Alongside the default exact (C++-matching) pipeline there is a second, robust boolean engine (Barki, Guennebaud, Foufou 2015) built on exact rational arithmetic. It requires inputs only to be closed and orientable: shared edges/vertices, disconnected shells, and internal voids are all fine. On manifold inputs it agrees with the exact engine to near-f64 precision (triangulation may differ), and vertex properties (colors, UVs) carry through to the result the same way the exact engine's do.

use manifold_rust::manifold::Manifold;
use manifold_rust::types::{BooleanConfig, BooleanEngine};

// Import geometry the strict path would reject as NotManifold:
let soup = Manifold::from_mesh_gl_robust(&mesh);          // or from_mesh_gl64_robust

// Per-call engine choice…
let cut = soup.difference_with_engine(&cutter, BooleanEngine::Auto);

// …or a process-global default. Auto = exact for manifold pairs,
// robust whenever a non-manifold operand is involved.
BooleanConfig::set_default_engine(BooleanEngine::Auto);
let cut = soup.difference(&cutter);

Geometry that is not even closed imports as empty with Error::NotClosed. The default engine remains Exact, so existing code is byte-identical to previous releases.

Demo

An interactive WASM demo is live at https://larsbrubaker.github.io/manifold-rust/ — booleans, extrude/revolve with twist, convex hull, subdivision, a Menger sponge, and more, all running the Rust engine compiled to WebAssembly.

The Boolean Gallery includes an engine selector (Exact / Robust / Auto) and can load random mesh pairs from the Thingi10K dataset — manifold or non-manifold — to exercise the robust engine on real-world geometry. Every operation's inputs (model IDs, transform, engine) are captured behind a Copy Debug Info button so a failing combination can be pasted straight into a bug report.

Building

cargo build

cargo test

Restore the upstream C++ reference before doing exact-match validation:

git submodule update --init --recursive

Build and compare against the C++ reference with:

./validate-reference.ps1

You can also run a narrower validation slice by phase, for example:

./validate-reference.ps1 -Phase phase8

This configures and builds cpp-reference/manifold, runs the matching C++ reference tests, and then runs the corresponding Rust tests for the selected phase.

For the WASM demo:

cd demo

bun run build:wasm

bun run dev

Performance

The port is benchmarked against the C++ reference using Rust ports of the upstream perf drivers, printing identical output lines so runs diff cleanly:

  • cargo run --release --example perf_test — a sphere-minus-sphere boolean at doubling tessellation levels (extras/perf_test.cpp)
  • cargo run --release --example large_scene_test -- <n> — union of an n×n×n grid of unit spheres through the CSG tree (extras/large_scene_test.cpp)

Representative timings, best of several runs on the same machine (Windows 10, i7-7660U 2C/4T, 8 GB RAM; both sides sequential: C++ built Release with MANIFOLD_PAR=OFF, Rust default features, MSVC 19.44 / rustc via fat LTO):

Benchmark input tris C++ Rust
sphere ∖ sphere 2 048 5.2 ms 5.5 ms
sphere ∖ sphere 32 768 48 ms 43 ms
sphere ∖ sphere 131 072 170 ms 177 ms
sphere ∖ sphere 524 288 659 ms 621 ms
sphere ∖ sphere 2 097 152 2.61 s 2.57 s
sphere grid union, n=10 (999 spheres) 2.29 s 2.32 s
sphere grid union, n=20 (7 999 spheres) 13.5 s 14.5 s

Both implementations produce identical triangle counts on every benchmark (and the test suite validates bit-exact geometry). The largest perf_test round (8.4 M input tris) needs several GB of working set and is dominated by paging on the 8 GB test machine, so its timings are not comparable there. Peak memory is within ~10 % of C++ (1.47 GB vs 1.34 GB peak working set on the 2 M-tri round) after slimming the cached collider to the C++ storage layout and dropping assembly intermediates at the same points the C++ clears them; use cargo run --release --example mem_profile with MANIFOLD_TIMING=1 to see per-stage heap use.

Per-stage timing is available on both sides for gap hunting: set the MANIFOLD_TIMING environment variable for the Rust build (stage boundaries match the C++ MANIFOLD_TIMING build's output) — this is how the cached-face- collider optimization was found, which brought the intersection stage from 2.7× slower than C++ to faster than C++.

An optional parallel cargo feature parallelizes determinism-preserving sites with rayon (results stay bit-identical to the sequential build); see PORTING_PLAN.md for which stages it covers.

Architecture

The port follows the C++ module structure:

Rust module C++ source Description
vec / linalg linalg.h, vec.h Vector math, linear algebra
polygon polygon.cpp 2D polygon triangulation
impl impl.cpp, impl.h Core mesh data structure
constructors constructors.cpp Primitive mesh constructors
boolean3 boolean3.cpp 3D boolean operations
boolean_result boolean_result.cpp Boolean output assembly
csg_tree csg_tree.cpp CSG tree evaluation
edge_op edge_op.cpp Edge manipulation
face_op face_op.cpp Face manipulation
smoothing smoothing.cpp Smooth normals and subdivision
subdivision subdivision.cpp Mesh subdivision
properties properties.cpp Mesh properties
sdf sdf.cpp SDF-based mesh generation
quickhull quickhull.cpp Convex hull
minkowski minkowski.cpp Minkowski operations
cross_section cross_section/ 2D cross section
robust — (Rust-only) Robust boolean engine for non-manifold input (Barki et al. 2015)

License

Apache-2.0 — matching the original Manifold library.

Credits