| Crates.io | wobj |
| lib.rs | wobj |
| version | 0.3.0 |
| created_at | 2026-01-13 12:21:30.092321+00 |
| updated_at | 2026-01-17 12:23:17.163367+00 |
| description | Wavefront OBJ polygonal geometry and MTL material parser library |
| homepage | |
| repository | https://github.com/AmionSky/wobj |
| max_upload_size | |
| id | 2040026 |
| size | 60,245 |
Wavefront OBJ polygonal geometry and MTL material parser library.
OBJ parsing only supports polygonal geometry and ignores all other statements.
MTL parsing supports both the original spec and the PBR extensions.
To load an OBJ file:
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bytes = std::fs::read("assets/cube.obj")?;
let obj = wobj::Obj::parse(&bytes)?;
// To get the meshes
for mesh in &obj.meshes() {
println!("Name: {:?}", mesh.name());
// To triangulate the meshes
let (indicies, verticies) = mesh.triangulate()?;
}
Ok(())
}
To load a material:
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bytes = std::fs::read("assets/cube.mtl")?;
let mtl = wobj::Mtl::parse(&bytes)?;
let material: Option<&wobj::Material> = mtl.get("CubeMaterial");
Ok(())
}
Since OBJ files can use a different MTL file for each material, if we want to load all used materials without wasting work:
fn main() -> Result<(), Box<dyn std::error::Error>> {
let obj_path = std::path::Path::new("assets/cube.obj");
let parent_path = obj_path.parent().unwrap();
// Load the OBJ
let obj = wobj::Obj::parse(&std::fs::read(obj_path)?)?;
// Use a HashMap to store loaded MTLs
let mut mtls = std::collections::HashMap::new();
// Iterate through all meshes in the OBJ
for mesh in &obj.meshes() {
// Check if the mesh has a material
if let Some(mtllib) = mesh.mtllib()
&& let Some(material_name) = mesh.material()
{
// Load the MTL if it has not been loaded before
if !mtls.contains_key(mtllib) {
// MTL-lib path is relative to the OBJ file
let mtl_path = parent_path.join(mtllib);
let mtl = wobj::Mtl::parse(&std::fs::read(mtl_path)?)?;
mtls.insert(mtllib, mtl);
}
// Get the material
let material = mtls
.get(mtllib)
.and_then(|m| m.get(material_name))
.expect("Material not found");
// Use the material
println!("Material '{material_name}': {material:?}");
}
}
Ok(())
}
Licensed under either of
at your option.