Mesh booleans
Union, intersection and difference of 3D meshes, tested on the inputs that break booleans: identical operands, flush faces, non-manifold edges, meshes that cross themselves. Then the speed, in C++, Python and JavaScript.
Subtract the Stanford dragon from itself and the answer should be nothing. It is a hard test. Every face of one operand lies on a face of the other, so every decision lands exactly on zero. This page puts trueform through that test and three more that break booleans. Then it says what trueform asks of your meshes and how fast it runs.
A mesh boolean returns the union (A ∪ B), the intersection (A ∩ B) or the difference (A ∖ B) of solids stored as surface meshes. It also goes by CSG, mesh subtraction and 3D boolean operations. Below, the dragon is A and a sphere is B. Every output face is coloured by the operand it came from.




Each output is one closed mesh. The orange faces are pieces of the sphere: in the union they are its outside, in the intersection and the difference they wall the cut. Run booleans on a dragon in your browser in the live example. Each language has a full tutorial.
Four inputs that break booleans
A boolean is easy when two surfaces cross cleanly. It is hard where they touch, coincide or cross themselves. The four tests below aim at exactly that. We ran them with trueform 0.10.8 from pip, in Python. The data is the public Stanford dragon, or shapes made from it. Run your own hard cases too; pip install trueform is one line.
The same mesh twice
The dragon has 244,026 triangles. Use it as both operands. Every face now sits on a face of the other mesh, edge on edge and corner on corner.
- A ∪ A returns the dragon: 244,026 triangles, closed.
- A ∩ A returns the dragon: 244,026 triangles, closed.
- A ∖ A returns an empty mesh.
Nothing is nudged to make the case generic. Each contact is classified for what it is, and coincident faces count as coincident.
Flush faces everywhere

We turned the dragon into voxels: a closed mesh of 46,268 triangles, every vertex on a unit grid. Then we moved a copy by one voxel along each axis. Every face of one operand now lies in a plane of the other. Edges run along edges and corners land on corners. The voxel surface also has 45 non-manifold edges, where two voxels meet along an edge and nothing more.
This input has a known answer. Count the voxels. The volume of each output mesh must equal the count exactly.
The picture is the difference. The teal faces are what is left of the first dragon. The orange faces are walls of the moved copy, now cut into the first. The two colours meet only along shared edges and shared planes.
A mesh that crosses itself

Real files often hold two overlapping shells as one mesh. Inside and outside are then ambiguous, and a boolean expression needs them. There are two ways through, both in the CSG module.
Repair, then combine. outer_shell keeps only the faces that bound the outside and drops everything buried in the overlap. The shell is a valid operand for any boolean.
shell = tf.outer_shell(mesh) # C++: tf::make_outer_shell, JavaScript: tf.outerShell
result = tf.boolean_difference(shell, other)
Two dragons in one mesh: 488,052 triangles that cross themselves along the pink curves. The shell has 444,856 triangles. It is closed and crosses itself nowhere.
Keep the overlap as a region. Build a CSG graph with within on. Each operand is then also cut against itself, and domains() returns the overlap pocket as its own closed cell. Pick the cells you need from there. Boolean expressions on the graph still read each operand as one solid, so for an expression, repair first. CSG for engineering works through both.

An open surface
A plane, a terrain or a scanned patch bounds no volume. Declare it a sheet and it becomes a valid operand. It cuts a solid, and difference and intersection return the two halves, each capped and closed. A unit box cut by a plane gives two halves of volume 0.5.
(faces, points), labels, face_labels = tf.boolean_difference(box, plane, sheets=[1])
Many sheets cutting many solids at once are the subject of CSG for engineering.
Why these cases hold
Exact decisions. Every geometric decision runs in integer arithmetic. Float coordinates go onto an int32 lattice, double coordinates onto int64. Each predicate is evaluated in integers wide enough to be exact. A sign test returns minus, zero or plus. Zero means touching, not "close to touching". The method is written up in Fast and Exact Mesh Booleans and Arrangements.
Five kinds of contact. Two triangles can meet vertex to vertex, vertex to edge, edge to edge, vertex to face or edge to face. The default mode states each contact as one of the five. It does not perturb them away. That is why the identical and voxel tests come out exact. Coincident faces are classified as facing the same way or opposite ways.
One arrangement, read once. A boolean is the two-mesh case of trueform's CSG graph. It splits both meshes along the curves where they cross, classifies every piece against the other mesh, and keeps the pieces the operation asks for.
How other libraries handle a touch
The hard cases above all land on exact contact. Libraries take different roads there, and each road has a price. The descriptions come from each library's own documentation.
Sources: Manifold's library notes, CGAL's Boolean Operations on Meshes manual and MeshLib's mesh boolean page, which describes both of its modes. Speed is a separate question, answered below.
trueform also takes the voxel road when it fits. Its volume module samples closed meshes into signed distance fields and combines them by union, intersection and difference. A field boolean is bounded by the grid's spacing; use it for offsets, blends and inputs that must be resampled. See fields on the CSG page.
Preparing operands
Each condition below has a call that handles it, so a pipeline can run on files as they arrive.
- Faces that disagree on their winding. An operand must say where its inside is. Orient it first with
orient_faces_consistently. - An operand that overlaps itself. Repair it with
outer_shell, or keep the overlap as a region with awithinCSG graph, as above. - An open surface. List it in
sheetsand it cuts as a sheet. An open mesh not listed is read as a volume. - Coordinates far apart. Pass double coordinates, or ask for
tf::exact::int64in C++. Decisions then run on the int64 lattice. The API is the same. - CAD solids. B-rep and NURBS go in tessellated, as triangle meshes.
- A long chain of booleans. The points created where two surfaces cross are written back in your input's type, float in, float out, and the next boolean reads them as fresh input. Build one CSG graph instead: one arrangement over every operand, every result read from it.
How fast
The same corpus runs in every language: 1,000 pairs of solid Thingi10K meshes, 200K to 1.5M polygons per pair, each pair randomly rotated and overlapped. Arrays in, arrays out. Apple M4 Max, 16 threads, trueform 0.9.8.

