5 releases (2 stable)

Uses old Rust 2015

1.0.1 Feb 13, 2021
1.0.0 Apr 6, 2020
0.1.2 Jun 20, 2017
0.1.1-pre Jun 20, 2017
0.1.0 Jun 20, 2017

#44 in Data formats

Download history 6/week @ 2024-02-26 85/week @ 2024-04-01

85 downloads per month

MIT license

407 lines


Build Status license


3D mesh manipulation library.

Supported formats

All formats are enabled by default when including mash as a dependency.

In order to pick and choose which formats are supported, explicitly set which features you want to enable.

mash = { version = "1.0", default-features = false, features = ["wavefront"]}


Models are first loaded into memory into format-specific structures, to allow the most flexibility. You will find documentation for these types inside the relevant load/<format> module.

Once the relevant objects/groups/triangles are separated out, the models can then converted into a format-independent representation - mash::Model.

The basic workflow looks like this

extern crate mash;

use mash::load;

type Vertex = mash::Vector;
type Index = u32;
type Model = mash::Model<Vertex, Index>;

fn main() {
    // Load the shape into a wavefront-specific data structure.
    let world = load::wavefront::from_path("res/world.obj").unwrap();

    // Rather than converting the entire world into a single model, let's extract
    // every object labelled 'door'.
    let doors: Vec<Model> = world.objects().filter(|o| o.name().contains("door")).map(|object| {
        // Convert each object into its own mesh.

    // We can also load the entire world into a single model if we wanted.
    let entire_world = Model::new(world).unwrap();

    // Skip every second triangle if that's your kind of thing.
    let half_triangles = entire_world.mesh.triangles().enumerate().filter(|&(idx,_)| idx%2 == 0).map(|(_,t)| t);
    let half_world: Model = Model { mesh: half_triangles.collect() };


~72K SLoC