obj
stableParse and export Wavefront OBJ and MTL files, providing access to vertices, normals, texture coordinates, faces, and material definitions.
use plugin obj::{parse_obj, parse_obj_file, vertex_count, …} Functions (10)
- parse_obj Parse OBJ text into a mesh data table
- parse_obj_file Parse an OBJ file from disk
- vertex_count Count vertices in a parsed mesh
- face_count Count faces in a parsed mesh
- parse_mtl Parse MTL material text into a table
- normal_count Count normals in a parsed mesh
- texcoord_count Count texture coordinates in a parsed mesh
- bounding_box Compute axis-aligned bounding box of a mesh
- export_obj Serialize mesh data to OBJ text
- export_obj_file Write mesh data to an OBJ file on disk
Overview
obj is a self-contained reader and writer for the Wavefront OBJ geometry
format and its companion MTL material format, with no external dependencies.
Parsing a model returns a plain mesh table with four sections — vertices,
normals, texcoords, and faces — so the geometry is ordinary Zolo data you
can index, count, transform, and feed back to the exporter. Faces store
index triples {v, vt, vn} exactly as written in the file, where -1 marks a
component (texture or normal) that was omitted.
Reach for it whenever you need to load a .obj mesh, inspect its size or
bounds, read material colors out of a .mtl file, or generate and round-trip
OBJ text programmatically. The mental model is: parse with parse_obj /
parse_obj_file (or parse_mtl for materials), inspect with the *_count and
bounding_box queries, then serialize with export_obj / export_obj_file.
Common patterns
Load a mesh and report its size and extents:
use plugin obj::{parse_obj_file, vertex_count, face_count, bounding_box}
let mesh = parse_obj_file("models/cube.obj")
let bb = bounding_box(mesh)
print("{vertex_count(mesh)} verts, {face_count(mesh)} faces")
print("height: {bb["max_y"] - bb["min_y"]}")
Round-trip a mesh: parse OBJ text, then serialize it straight back out:
use plugin obj::{parse_obj, export_obj}
let mesh = parse_obj("v 0 0 0\nv 1 0 0\nv 0 1 0\nf 1 2 3")
print(export_obj(mesh))
Read a material's diffuse color from MTL text:
use plugin obj::{parse_mtl}
let mats = parse_mtl("newmtl red\nKd 1.0 0.0 0.0\nKs 0.5 0.5 0.5")
let red = mats["red"]
print("diffuse: {red["diffuse_r"]}, {red["diffuse_g"]}, {red["diffuse_b"]}")
Parse OBJ text into a mesh data table
Parses Wavefront OBJ text and returns a table with four sections: vertices (list of {x, y, z}), normals (list of {x, y, z}), texcoords (list of {u, v}), and faces (list of face vertex index triples {v, vt, vn}, where -1 means absent).
use plugin obj::{parse_obj}
let mesh = parse_obj("v 0 0 0\nv 1 0 0\nv 0 1 0\nf 1 2 3")
print("vertices: {mesh["vertices"][0]["x"]}")
Faces preserve the full v/vt/vn index triple; absent components read as -1:
use plugin obj::{parse_obj}
let mesh = parse_obj("v 0 0 0\nvt 0 0\nvn 0 1 0\nf 1/1/1 1/1/1 1/1/1")
let corner = mesh["faces"][0][0]
print("v={corner["v"]} vt={corner["vt"]} vn={corner["vn"]}")
Parse an OBJ file from disk
Reads an OBJ file from the given path and returns the same structure as parse_obj. Errors if the file cannot be read.
use plugin obj::{parse_obj_file, vertex_count, face_count}
let mesh = parse_obj_file("models/cube.obj")
print("verts: {vertex_count(mesh)}, faces: {face_count(mesh)}")
Count vertices in a parsed mesh
Returns the number of vertices in a parsed mesh table. Equivalent to reading the length of data["vertices"].
use plugin obj::{parse_obj_file, vertex_count}
let mesh = parse_obj_file("scene.obj")
print("{vertex_count(mesh)} vertices")
Count faces in a parsed mesh
Returns the number of polygon faces in a parsed mesh table.
use plugin obj::{parse_obj_file, face_count}
let mesh = parse_obj_file("scene.obj")
print("{face_count(mesh)} faces")
Parse MTL material text into a table
Parses Wavefront MTL material text and returns a table keyed by material name. Each entry contains name, diffuse_r/g/b, and specular_r/g/b fields from the Kd and Ks directives.
use plugin obj::{parse_mtl}
let mtl_text = "newmtl red\nKd 1.0 0.0 0.0\nKs 0.5 0.5 0.5"
let mats = parse_mtl(mtl_text)
let red = mats["red"]
print("diffuse r: {red["diffuse_r"]}")
A library can contain several materials; each is keyed by its newmtl name:
use plugin obj::{parse_mtl}
let mats = parse_mtl("newmtl gold\nKd 1.0 0.84 0.0\nnewmtl steel\nKd 0.6 0.6 0.65")
print("gold diffuse_g: {mats["gold"]["diffuse_g"]}")
print("steel diffuse_b: {mats["steel"]["diffuse_b"]}")
Count normals in a parsed mesh
Returns the number of vertex normals in a parsed mesh table.
use plugin obj::{parse_obj_file, normal_count}
let mesh = parse_obj_file("scene.obj")
print("{normal_count(mesh)} normals")
Count texture coordinates in a parsed mesh
Returns the number of texture coordinate pairs (UV) in a parsed mesh table.
use plugin obj::{parse_obj_file, texcoord_count}
let mesh = parse_obj_file("scene.obj")
print("{texcoord_count(mesh)} uvs")
Compute axis-aligned bounding box of a mesh
Computes the axis-aligned bounding box of all vertices in the mesh. Returns {min_x, min_y, min_z, max_x, max_y, max_z}. Useful for centering or scaling a model.
use plugin obj::{parse_obj_file, bounding_box}
let mesh = parse_obj_file("character.obj")
let bb = bounding_box(mesh)
let height = bb["max_y"] - bb["min_y"]
print("model height: {height}")
Use the min/max corners to find the model's center point:
use plugin obj::{parse_obj, bounding_box}
let mesh = parse_obj("v -1 -1 -1\nv 1 1 1")
let bb = bounding_box(mesh)
let cx = (bb["min_x"] + bb["max_x"]) / 2
let cy = (bb["min_y"] + bb["max_y"]) / 2
let cz = (bb["min_z"] + bb["max_z"]) / 2
print("center: {cx}, {cy}, {cz}")
Serialize mesh data to OBJ text
Serializes a mesh data table back to Wavefront OBJ text format. The output includes v, vt, vn, and f lines in the correct order. Use this to generate or modify OBJ files programmatically.
use plugin obj::{parse_obj_file, export_obj}
let mesh = parse_obj_file("input.obj")
let text = export_obj(mesh)
print(text)
Because the exporter consumes the same table shape parse_obj produces, you can
build a mesh from text and serialize it back in one pass:
use plugin obj::{parse_obj, export_obj}
let triangle = parse_obj("v 0 0 0\nv 1 0 0\nv 0 1 0\nf 1 2 3")
print(export_obj(triangle))
Write mesh data to an OBJ file on disk
Serializes a mesh data table to OBJ format and writes it directly to the given file path. Errors if the file cannot be written.
use plugin obj::{parse_obj_file, export_obj_file}
let mesh = parse_obj_file("original.obj")
export_obj_file(mesh, "output/copy.obj")
print("exported")