Skip to main content

Crate wavefront_obj_io

Crate wavefront_obj_io 

Source
Expand description

Streaming, callback-based Wavefront OBJ and MTL reader and writer with matched read/write traits.

§Why

Most OBJ crates on crates.io eagerly load a file into a Mesh struct. That works great when the input fits in memory and you don’t care about preserving exact byte layout. This crate fills the opposite niche:

  • Streaming. read_obj_file walks the file once and dispatches to trait callbacks - no intermediate allocation per element. You can process arbitrarily large meshes by writing your own ObjReader that pushes data straight into the buffer of your choice.
  • Round-trip fidelity. ObjReader and ObjWriter are matched trait pairs: every directive a reader can produce, a writer can emit. That makes byte-equal round trips of OBJ files trivial.
  • Configurable float precision. Read and write f32 or f64 via the ObjFloat generic parameter.
  • Strict-by-default with explicit opt-in for lenient parsing. ObjReader::read_unknown returns an error by default; override it to silently skip directives you don’t care about (e.g. NURBS).

If what you want is let mesh = obj::load(path)?, use tobj instead - that is the right tool for that job.

§Supported directives

Core geometry: v, vt, vn, f, o, # comments.

Standard auxiliary directives have first-class trait methods on both ObjReader and ObjWriter: mtllib, usemtl, g, s (with SmoothingGroup), l, p.

Anything else (NURBS / free-form geometry, display attributes, vendor extensions) routes to ObjReader::read_unknown - reject or ignore as you see fit.

MTL (material library) files are handled by the matched MtlReader / MtlWriter pair via read_mtl_file. Supported directives: newmtl, Ka, Kd, Ks, Ke, Ns, Ni, d, Tr, illum, and the texture-map family (map_Ka, map_Kd, map_Ks, map_Ke, map_Ns, map_d, bump / map_bump, disp, decal, refl). Map options (-bm, -clamp, -o, -s, …) are passed through verbatim to keep round trips byte-equal.

§Quick start

use wavefront_obj_io::{ObjReader, read_obj_file};
use std::io::Cursor;

#[derive(Default)]
struct CountVertices(usize);

impl ObjReader<f32> for CountVertices {
    fn read_comment(&mut self, _: &str) {}
    fn read_object_name(&mut self, _: &str) {}
    fn read_vertex(&mut self, _: f32, _: f32, _: f32, _: Option<f32>) {
        self.0 += 1;
    }
    fn read_texture_coordinate(&mut self, _: f32, _: Option<f32>, _: Option<f32>) {}
    fn read_normal(&mut self, _: f32, _: f32, _: f32) {}
    fn read_face(&mut self, _: &[(usize, Option<usize>, Option<usize>)]) {}
}

let obj = "v 0 0 0\nv 1 0 0\nv 0 1 0\n";
let mut counter = CountVertices::default();
read_obj_file(Cursor::new(obj), &mut counter).unwrap();
assert_eq!(counter.0, 3);

Indices follow the Wavefront convention and are kept 1-based throughout the API.

Structs§

IoMtlWriter
File-backed MtlWriter. Mirrors IoObjWriter.
IoObjWriter

Enums§

MapKind
Texture-map directive kind.
MtlError
Error type returned by read_mtl_file.
MtlParseErrorKind
Structured description of an MTL syntax problem.
ObjError
Error type returned by read_obj_file.
ParseErrorKind
Structured description of an OBJ syntax problem.
SmoothingGroup
Smoothing group selector for the s directive.

Traits§

MtlReader
Trait for reading MTL (material library) data.
MtlWriter
Trait for writing MTL data. Mirror of MtlReader.
ObjFloat
Trait for floating point types that can be used in OBJ files. This allows the library to work with both f32 and f64 precision.
ObjReader
Trait for reading OBJ file data with configurable float precision.
ObjWriter
Trait for writing OBJ file data with configurable float precision.

Functions§

read_mtl_file
read_obj_file