Repeated booleans on the same mesh go faster still. Hold the meshes and move the operand with a transformation. The first boolean builds the spatial tree and the topology; every later one reuses them.
dragon = tf.Mesh(*tf.read_stl("dragon.stl"))
tool = tf.Mesh(*tf.read_stl("tool.stl"))
for T in poses: # 4×4 transformations
tool.transformation = T # no copy, no rebuild
(faces, points), labels, face_labels = tf.boolean_difference(dragon, tool)
The C++ tutorial runs ten booleans on two 500K-polygon dragons this way, with the tree and topology built once.
The protocols, corpus IDs and per-library notes are in the three comparisons:
- Mesh Boolean Library Comparison and Benchmarks at Industry Scale — 2026: eight native libraries.
- Python Mesh Boolean Library Comparison and Benchmarks — 2026: three pip-installable libraries.
- Browser Mesh Boolean Library Comparison and Benchmarks — 2026: three client-side libraries, with a watertightness count.
Every trueform benchmark, by module and language, is on the trueform benchmarks page.
The call
Load a mesh, offset a copy, take the union. The copy shares the original's data and carries only a transformation. Intersection and difference are one word away.
#include <trueform/trueform.hpp>
auto dragon_buffer = tf::read_stl("stanford_dragon.stl");
auto dragon = dragon_buffer.polygons();
auto T = tf::make_transformation_from_translation(
tf::make_vector(0.f, 1.f, 0.f));
auto translated = dragon | tf::tag(T);
// tf::boolean_op::intersection, tf::boolean_op::left_difference
auto [result_buffer, labels, face_labels] = tf::make_boolean(
dragon, translated, tf::boolean_op::merge);
import numpy as np
import trueform as tf
dragon = tf.Mesh(*tf.read_stl("stanford_dragon.stl"))
translated = dragon.shared_view()
T = np.eye(4, dtype=np.float32)
T[:3, 3] = [0.0, 1.0, 0.0]
translated.transformation = T
# tf.boolean_intersection, tf.boolean_difference
(result_faces, result_points), labels, face_labels = \
tf.boolean_union(dragon, translated)
import * as tf from "@polydera/trueform";
const response = await fetch("stanford_dragon.stl");
const bytes = new Uint8Array(await response.arrayBuffer());
const dragon = tf.readStl(bytes);
const translated = dragon.shallowCopy();
translated.transformation = tf.makeTranslation(0, 1, 0);
// tf.async.booleanIntersection, tf.async.booleanDifference
const { mesh, labels, faceLabels } =
await tf.async.booleanUnion(dragon, translated);
Every call returns three things. The first is the output mesh. The second, labels, says which operand each output face came from: 0 or 1. The third maps each output face to its source face, so colours, materials and other attributes follow the geometry. Ask for curves too, and the call also returns the polylines where the two surfaces cross. Install with pip install trueform, npm install @polydera/trueform, or CMake, conan or nuget for C++.
Where to go next
- Tutorials. C++, Python, JavaScript, and variadic booleans in C++ for one arrangement over many meshes.
- Many meshes, sheets and domains. CSG for engineering: hundreds of operands cut into domains, with regions selected by expression or mask.
- Related operations. The crossing curves on their own: mesh intersection curves. Only whether two meshes touch: collision detection.
- Documentation. The CSG module in C++, Python and TypeScript. Run a boolean in your browser in the live example.
- Research. Real-Time Mesh Booleans that Commute with Mesh Idealization, Žiga Sajovic and Dejan Knez, 2025 (doi).
Booleans are one module of trueform. The same engine does spatial queries, topology, remeshing, isocontours, geodesics and more. See trueform.
@article{polydera:mesh-booleans,
title={Mesh booleans},
author={Sajovic, {\v{Z}}iga, Polydera},
year={2026},
url={https://polydera.com/algorithms/mesh-booleans},
organization={Polydera}
}
