Pure Rust port of the Manifold 3D geometry library
20
stars
241
commits
Rust
primary language
Aug 30, 2026
updated
3D mesh booleans in pure Rust — exact on clean geometry, robust on real-world geometry.
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.
NotClosed failures, 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.Auto gives 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.+ - ^ operators), n-ary batch and
CSG-tree evaluationrepair_orientation() for inside-out bodies,
rebuild_solid(rule) to re-derive a solid from the winding numbers when rewinding is
not enough, has_self_intersections() as an exact self-scanparallel feature (rayon) — results stay bit-identical to the sequential
build; only determinism-preserving sites are parallelizedffi/manifold_rs.h) and C#/.NET bindings (dotnet/,
ManifoldRust on NuGet)cargo add manifold-rust
use manifold_rust::linalg::Vec3;
use manifold_rust::manifold::Manifold;
use manifold_rust::types::Error;
let cube = Manifold::cube(Vec3::new(1.0, 1.0, 1.0), true);
let sphere = Manifold::sphere(0.6, 32);
let result = cube.difference(&sphere);
assert_eq!(result.status(), Error::NoError);
println!("volume = {}", result.volume());
println!("area = {}", result.surface_area());
let mesh = result.get_mesh_gl(0); // vert_properties / tri_verts, ready for a GPU
Messy input — import as soup and let Auto choose the engine:
use manifold_rust::types::{BooleanConfig, BooleanEngine};
// Imports geometry the strict pipeline would reject as NotManifold.
let scan = Manifold::from_mesh_gl_robust(&mesh);
// Per call…
let cut = scan.difference_with_engine(&cutter, BooleanEngine::Auto);
// …or once, process-wide.
BooleanConfig::set_default_engine(BooleanEngine::Auto);
let cut = scan.difference(&cutter);
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):
[dependencies]
manifold-rust = { version = "0.12", features = ["parallel"] }
dotnet add package ManifoldRust
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.
The ManifoldRust package above is a P/Invoke binding: it loads this Rust cdylib and calls
into it. manifold-sharp is the other
thing you might want — a complete pure C# port of manifold-rust, with no native library
at all, so it runs anywhere .NET runs, browser-wasm included. It is bit-exact with this
crate on identical inputs, and it lives as a submodule of
agg-sharp.
The two projects check each other: manifold-sharp's oracle test lane runs the same operations through its port and through this library via the binding, then compares the exported meshes row for row with no slack.
#[ignore]d tests are debug-build-speed
only). Details in PORTING_PLAN.md.parallel
feature roughly doubles throughput. Reproduce with
cargo run --release --example perf_test and --example large_scene_test.Known limits, honestly:
Cancelled rather than wrong. Speeding up the exact-predicate fallback is the top
open item.parallel feature is native-only.Error::NotClosed.cargo build
cargo test --release
Exact-match validation against the upstream C++ (needs the submodule):
git submodule update --init --recursive
./validate-reference.ps1 # or: ./validate-reference.ps1 -Phase phase8
The WASM demo:
cd demo && bun run build:wasm && bun run dev
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.
Part of the rust-apps suite — Rust graphics and geometry libraries by Lars Brubaker.
Apache-2.0, matching the original Manifold library.
240 commits
1 commits
Rust
90.4%
C#
8.2%
C
1.3%
Pure Rust port of the Manifold 3D geometry library
20
stars
241
commits
Rust
primary language
Aug 30, 2026
updated
3D mesh booleans in pure Rust — exact on clean geometry, robust on real-world geometry.
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.
NotClosed failures, 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.Auto gives 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.+ - ^ operators), n-ary batch and
CSG-tree evaluationrepair_orientation() for inside-out bodies,
rebuild_solid(rule) to re-derive a solid from the winding numbers when rewinding is
not enough, has_self_intersections() as an exact self-scanparallel feature (rayon) — results stay bit-identical to the sequential
build; only determinism-preserving sites are parallelizedffi/manifold_rs.h) and C#/.NET bindings (dotnet/,
ManifoldRust on NuGet)cargo add manifold-rust
use manifold_rust::linalg::Vec3;
use manifold_rust::manifold::Manifold;
use manifold_rust::types::Error;
let cube = Manifold::cube(Vec3::new(1.0, 1.0, 1.0), true);
let sphere = Manifold::sphere(0.6, 32);
let result = cube.difference(&sphere);
assert_eq!(result.status(), Error::NoError);
println!("volume = {}", result.volume());
println!("area = {}", result.surface_area());
let mesh = result.get_mesh_gl(0); // vert_properties / tri_verts, ready for a GPU
Messy input — import as soup and let Auto choose the engine:
use manifold_rust::types::{BooleanConfig, BooleanEngine};
// Imports geometry the strict pipeline would reject as NotManifold.
let scan = Manifold::from_mesh_gl_robust(&mesh);
// Per call…
let cut = scan.difference_with_engine(&cutter, BooleanEngine::Auto);
// …or once, process-wide.
BooleanConfig::set_default_engine(BooleanEngine::Auto);
let cut = scan.difference(&cutter);
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):
[dependencies]
manifold-rust = { version = "0.12", features = ["parallel"] }
dotnet add package ManifoldRust
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.
The ManifoldRust package above is a P/Invoke binding: it loads this Rust cdylib and calls
into it. manifold-sharp is the other
thing you might want — a complete pure C# port of manifold-rust, with no native library
at all, so it runs anywhere .NET runs, browser-wasm included. It is bit-exact with this
crate on identical inputs, and it lives as a submodule of
agg-sharp.
The two projects check each other: manifold-sharp's oracle test lane runs the same operations through its port and through this library via the binding, then compares the exported meshes row for row with no slack.
#[ignore]d tests are debug-build-speed
only). Details in PORTING_PLAN.md.parallel
feature roughly doubles throughput. Reproduce with
cargo run --release --example perf_test and --example large_scene_test.Known limits, honestly:
Cancelled rather than wrong. Speeding up the exact-predicate fallback is the top
open item.parallel feature is native-only.Error::NotClosed.cargo build
cargo test --release
Exact-match validation against the upstream C++ (needs the submodule):
git submodule update --init --recursive
./validate-reference.ps1 # or: ./validate-reference.ps1 -Phase phase8
The WASM demo:
cd demo && bun run build:wasm && bun run dev
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.
Part of the rust-apps suite — Rust graphics and geometry libraries by Lars Brubaker.
Apache-2.0, matching the original Manifold library.
240 commits
1 commits
Rust
90.4%
C#
8.2%
C
1.3%