nom-obj 0.2.0

A simple obj/mtl parser written with nom.
Documentation

nom-obj

Build Status Crates.io Version

An obj/mtl (wavefront 3d model format) file format parser written with nom.

https://en.wikipedia.org/wiki/Wavefront_.obj_file

This crate was designed to parse an obj, and any referenced mtl files that it points to. It doesn't try to implement the entire spec, but instead just relies on triangulated meshes. The purpose was to provide a model parser for sg-engine. Since the purpose was to generate a structure of data for the GPU to consume, I went with the opinionated stance of interleaved vertex data (vertex/texture/normal information). Both glutin and vulkano require implementing a trait on a vertex (either using a macro or manually), so we have to copy the vertex data into our desired format.

let obj = Obj::read_file("assets/cube.obj")?;

// Multiple mesh objects are supported, stored in objects[] vec
let Interleaved{ v_vt_vn, idx } = obj.objects[0].interleaved();

// Copy interleaved vertex information
let verts = v_vt_vn.iter()
	.map(|&(v,vt,vn)| Vertex::create(v.0, v.1, v.2, vt.0, vt.1, vt.2, vn.0, vn.1, vn.0) )
	.collect::<Vec<_>>();

assert!(verts.len() > 0);

let indices = idx.iter()
	.map(|x:&usize| *x as u16)
	.collect::<Vec<_>>();

use std::path::Path;
let material_path = obj.material.diffuse_map.clone();
let diffuse_map = image::open(material_path).expect("unable to open image file from material");

Todo:

  • upgrade nom to 5.1+
  • update code to rust 2018
  • some usage examples are needed. For now it can be seen in sg-engine
  • fix paths to assets (probably only works on unix currently)
  • file paths for materials need some attention in Windows.
  • Support multiple materials per mtl file - multiple materials can be defined in an mtl file.

Notes:

  • obj and mtl parsers are implemented in terms of nom parser combinators, and while the learning curve was a bit high, I really enjoyed writing parsers this way. It's a very different experience from classical manual parsing. obj and mtl are plain text formats. Thanks Geal, nom is an excellent tool. Be sure to check out nom for your parsing needs in Rust.