| Crates.io | mcubes |
| lib.rs | mcubes |
| version | 0.1.7 |
| created_at | 2025-06-05 01:48:21.362+00 |
| updated_at | 2025-11-10 20:46:32.525519+00 |
| description | The Marching Cubes algorithm for creating isosurfaces |
| homepage | |
| repository | https://github.com/David-OConnor/mcubes |
| max_upload_size | |
| id | 1701012 |
| size | 4,408,780 |
Uses the Marching Cubes algorithm to create isosurfaces in Rust or Python, from volume data. Designed to be easy to integrate in applications.

Based loosely on PyMarchingCubes.
Outputs a native Mesh, which contains native Vertexs. In practice, you will convert these to whatever
mesh struct your application uses. For example, graphics::Mesh.
Uses lin-alg for its Vec3 type; this is the library's only dependency.

Used by the Daedalus molecule viewer to view experimentally-derived electron density from protein crystals.
The grid must be regularly spaced, along 3 orthogonal axes. Values are either a Vec<f32>. The packing order is important;
Z is the fastest-changing axis (inner-most loop).
This trait contains a single method: To get the value at that point.
Example creating a solvent-accessible-surface mesh by setting the ISO level to 0, and
rendering only the vertices.

Example use:
use mcubes::{MarchingCubes, MeshSide};
/// An example data struct from your application.
pub struct ElectronDensity {
pub coords: Vec3,
pub density: f64,
}
fn create_mesh(hdr: &MapHeader, density_pts: &[ElectronDensity], iso_level: f32) {
let density: Vec<_> = density_pts.iter(|p| p.density).collect();
let mc = MarchingCubes::new(
// Number of grid points along each axis
(hdr.nx as usize, hdr.ny as usize, hdr.nz as usize),
// Grid dimensions per unit cell along each axis
(hdr.cell[0], hdr.cell[1], hdr.cell[2]),
// Sampling interval along each axis. (Usually the same as grid point number of grid points.)
(hdr.mx as f32, hdr.my as f32, hdr.mz as f32),
density,
// The value to draw the isosurface at.
iso_level,
);
// Use MeshSide::Inside or MeshSide::Outside as required.
let mesh = mc.generate(MeshSide::Both);
// Example of converting the generic output mesh to a graphic engine's:
let vertices = mesh
.vertices
.iter()
.map(|v| graphics::Vertex::new(v.posit.to_arr(), v.normal))
.collect();
scene.meshes[MESH_DENSITY_SURFACE] = graphics::Mesh {
vertices,
indices: mesh.indices,
material: 0,
};
}
Why another Marching Cubes library? I couldn't figure out how to use the existing ones.