Docs/Tutorials/CSG Operations

What is CSG?

Constructive Solid Geometry (CSG) lets you combine primitive shapes using Boolean set operations. MeshCraft supports three operations:

OperationElementResult
Union<union>All children merged into one solid (OR)
Difference<difference>Children marked role="cutter" are subtracted from the rest (NOT)
Intersection<intersection>Only the overlapping volume of all children (AND)

CSG is evaluated using the Manifold v3 library, which produces real boolean geometry. The result is cached and re-evaluated when the scene is modified.

Example: Box Minus Sphere (Difference)

<difference name="HollowBox" material="stone">
  <box    name="body"   size="2 2 2"/>
  <sphere name="cavity" radius="0.9" role="cutter"/>
</difference>

The box has a spherical cavity carved out. The key is role="cutter" on the sphere — without it, the sphere would not be treated as a subtractor.

Example: Two Spheres Merged (Union)

<union name="TwoSpheres" material="glass">
  <sphere name="left"  radius="0.6" position="-0.4 0 0"/>
  <sphere name="right" radius="0.6" position=" 0.4 0 0"/>
</union>

Example: Box ∩ Sphere (Intersection)

<intersection name="RoundedBlock" material="metal">
  <box    name="block"  size="1.5 1.5 1.5"/>
  <sphere name="sphere" radius="0.9"/>
</intersection>

Only the volume inside both the box and sphere is kept — producing a rounded cube.

Adding CSG from the Editor

Use the Add menu: Add → CSG → Union / Difference / Intersection.

A new CSG node appears in the hierarchy. You can then drag existing objects into it, or add new primitive children via the Add menu or keyboard shortcuts while the CSG node is selected in the hierarchy.

Nested CSG

CSG operations can be nested — a <difference> child can itself be a <union>:

<difference name="Complex">
  <union name="Base">
    <box    name="a" size="2 1 2"/>
    <sphere name="b" radius="0.7" position="0 0.8 0"/>
  </union>
  <cylinder name="hole" radius="0.3" height="3" role="cutter"/>
</difference>

Test Scene

The repository includes test/csg_test.mc3.xml with three CSG examples you can open directly:

./cmake-build-debug/MeshCraft test/csg_test.mc3.xml

CSG Limitations

ℹ️
  • CSG is evaluated by the Manifold library, which requires non-degenerate, watertight meshes. Very thin or coplanar surfaces may produce unexpected results.
  • CSG meshes are cached per Mc3Object*. The cache is cleared on every edit (undo push). If you have many complex CSG objects, edits may feel slightly slower.
  • The CSG result falls back to rendering children individually if Manifold returns an empty mesh.
  • CSG geometry is not resolved when exporting via mc3togltf — the individual child primitives are exported as separate glTF meshes. This limitation may be addressed in a future release.