manifold-rust
3D mesh booleans in pure Rust — exact on clean geometry, robust on real-world geometry.
What this is
Two things in one library:
-
A pure-Rust port of Manifold (Emmett Lalish's C++ geometry kernel, v3.5.0) — union / intersection / difference on triangle meshes, plus constructors, cross-sections, convex hull, Minkowski, SDF meshing and smooth subdivision. The port targets exact numerical match: same algorithms, same floating-point results, same triangle topology, validated by instrumented boolean-by-boolean trace comparison against a locally built C++ reference.
-
A second, original "robust" boolean engine that the C++ library does not have. It accepts the meshes real pipelines actually contain — triangle soup, scans, Thingiverse downloads: non-manifold connectivity, self-intersections, doubled sheets, disconnected shells, internal voids, inside-out bodies. It computes on exact rational arithmetic with a mesh-arrangement formulation (Zhou, Grinspun, Zorin & Jacobson 2016), so its answers are decided by exact predicates rather than by tolerances.
Why you'd use it
- The exact engine matches the C++ reference, down to the tie-breaking order of the symbolic-perturbation predicates — so results are reproducible against the reference implementation the rest of the ecosystem uses, with no FFI and clean WASM builds.
- The robust engine handles what the exact engine can't. It has been swept over the
whole Thingi10K corpus (~10k meshes):
0
NotClosedfailures, and every volume disagreement above the sampling-noise floor was arbitrated by an independent Monte-Carlo referee — in the robust engine's favour in every case (~150 arbitrated meshes). The typical exact-engine failure on such input is 2–3× volume overcounting on self-overlapping shells. Autogives you clean data by default. It picks the fast exact engine only when that is provably safe (both operands manifold and free of self-intersections, a cached ~0.2 ms exact scan), and the robust engine otherwise. You do not have to know which kind of mesh you were handed.
Features
- Booleans: union, intersection, difference (also
+-^operators), n-ary batch and CSG-tree evaluation - Constructors and modeling: cube / sphere / cylinder, extrude, revolve, convex hull, Minkowski sum & difference, SDF level sets, smooth subdivision, 2D cross-sections
- Mesh repair utilities:
repair_orientation()for inside-out bodies,has_self_intersections()as an exact self-scan - Cooperative cancellation and coarse progress reporting through the whole boolean pipeline (library → C FFI → WASM → demo)
- Optional
parallelfeature (rayon) — results stay bit-identical to the sequential build; only determinism-preserving sites are parallelized - C FFI (
ffi/manifold_rs.h) and C#/.NET bindings (dotnet/, ManifoldRust on NuGet) - WASM: an interactive demo runs the whole engine in the browser — https://larsbrubaker.github.io/manifold-rust/
Quickstart — Rust
use Vec3;
use Manifold;
use Error;
let cube = cube;
let sphere = sphere;
let result = cube.difference;
assert_eq!;
println!;
println!;
let mesh = result.get_mesh_gl; // vert_properties / tri_verts, ready for a GPU
Messy input — import as soup and let Auto choose the engine:
use ;
// Imports geometry the strict pipeline would reject as NotManifold.
let scan = from_mesh_gl_robust;
// Per call…
let cut = scan.difference_with_engine;
// …or once, process-wide.
set_default_engine;
let cut = scan.difference;
Geometry that is not even closed imports as empty with Error::NotClosed. The default
engine remains Exact, so existing code is unchanged.
Parallel execution (bit-identical results, roughly 2× on heavy boolean workloads):
[]
= { = "0.12", = ["parallel"] }
Quickstart — C# / .NET
using ManifoldRust;
using Manifold body = Manifold.FromMesh(vertProperties, triVerts);
using Manifold hole = Manifold.FromMesh(holeVerts, holeTris);
// Check Status on every operand: a failed import is absorbed as empty geometry.
if (body.Status != ManifoldStatus.NoError || hole.Status != ManifoldStatus.NoError)
throw new InvalidOperationException("bad input mesh");
Manifold.DefaultBooleanEngine = BooleanEngine.Auto; // robust when it matters
using Manifold result = Manifold.BatchBoolean(new[] { body, hole }, ManifoldOpType.Subtract);
MeshGL mesh = result.GetMeshGL();
There is a double-precision path (FromMesh64 / GetMeshGL64), a robust import
(FromMeshRobust), and CancellationToken support. Full binding documentation:
dotnet/README.md; the ABI itself is described in
ffi/manifold_rs.h.
State of the project
- Port: complete. All 18 phases of the C++ engine (v3.5.0) are implemented and every
C++ test is ported or covered — 686 tests passing, 0 failing (the handful of
#[ignore]d tests are debug-build-speed only and pass in release). Details in PORTING_PLAN.md. - Performance: at parity with the sequential C++ build. Sphere-minus-sphere at 2 M
input triangles: 2.61 s (C++) vs 2.57 s (Rust); a 7 999-sphere grid union: 13.5 s vs
14.5 s — identical triangle counts throughout, peak memory within ~10%. The
parallelfeature roughly doubles throughput. Reproduce withcargo run --release --example perf_testand--example large_scene_test. - Robust engine: corpus-validated, with the current numbers, open items and the referee tooling in docs/ROBUST_ENGINE_STATUS.md.
- Deliberate divergences from C++ (accuracy fixes, each with evidence) are catalogued in docs/CPP_DIVERGENCES.md.
Known limits, honestly:
- Very large, heavily self-intersecting meshes can be slow in the robust engine —
a handful of the ~10k corpus meshes exceed a 120 s budget and are reported as
Cancelledrather than wrong. Speeding up the exact-predicate fallback is the top open item. - The WASM build is single-threaded; the
parallelfeature is native-only. - The robust engine requires input to be closed; anything else imports empty with
Error::NotClosed.
Building
Exact-match validation against the upstream C++ (needs the submodule):
./validate-reference.ps1 # or: ./validate-reference.ps1 -Phase phase8
The WASM demo:
&& &&
Support the project
manifold-rust is open source, free to use, and maintained in spare time as a labor of love (friends James Smith and Dan Ruskin help out from time to time). MatterHackers sponsors the work — it uses mesh booleans extensively in production 3D-printing workflows, which is why a dependable pure-Rust kernel exists at all.
- Donate: Buy Me a Coffee
- Star the repo — costs nothing, helps others find it
- Report issues: open an issue; the demo's Copy Debug Info button captures everything a boolean bug report needs
- Contribute: PRs welcome — open an issue first for larger changes
Part of the rust-apps suite — Rust graphics and geometry libraries by Lars Brubaker.
License and credits
Apache-2.0, matching the original Manifold library.
- Emmett Lalish — author of the original Manifold C++ library, which this port follows.
- Lars Brubaker — port author, robust engine.
- MatterHackers — sponsor.
