mcubes 0.1.7

The Marching Cubes algorithm for creating isosurfaces
Documentation

Mcubes: Marching Cubes Isosurface library

Crate Docs PyPI

Home page

Uses the Marching Cubes algorithm to create isosurfaces in Rust or Python, from volume data. Designed to be easy to integrate in applications.

Electron density demo

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.

Surface demo

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. Surface mesh

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.