Crate tobj [−] [src]
Tiny OBJ loader, inspired by Syoyo's excellent tinyobjloader. Aims to be a simple and lightweight option for loading OBJ files, just returns two vecs containing loaded models and materials. All models are made of triangles, any quad or polygon faces in an OBJ file will be converted to triangles. Note that only polygons that are trivially convertible to triangle fans are supported, arbitrary polygons may not behave as expected. The best solution would be to re-export your mesh using only triangles in your modeling software.
It is assumed that all meshes will at least have positions, but normals and texture coordinates
are optional. If no normals or texture coordinates were found then the corresponding vecs for
the mesh will be empty. Values are stored packed as floats in vecs, eg. the positions member of
a loaded mesh will contain [x, y, z, x, y, z, ...]
which you can then use however you like.
Indices are also loaded and may re-use vertices already existing in the mesh, this data is
stored in the indices
member.
Standard MTL attributes are supported as well and any unrecognized parameters will be stored in a HashMap containing the key-value pairs of the unrecognized parameter and its value.
Example
In this simple example we load the classic Cornell Box model that only defines positions and
print out its attributes. This example is a slightly trimmed down version of print_model_info
and print_material_info
combined together, see them for a version that also prints out
normals and texture coordinates if the model has them.
use std::path::Path; use tobj; let cornell_box = tobj::load_obj(&Path::new("cornell_box.obj")); assert!(cornell_box.is_ok()); let (models, materials) = cornell_box.unwrap(); println!("# of models: {}", models.len()); println!("# of materials: {}", materials.len()); for (i, m) in models.iter().enumerate() { let mesh = &m.mesh; println!("model[{}].name = \'{}\'", i, m.name); println!("model[{}].mesh.material_id = {:?}", i, mesh.material_id); println!("Size of model[{}].indices: {}", i, mesh.indices.len()); for f in 0..mesh.indices.len() / 3 { println!(" idx[{}] = {}, {}, {}.", f, mesh.indices[3 * f], mesh.indices[3 * f + 1], mesh.indices[3 * f + 2]); } // Normals and texture coordinates are also loaded, but not printed in this example println!("model[{}].vertices: {}", i, mesh.positions.len() / 3); assert!(mesh.positions.len() % 3 == 0); for v in 0..mesh.positions.len() / 3 { println!(" v[{}] = ({}, {}, {})", v, mesh.positions[3 * v], mesh.positions[3 * v + 1], mesh.positions[3 * v + 2]); } } for (i, m) in materials.iter().enumerate() { println!("material[{}].name = \'{}\'", i, m.name); println!(" material.Ka = ({}, {}, {})", m.ambient[0], m.ambient[1], m.ambient[2]); println!(" material.Kd = ({}, {}, {})", m.diffuse[0], m.diffuse[1], m.diffuse[2]); println!(" material.Ks = ({}, {}, {})", m.specular[0], m.specular[1], m.specular[2]); println!(" material.Ns = {}", m.shininess); println!(" material.d = {}", m.dissolve); println!(" material.map_Ka = {}", m.ambient_texture); println!(" material.map_Kd = {}", m.diffuse_texture); println!(" material.map_Ks = {}", m.specular_texture); println!(" material.map_Ns = {}", m.normal_texture); println!(" material.map_d = {}", m.dissolve_texture); for (k, v) in &m.unknown_param { println!(" material.{} = {}", k, v); } }
Rendering Examples
For an example of integration with glium to make a simple OBJ viewer, check out tobj viewer. Some sample images can be found in tobj viewer's readme or in this gallery.
The Rungholt model shown below is reasonably large (6.7M triangles, 12.3M vertices) and is loaded in 8.765s (+/- .56s) using a peak of ~1GB of memory on a Windows 8 machine with an i7-4790k and 16GB of 1600Mhz DDR3 RAM on rustc 1.1.0-nightly 97d4e76c2. The model can be found on Morgan McGuire's meshes page and was originally built by kescha. Future work will focus on improving performance and memory usage.
For an example of integration within a ray tracer, check out tray_rust's mesh module. The Stanford Buddha and Dragon from the Stanford 3D Scanning Repository both load quite quickly. The Rust logo model was made by Nylithius on BlenderArtists. The materials used are from the MERL BRDF Database.
Structs
Material |
A material that may be referenced by one or more meshes. Standard MTL attributes are supported.
Any unrecognized parameters will be stored as key-value pairs in the |
Mesh |
A mesh made up of triangles loaded from some OBJ file |
Model |
A named model within the file, associates some mesh with a name that was specified with an |
Enums
LoadError |
Possible errors that may occur while loading OBJ and MTL files |
Functions
load_mtl |
Load the materials defined in a MTL file Returns a pair with a Vec holding all loaded materials and a HashMap containing a mapping of material names to indices in the Vec. |
load_obj |
Load the various objects specified in the OBJ file and any associated MTL file Returns a pair of Vecs containing the loaded models and materials from the file. |
print_material_info |
Print out all loaded properties of some materials |
print_model_info |
Print out all loaded properties of some models and associated materials |
Type Definitions
LoadResult |
LoadResult is a result containing all the models loaded from the file and any materials from referenced material libraries, or an error that occured while loading |
MTLLoadResult |
MTLLoadResult is a result containing all the materials loaded from the file and a map of MTL name to index or the error that occured while loading |