Skip to content
OBJ Loader
step 1/5

Reading — step 1 of 5

Read

~1 min readProduction

OBJ Loader

Wavefront .obj is the simplest 3D mesh format that real tools (Blender, ZBrush, Maya) export. Plain text, no binary parsing, no compression — perfect for a software renderer.

Minimal grammar:

# comment
v  <x> <y> <z>                # geometric vertex
vt <u> <v>                    # texture coordinate
vn <nx> <ny> <nz>             # vertex normal
f  v1 v2 v3                   # face with 3 vertex indices (1-based!)
f  v1/vt1 v2/vt2 v3/vt3       # face with vertex + UV
f  v1//vn1 v2//vn2 v3//vn3    # face with vertex + normal
f  v1/vt1/vn1 v2/vt2/vn2 ...  # face with all three

Indices are 1-based. The first v line is vertex 1. v -1 indexes from the end (vertex -1 == last vertex declared) — supported but rare. Most loaders normalize to 0-based after parsing.

Faces can be n-gons. f 1 2 3 4 5 is a pentagon. Triangulate with a simple fan: (v1, v2, v3), (v1, v3, v4), (v1, v4, v5) — works for convex polygons.

Other tags (typically ignored for a basic renderer): o (object name), g (group), usemtl (material reference), mtllib (material library), s (smooth shading group), blank lines.

Practical pitfalls:

  • Some exports use \r\n; strip both.
  • Trailing whitespace on lines.
  • Comments mid-line (rare, treat as line-ending).
  • Faces referencing indices that don't exist yet (legal in OBJ; the spec allows forward refs, but in practice never seen).

Real-world OBJs (Stanford Bunny, Utah Teapot) load in under 100 lines of careful parsing. This is the right format for "hello world, 3D" — once you can rasterize triangles, parsing OBJ unlocks every 3D asset that exists.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…