OBJ file format
About
Wavefront OBJ (.obj) is a ASCII file format for representing 3D mesh geometries - namely the position of vertices, texture coordinates, normals and the faces of each polygon defined as a list of vertices. Unlike other 3D interchange formats, like VRML and X3D, OBJ files do not support any animation, object hierarchy, transformation or even the use of 3D primitives (spheres, cubes etc). Material information is also mission from OBJ files, however can be referenced in ".mtl" files using OBJ's Material Template Library (MTL) companion file format. Despite these limitations, the OBJ format by Wavefront Technologies is a universally accepted format and remains in common use due to its relative simplicity. Be warned, however, that MTL is much less supported, so conversions between different 3D graphics programs is likely to result in a loss of material and color information.
OBJ File Format Basics
OBJ is a very simple format:
- To start a 3D polygon mesh "group" you should use g [group name].
- Follow this with a list of vertices (3d points) in the form: v [x y z [w]] (w is optional).
- Finish each polygon with a list of face definitions by listing vertices counter-clockwise in the form: f [vertexNum1 vertexNum2 vertexNum3 ...].
- Important Note: Vertex numbers are continuous and start at 1 - meaning "f 1 2 3 4" will turn the very first four vertices in a rectangle. Even if you start a new group, the numbers continue over, so it's a good idea to keep track of the vertex number. As a second option, negative numbers can be used to make relative references, counting backwards from the current position - meaning "f -1 -5 -20 will make a triangle between the very last, 5th last and 20th last listed vertices.
- If desired you can include normals and texture coordinates above the list of faces:
- Normals in the form vn [x y z].
- Texture coordinates in the form vt [u v [w]] (w is optional).
- Line comments are made with a hash character (#).
Warning: Not all editors/viewers can handle OBJ line comments and may fail to load until you remove them. Unity 5 is one of them apparently! |
To demonstrate the file format here are a few basic examples:
Example 1a: A square facing forwards
This example demonstrates a single square in X/Y. Notice that the points are listed out in an anti-clockwise order such that the "front" face of this square will be looking forwards along -Z.
# My first .obj file:
# List of vertices:
v 0 0 0 # Bottom left.
v 5 0 0 # Bottom right.
v 5 5 0 # Top right.
v 0 5 0 # Top left.
# List of faces:
f 1 2 3 4 # Square.
Example 1b: A square and a triangle
Here we've modified the example above to include a triangle on top such that it looks like a 2D house. Notice that we've put the square and triangle into two separate groups, but the vertex numbers continue regardless. We could also have listed the triangle face as "f -3 -2 -1".
g MySquare
v 0 0 0 # Bottom left.
v 5 0 0 # Bottom right.
v 5 5 0 # Top right.
v 0 5 0 # Top left.
f 1 2 3 4 # Square base.
g MyTriangleRoof
v -2 5 0 # Left side.
v 7 5 0 # Right side.
v 2.5 7 0 # Top of room.
f 5 6 7 # Triangle.
Example 2a: Square based pyramid
In this example we have a square based pyramid with 1 square face and 4 triangular faces organized into a single group called "MySquareBasedPyramid".
# WaveFront .obj file - a single square based pyramid
# Start a new group:
g MySquareBasedPyramid
# List of vertices:
v -0.5 0 0.5 # Front left.
v 0.5 0 0.5 # Front right.
v 0.5 0 -0.5 # Back right
v -0.5 0 -0.5 # Back left.
v 0 1 0 # Top point (top of pyramid).
# List of faces:
f 4 3 2 1 # Square base (note: normals are placed anti-clockwise).
f 1 2 5 # Triangle on front.
f 3 4 5 # Triangle on back.
f 4 1 5 # Triangle on left side.
f 2 3 5 # Triangle on right side.
Example 2b: Square based pyramid with custom normals
This example is almost exactly the same as the example above, but demonstrates how to list and reference normals using "vt". Typically you can get a much nicer and smaller file size by omitting normals, because most programs will generate good normals for you - but in cases where you want to list your own normals your face definitions should be in the form: f [vertex1//normal1 vertex2//normal2 vertex3//normal3 ...] or f [vertex1/texturecoord1/normal1 vertex2/texturecoord2/normal2 vertex3/texturecoord3/normal3 ...].
# WaveFront .obj file - a single square based pyramid with custom normals
g MySquareBasedPyramid
# List of vertices:
v -0.5 0 0.5
v 0.5 0 0.5
v 0.5 0 -0.5
v -0.5 0 -0.5
v 0 1 0
# List of normals:
vt 0 0 0
vt 1 0 0
vt 0 1 0
vt 1 0 0
vt 0 0 0
vt 1 1 0
vt 0 0 0
vt 1 0 0
vt 0 0 0
vt 1 0 0
vt 0.5 1 0
# List of faces and normals for each corner:
f 4//9 3//8 2//6 1//3
f 2//5 3//8 5//11
f 3//7 4//10 5//11
f 4//9 1//2 5//11
f 1//1 2//4 5//11
MTL File Format Basics
Material Template Library (MTL) is an ASCII file format defined by Wavefront Technologies to specify material and light reflecting properties. MTL files are typically accompanied by and referenced from OBJ files that define geometry upon which the materials of the MTL file are mapped. A more detailed look at this standard is available here. Here we ignore the illumination properties, but list out the more basic properties and method used to define a material:
- Within the .obj file:
- an .mtl file is referenced using: mtllib [external .mtl file name].
- a different material can be specified for each polygon group by using this line just under the group tag: usemtl [material name].
- Within the .mtl file:
- each new material must be started with the tag: newmtl [MaterialName]
- ambient color is declared using: Ka [r g b]. RGB (red green blue) values like this are always a coefficient between 0 and 1.
- diffuse color is declared using: Kd [r g b].
- specular color is declared using: Ks [r g b] and then the amount of "shininess" defined with: Ns [#] where # ranges between 0 and 1000.
- transparency can be declared using: Tr [r g b] and d [r g b] (some implementation use 'd' instead of 'Tr').
Example 3: Two triangles with materials referenced in a .mtl file
In this final example we have two files... the first is our .obj file with two triangle, the second file is our .mtl file:
my_triangles.obj:
# Two triangles...
mtllib my_triangles.mtl
# FIRST TRIANGLE / GROUP: (will be red and shiny)
g triangle1
usemtl material_for_first_triangle
v 0 0 0
v 4 0 0
v 4 2 0
f -3 -2 -1
# SECOND TRIANGLE / GROUP: (will be white and transparent)
usemtl material_for_first_triangle
v 0 0 0
v 4 0 0
v 4 2 0
f -3 -2 -1
my_triangles.mtl:
#MATERIAL FOR GROUP 1:
newmtl material_for_first_triangle
Ka 1 0 0 # Red.
Kd 1 0 0
Ks 1 1 1
Ns 500 # Very shiny.
MATERIAL FOR GROUP 2:
newmtl material_for_second_triangle
Ka 1 1 1 # White.
Kd 1 1 1
Ks 1 1 1
Ns 0 # No shine (completely dull).
Tr 0.5 # Is 50% transparent.
See Also
- Generating a sphere as a 3D mesh - shows an example of generating a OBJ file using C code.
- VRML - a more versatile 3D vector file format which allows for animation, lights and many other features, but is a bit harder to read/parse
Links
- Wavefront .obj file - Wikipedia - gives a great little summary of the main keywords.
- Wavefront specifications - explains all the syntax.
Acknowledgements: Eric Ball for pointing out the loading problem with Unity 5 loading OBJs with line comments.... and (more importantly) submitting to them a feature request |