Library / SDK
elalish/manifold avatar
elalish/manifold

Manifold: a mesh library that refuses broken input

Geometry library for topological robustness

2,323 stars261 forksC++Apache-2.0

At a glance

What is it?
Manifold is a C++ geometry library whose primary goal is guaranteed manifold output with no caveats, taking only meshes that represent a solid and saying so when they do not. It ships bindings for twelve languages, four of them maintained in-repository, and a native Rust port that passes the full test suite without a C++ dependency.
Who is it for?
Adopt Manifold when your pipeline produces or validates watertight solids and boolean reliability is what stopped you using mesh CSG before, and construct your geometry with its OpenSCAD-style constructors or its level set function rather than meshing a voxel grid yourself. Do not adopt it as a mesh repair tool, since non-manifold input returns an error status rather than being fixed.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The guarantee is the product

Manifold is a geometry library dedicated to creating and operating on manifold triangle meshes. A manifold mesh is one that represents a solid object, which the README calls very important in manufacturing, CAD and structural analysis, since a mesh that does not represent a solid cannot be printed, machined or meshed for analysis.

The stated priorities are ordered deliberately. The primary goal is reliability, described as guaranteed manifold output without caveats or edge cases. The secondary goal is performance, through efficient algorithms that make extensive use of parallelization, or of pipelining when only a single thread is available.

That ordering is the whole pitch. Boolean operations on triangle meshes are notorious for producing garbage under exactly the conditions that matter, so a library whose selling point is that it will not do that is solving the problem that makes people avoid mesh CSG entirely. The guarantee is stated without a caveat clause, which is unusual and is the reason the user list includes Blender, OpenSCAD, Godot Engine, Babylon.js and BRL-CAD rather than only research projects.

Arbitrary vertex properties are supported alongside the geometry, and materials can be mapped for rendering use cases, so the output is a mesh you can display rather than a triangle soup you have to re-attribute.

The library also extends past polygons: it supports arbitrary vertex properties and offers a level set function for evaluating signed-distance functions, which the README says improves significantly over Marching Cubes.

You have to arrive with a solid already

The contract is the first thing to understand, and the README is blunt about it. As such you need manifold meshes as input.

The library will create them for you, in two ways. The first is a set of constructors inspired by the OpenSCAD API, which is a deliberate compatibility choice aimed at the large existing OpenSCAD audience. If your solids are already expressed in OpenSCAD, the primitives and operations you wrote carry across.

The second is the level set function, which evaluates signed-distance functions. This is the more interesting path for procedural geometry: you describe a shape as a function that returns distance from the surface, anywhere positive outside and negative inside, and the library produces the mesh. Compared to Marching Cubes, which samples a scalar field on a regular grid and emits triangles between sample points, a level set approach places vertices where the surface actually is, which the README says improves the result significantly.

You can also pass your own mesh data in. What you cannot do is pass a mesh that is not a solid, because the README says you will get an error status back.

That is the design trade in one sentence. Manifold will not repair a broken mesh, convert an open surface, or guess at a watertight boundary. It refuses the input and tells you. For a pipeline that generates its own geometry, or that validates before it operates, that is exactly right. For a pipeline that ingests arbitrary meshes from a modelling tool, that is a conversion problem you have to solve first.

Twelve languages, four maintained here

The bindings table is the most useful thing in the README for anyone deciding, because it has a maintenance column that distinguishes what this project owns from what it hopes someone else maintains.

Marked internal, meaning maintained in this repository: C, which is the core with no packager listed, TypeScript and JavaScript on npm as `manifold-3d`, and Python on PyPI as `manifold3d`. Three packaged bindings under the author's control.

Marked external: C++ through vcpkg as `manifold`, Java on Maven as `manifold3d` from CommonWealthRobotics, Clojure as `clj-manifold3d`, C# on NuGet as `ManifoldNET`, Julia as `ManifoldBindings.jl`, OCaml as `OManifold`, two separate Rust crates on crates.io, and Swift via SPM as `Manifold-Swift`.

Note how the package names differ from the project name. The repository is `manifold`, the Python package is `manifold3d`, the npm package is `manifold-3d`, and the NuGet package is `ManifoldNET`. Four spellings, so a search for the library in a new language needs the language, not the project name.

The maintenance column is the honest part. If you are on Java, C#, Julia or OCaml, you are depending on a binding someone else maintains, and the README is not making a claim about its current state. The core is where the guarantee lives; a binding only exposes it.

manifold-rust is a port, not a wrapper

Among the external bindings, one is called out in prose rather than only in the table, and it deserves attention because of what it claims.

There is also a native Rust port, manifold-rust, which passes Manifold's full test suite with identical results and has no C++ dependency. The README adds that from a user's perspective it works like a binding.

Read that carefully. It is not a wrapper that calls into the C++ library through FFI, which is what the other Rust entry, `manifold-csg`, is. It is a reimplementation that produces identical output on the full test suite, which is the strongest correctness claim a port can make and the reason it can be treated as a drop-in.

The distinction matters for deployment. A binding carries the C++ toolchain into your build and the resulting binary size of the library with it. A native port carries none of that, which in a serverless function, a WASM build or a constrained container is often the difference between shipping the dependency and not.

The trade is that two implementations can diverge. The test suite is what holds them together, and it is worth checking how often it runs against the port rather than assuming the claim stays true.

The Python wheel build, and what cibuildwheel skips

The Python package is built with scikit-build-core and nanobind, and the configuration is worth reading because it explains both the parallel backend and the wheel matrix.

toml
[build-system]
requires = [
    "nanobind>=1.8.0,<4.0.0",
    "scikit-build-core",
]

