Marching Tetrahedra¶
Marching tetrahedra splits every cell into six tetrahedra and extracts the surface per tetrahedron. No sign pattern of a tetrahedron has more than one valid triangulation, so the mesh comes out closed and consistent by construction. The price is roughly 2-3x more triangles than marching cubes, with worse triangle shapes and a slight directional grain from the cell split. The method goes back to Doi and Koide [1991].
import torch
import isoext
from isoext import viewer
from isoext.sdf import SphereSDF
Basic Usage¶
The interface matches the other extraction methods: a grid with scalar values in, vertex and face tensors out.
grid = isoext.UniformGrid([32, 32, 32])
grid.set_values(SphereSDF(radius=0.7)(grid.get_points()))
vertices, faces = isoext.marching_tetrahedra(grid)
print(f"marching_tetrahedra: {faces.shape[0]:,} triangles")
v_mc, f_mc = isoext.marching_cubes(grid)
print(f"marching_cubes: {f_mc.shape[0]:,} triangles")
viewer.embed(vertices, faces, color="tomato", flat_shading=True)
marching_tetrahedra: 13,416 triangles
marching_cubes: 4,508 triangles
How It Works¶
Each cube is split into six tetrahedra that all share the cube’s main diagonal. The purple lines below are the extra edges the split introduces: one diagonal per face, plus the main diagonal itself:
A tetrahedron has 4 corners and only 16 sign patterns, each producing one or two triangles with no choices to make, so the mesh is consistent by construction. The price shows on a field with one corner inside: the surface also crosses the diagonals, and marching cubes’ single triangle becomes six:
v, f = isoext.marching_tetrahedra(cell)
print(f"{f.shape[0]} triangle(s)")
viewer.embed(v, f, color="mediumpurple", flat_shading=True, side="double", height=300,
grid=cell, draw=lambda s: viewer.add_lines(s, diagonals, color="orchid"))
6 triangle(s)
Tessellation¶
The wireframes on a coarse grid show where the extra triangles go and the diagonal grain left by the six-tetrahedra split. Marching cubes first, marching tetrahedra second.
coarse = isoext.UniformGrid([16, 16, 16])
coarse.set_values(SphereSDF(radius=0.7)(coarse.get_points()))
v, f = isoext.marching_cubes(coarse)
viewer.embed(v, f, color="steelblue", wireframe=True)
v, f = isoext.marching_tetrahedra(coarse)
viewer.embed(v, f, color="tomato", wireframe=True)
When to Use It¶
Pick marching tetrahedra when guaranteed topology matters more than triangle count, for example as input to solvers or simplification passes that assume a closed manifold. For visual quality at the same budget, marching cubes gives cleaner triangles.
References¶
Akio Doi and Akio Koide. An efficient method of triangulating equi-valued surfaces by using tetrahedral cells. IEICE Transactions on Information and Systems, E74-D(1):214–224, 1991.