Blog · Format primers
What is an OBJ file? Wavefront's open mesh format
An OBJ file is a plain-text 3D mesh format created by Wavefront Technologies in the early 1990s. It stores vertices, normals, UV coordinates, and faces in a human-readable layout, with materials and textures kept in a separate .mtl file. OBJ became a universal pipeline glue for moving static meshes between modelling tools, and it's still widely used in 2026 — even though there are technically better alternatives for most use cases.
The short version
An OBJ file describes a 3D mesh in plain text. Each line either declares a vertex, a normal, a texture coordinate, or a face. Materials are referenced by name and defined in a companion .mtl file that itself references texture images. Open an .obj in a text editor and the structure is immediately legible.
OBJ has no support for animation, no concept of a scene graph beyond simple grouping, no rigging, and no modern material model. It is a static-mesh format and that's all. But the underlying simplicity is why it has lasted: importing and exporting OBJ is straightforward, and almost every 3D tool ever written can handle it.
Where OBJ came from
Wavefront Technologies was a Santa Barbara company that made 3D animation software in the 1980s and 1990s. Their Advanced Visualizer suite was a major name in the era and shipped a documented file format for static geometry — the .obj format — alongside the .mtl material library and a small family of related extensions.
Wavefront merged into what became Alias|Wavefront in 1995, which itself was eventually acquired by Autodesk and folded into Maya. The original Advanced Visualizer is long gone. The .obj format outlived its parent company by decades because it was simple, well-documented, and quickly picked up by every other 3D tool as a least-common-denominator interchange option.
What's actually inside an OBJ file
A minimal OBJ file looks like this:
# A textured cube mtllib cube.mtl o Cube v -1.000000 -1.000000 1.000000 v -1.000000 1.000000 1.000000 v -1.000000 -1.000000 -1.000000 v -1.000000 1.000000 -1.000000 v 1.000000 -1.000000 1.000000 v 1.000000 1.000000 1.000000 v 1.000000 -1.000000 -1.000000 v 1.000000 1.000000 -1.000000 vn -1.0000 0.0000 0.0000 vn 0.0000 0.0000 -1.0000 vt 0.625 0.500 vt 0.875 0.500 usemtl Default s off f 2/1/1 3/2/1 1/3/1 f 4/1/2 7/2/2 3/3/2 ...
Each line is a directive followed by space-separated arguments:
v x y z— a vertex positionvn x y z— a vertex normalvt u v— a texture coordinate (UV)f i/j/k l/m/n ...— a face built from a list of vertex/UV/normal index triples, where each index is a 1-based reference into the corresponding arrayso name/g name— object and group names for organising partsusemtl name— switch to the named material from the .mtl file for subsequent facesmtllib filename.mtl— load the material definitions from this files on / off— smoothing group toggle# comment— any line starting with # is ignored
The face line is OBJ's only unusual touch — each corner of a face is a triple of three independent indices (position, UV, normal), allowing the same vertex position to carry different UVs or normals on different faces.
The .mtl file
The companion .mtl file uses a similar plain-text format to define materials. A simple example:
newmtl Default Ka 1.000 1.000 1.000 Kd 0.800 0.800 0.800 Ks 0.500 0.500 0.500 Ns 96.078431 d 1.000000 illum 2 map_Kd diffuse.png map_bump normal.png
The Ka/Kd/Ks lines define ambient, diffuse and specular colours; Ns is the specular exponent; d is opacity; illum picks an illumination model from a small set. The map_ lines reference external image files for textured channels — diffuse, normal, specular, bump, alpha.
The material model is firmly pre-PBR. Outside game engines, most modern viewers approximate it as a basic Phong or Blinn-Phong material. If you want consistent physically-based rendering across viewers, OBJ is the wrong choice — use GLB instead.
Why OBJ persists
OBJ should arguably have been replaced by FBX (binary, supports animation), Collada (XML, more complete) or now glTF (efficient, PBR materials). It hasn't been. The reasons it has stuck around:
- Universal support. Every 3D tool reads it. Even a brand-new open-source modeller will have an OBJ importer on day one because writing one is a weekend project.
- Human-readable. When something goes wrong, you can open the file and see what's actually there. The other formats need specialised inspectors.
- No licensing concerns. Wavefront's documentation has been public since the 1990s. FBX had years of licensing friction; Collada is technically open but unmaintained.
- Just good enough. For passing a static mesh between two artists, OBJ does the job, and switching to anything more sophisticated isn't worth the trouble.
When OBJ is the right choice
- Moving a static mesh between modelling tools — Blender to ZBrush to Substance Painter, for example.
- Sharing a model with someone whose toolchain you don't know — OBJ is the safest bet for a "every tool reads it" mesh.
- Authoring pipelines where the geometry and materials are edited by different artists in different tools — the split-file model fits that workflow.
- Quick-and-dirty exports where you don't care about file size or render fidelity.
When OBJ is the wrong choice
- Anything animated — OBJ has no animation support at all.
- Web or AR delivery — file sizes are several times larger than GLB for the same geometry, and the material model doesn't match what modern web viewers expect.
- Single-file distribution — losing the .mtl or a texture is too easy. GLB packs everything together.
- 3D printing — slicers want STL or 3MF, not OBJ.
How to view an OBJ file
- In your browser: open open3d.app/viewer and drag the .obj in. To get materials, also drag the .mtl and the texture images.
- Blender: File → Import → Wavefront (.obj). Material library is auto-detected.
- MeshLab: open-source, free, good for inspecting and cleaning OBJ meshes.
- Maya / 3ds Max / Cinema 4D / Modo: all support OBJ import out of the box.
- Game engines (Unity, Unreal): via their respective importers.
FAQ
What is the .mtl file that comes with .obj?
The Material Template Library — a separate text file with material definitions (colour, specular, transparency, texture maps) that the .obj references by name. If textures don't show, the .mtl or the images it points to are probably missing.
Why does OBJ ship as several files?
It was designed for early-1990s modelling pipelines where geometry and materials were edited separately. The split made sense then but is fragile for distribution today. Use GLB if you want a single file.
Does OBJ support animations?
No. OBJ is static geometry only. Animation pipelines that use OBJ export one file per frame, which is enormously inefficient.
Is OBJ a binary format or text?
Plain text. You can open it in any editor and read it line by line.
When should I use OBJ instead of GLB?
For moving a static mesh between modelling tools (Blender ↔ ZBrush ↔ Substance Painter) where OBJ is the lowest common denominator. Use GLB for web, AR, game engines, or anytime you want a single-file animated PBR result.