Meshes

Deborah Schmidt
Head of Helmholtz Imaging Support Unit, MDC Berlin
Sep 29, 2026
Slides available at https://ida-mdc.github.io/workshop-visualization/2026-workshop/meshes/

Converting voxel datasets into meshes

  • Fixed thresholds: Used to generate meshes by separating foreground from background using a set intensity threshold.
  • Content-based annotations: Create precise meshes by using annotated regions to define boundaries.
  • Machine learning & interactive labeling: Interactive tools combine user input with AI predictions to refine boundaries.

Converting voxel datasets into meshes

Marching Cubes

  • One cube of eight voxels at a time - each corner above or below the threshold
  • 8 corners → 256 patterns, looked up in a fixed table of which triangles to draw
  • A vertex lands where the threshold was actually crossed along an edge
The 2D case (marching squares)

The 2D case (marching squares)

Converting voxel datasets into meshes

The rules, applied

Converting voxel datasets into meshes

Other ways to place the surface

  • Marching cubes - a vertex on every crossing edge, from a 256-case lookup table
  • Flying edges - the same surface, in four passes over the grid; parallel, and what VTK runs today
  • Surface nets - one vertex per cell, at the average of that cell’s crossings
  • Dual contouring - surface nets plus the gradients at the crossings, so sharp edges survive
The same field and the same grid. Left, a vertex on each crossing edge; right, one vertex per crossing cell.

The same field and the same grid. Left, a vertex on each crossing edge; right, one vertex per crossing cell.

Converting voxel datasets into meshes

Make it smoother

  • Binary mask in → a lattice, whichever method you picked - every boundary voxel rounded in or out
  • Blurred mask in → smooth, details get lost
  • Probability map in → smooth and the right size
  • Anisotropic voxels: give any distance or blur step the voxel size, or the surface is wrong along the coarse axis

Converting voxel datasets into meshes

The one-voxel border

  • An object touching the edge of the volume extracts as an open surface
  • One voxel of background on every face closes it - np.pad(mask, 1).

Converting voxel datasets into meshes

The whole conversion

  1. Load the volume - and its voxel size
  2. Threshold
  3. Pad with one voxel of background
  4. Blur the mask into a field
  5. Extract - contour(method="flying_edges")
  6. Smooth
  7. Decimate
  8. Export - STL, PLY or glTF

voxel_to_mesh.ipynb

Large meshes

Three ways to make it cheaper

  • Decimation → fewer triangles
  • Compression → fewer bytes, same triangles back
  • Multi-resolution streaming → fewer triangles loaded for this view
  • They combine
Quadric edge collapse on a laser scan of the Stanford Armadillo.

Rendering meshes

From a script

Rendering meshes

Rendering meshes with Blender