CMake arguments turn the features on and off explicitly: `MANIFOLD_PYBIND=ON` and `MANIFOLD_PAR=ON` for the binding and the parallel backend, with `MANIFOLD_CBIND=OFF`, `MANIFOLD_TEST=OFF` and `BUILD_SHARED_LIBS=OFF`.

The flag name is a historical artefact worth noting. The option is `MANIFOLD_PYBIND` while the binding library is nanobind, so a CMake flag named for pybind11 is being passed to configure nanobind. Anyone grepping the build for pybind will find the flag and not the dependency.

The wheel matrix narrows rather than widens. cibuildwheel pins `manylinux_2_28` and `musllinux_1_2` images, and then the skip list is `*-win32`, `*_i686` and `*-musllinux*`, meaning no 32-bit Windows, no i686 and no musl builds are produced in that configuration. OneAPI TBB is fetched at build time from a shallow clone pinned to a single release.

toml
before-all = "git clone --depth 1 --branch v2022.3.0 https://github.com/oneapi-src/oneTBB.git"

So the parallel backend has an external dependency pinned in your build, not vendored. And the version in `pyproject.toml` reads 3.5.1 while the repository's releases are at v3.5.4.

The WASM path, and what interoperability costs

There is a browser path, and it is the project's own application rather than a demo.

ManifoldCAD.org is described as a solid modelling web app where you script in JavaScript or TypeScript. It uses the npm package `manifold-3d` built via WebAssembly.

The README is honest about the cost: it is not quite as fast as the raw C++, but it is hard to beat for interoperability.

That sentence is the whole trade. A WASM build cannot call into your native code, so the mesh has to cross a boundary in serialised form and the operation runs in a sandboxed virtual machine. What you get back is a mesh you can send to a server, another worker, or a renderer. For a CAD tool in a browser, or a scriptable viewer that other people can fork and modify, that is the right trade. For a batch job that processes ten thousand meshes an hour in a pipeline you control, it is not.

The Python side has its own equivalent, and it is a notebook. The README links a Colab example demonstrating interop between the `manifold3d` PyPI library and `trimesh`, showing the interactive model in the notebook and saving 3D model output.

Both of these exist for the same reason. Manifold is a C++ library, and the two places it reaches most easily are a browser and a Python notebook. If your work happens in neither, you are compiling C++ and that is fine, but it is worth knowing which environments the project actively supports.

Where Manifold is the wrong tool

Four cases, three of them stated by the library itself.

If your input is not a solid, this is the wrong tool. Manifold requires manifold meshes as input and returns an error status otherwise. If your pipeline starts with an open surface, a point cloud, a scanned mesh with holes, or anything a modelling tool exported without checking watertightness, you need a repair and validation step before Manifold is involved at all.

If your shapes come from voxels, the default approach is already handled. When your geometry is defined by a field rather than a solid, the library's own level set function is the path, and it says it improves significantly on Marching Cubes. Reaching for a general voxel-to-mesh tool first and feeding the result to Manifold adds a conversion step the library was built to avoid.

If you need the parallel backend without a build-time dependency on TBB, check before you start. `MANIFOLD_PAR=ON` is on in the Python wheel configuration, and TBB is cloned at build time from a pinned release rather than linked from your system.

The fourth is about the guarantee's scope. Guaranteed manifold output applies to the operations Manifold implements. It does not mean your final exported file is valid for a particular slicer or analyser, and the README says nothing about that step. A library that guarantees its own output is still one end of a pipeline.

Editorial conclusion

Adopt Manifold when your pipeline produces or validates watertight solids and boolean reliability is what stopped you using mesh CSG before, and construct your geometry with its OpenSCAD-style constructors or its level set function rather than meshing a voxel grid yourself. Do not adopt it as a mesh repair tool, since non-manifold input returns an error status rather than being fixed. Verify first which binding you are actually depending on, because only C, TypeScript and JavaScript, and Python are marked internal maintenance, and check that the TBB clone in the build matches the oneTBB release you expect.

Frequently asked questions

What does Manifold require as input?

Manifold meshes, meaning meshes that represent a solid object. The library can create them itself through constructors inspired by the OpenSCAD API or through a level set function for signed-distance fields; if you pass your own mesh data and it is not manifold, you get an error status back.

Which languages can I use Manifold from?

The README's bindings table lists C, C++ via vcpkg, TypeScript and JavaScript on npm as manifold-3d, Python on PyPI as manifold3d, Java on Maven, Clojure, C# on NuGet as ManifoldNET, Julia, OCaml, two Rust crates and Swift via SPM. C, TS/JS and Python are marked internal maintenance; the rest are external.

How does Manifold compare to Marching Cubes?

Its level set function evaluates signed-distance functions directly, and the README says this improves significantly over Marching Cubes, which samples a scalar field on a grid and fits triangles between sample points.

What is manifold-rust and is it a binding?

It is a native Rust port of the library with no C++ dependency, which the README says passes Manifold's full test suite with identical results. It works like a binding from a user's perspective, but it is a reimplementation rather than a wrapper.

Can I use Manifold in a browser?

Yes, through the npm package manifold-3d built via WebAssembly, which is what ManifoldCAD.org uses. The README notes it is not quite as fast as the raw C++ but hard to beat for interoperability.

What licence is Manifold under?

Apache-2.0, and the Python classifiers list it as OSI Approved under the Apache Software License. Read the LICENSE file for the terms themselves; this is not legal advice.

Official sources

  1. elalish/manifold on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/elalish-manifold.svg)](https://hysenlabs.com/projects/elalish-manifold)