Help with .OBJ format

Started by
5 comments, last by Basic 17 years, 10 months ago
I'm trying to write a parser for .obj objects, but I have stumbled into a major road block. Here's a basic stripped down .obj file to the bare minimum of what it needs to properly display an object. # Vertices: 5 # Texture vertices: 16 # Normals: 5 # Faces: 5 v 1.000000 0.000000 -1.000000 v 1.000000 0.000000 1.000000 v -1.000000 0.000000 -1.000000 v -1.000000 0.000000 1.000000 v -0.000001 0.500000 -0.000001 f 3 5 1 f 2 4 3 1 f 3 4 5 f 4 2 5 f 2 1 5 # The end. The first set of information is just general information about your model. The second set is the position of the vertices. The third is where you place your geometric vertices. You may also add a texture and normal coordinates using slashes(ex: 1/1/2 1/1/1 2/2/1), but I've stripped those out for simplicity. My question is, how do you calculate the geometric vertices. Where does 3 5 1 come from on the first line. I understand that it takes 3 vertices to make up that face. And then the next line consists of four vertices making up the face(2 4 3 1), but how do I calculate those numbers. If I want to save my object, do I calculate a 4x4 matrix and just pop in the values for a 5 polygon object? I'm a little confused, and any help would be much appreciated.
I ask for help and you give me a book? I hate book. Book is stupid.Also known as Yellow at the Dark Basic forums.
Advertisement
Basic,

Generally speaking, what you're looking for is the concept of an "index list." Nearly all meshes/models - cubes, pyramids, semi-spheres, grids, etc...will duplicate positions. For example, a cube has only 8 'vertices', but 12 triangles, each of 3 points totaling 36 points in space. So why does a cube not have 36 vertices? Well, because the triangles 'share' points in space...so although a cube may be made up of 36 points in space, only 8 of those points are unique. To save memory, we represent the points of a cube by simply listing the 8 unique points and then providing "indicies" into that list of 8.

In your example you provide 5 vertices...then you provide 16 indicies into that list of vertices. You've segmented them into polygons, but regardless, you're still using 16 indices into the list, creating a set of 16 points, all made up of 5 unique vertices.

f 3 5 1

The above line just says you've got a facet (polygon/surface) made up of the indices 3, 5, and 1...since its 3 points, it's a facet which happens to look like a triangle. And you can determine the rest for yourself.

How do you know which ones to use? Well, you just work it out for yourself. Think of a cube, which has 8 unique positions, then think about each of the quads or triangles that make up the cube, for each surface you store the 4 indices which make up that surface...then the next surface, the next, etc...until you've created all 6 surfaces, using indicies into your list of 8 vertices.

Hopefully this explanation will help you understand the problem set better. If you have additional questions, don’t hesitate to ask.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Thanks Jeremy, I'm pretty sure I have a solid understanding now. :)

The part I'm confused about is the actual application. So when I read this file, and then start plotting the vertices to use for each face, do I just test every combination until I eventually have my object? I could work this example out in my head, but what happens when I have a more complicated object with hundreds of vertices?

I'll do a search for an index list on google and see if that helps.

Thanks again ++
:)
I ask for help and you give me a book? I hate book. Book is stupid.Also known as Yellow at the Dark Basic forums.
Watch out for model loaders which unconditionally re-calculate the vertex normals using its own algorithm.

Annoying.

Specify vn x y z declares a vertex normal. It is also associated with the same indexing order as used by the vertices in the face specification statements.

To add the information to your face, you need to separate the information by forward slashes, such as: f v//vn

The space between the two slashes is where the texture coordinate information usually goes, but we are not including that for now, right?

Example:

# single triangle, single normal
v 1.0 1.0 1.0
v 0.0 0.0 0.0
v 0.0 0.0 1.0

vn 1.0 1.0 1.0

# don't forget that you can use different vertex normals per vertex as well!
# i cheaped out
f 1//1 2//1 3//1
Okay, thanks for the explanation.

The trick now is, how do I store which vertices each face is using so I can avoid bad geometry?
I ask for help and you give me a book? I hate book. Book is stupid.Also known as Yellow at the Dark Basic forums.
Load all vertices in an array of:
struct Vert {  float verts[ 3 ];}

And all faces in an array of:
struct ObjFace {  unsigned int vertIds[3];  unsigned int texCoordIds[3];  unsigned int normalIds[3];};

Now, in your rendering loop, for each face:
setNormalsFromArray( face.normalIds[ 0 ])
drawVertexFromArray( face.vertIds[ 0 ]);
setNormalsFromArray( face.normalIds[ 1 ])
drawVertexFromArray( face.vertIds[ 1 ]);
setNormalsFromArray( face.normalIds[ 2 ])
drawVertexFromArray( face.vertIds[ 2 ]);

It concerns me that I received around 10 IIS 500.13 errors in trying to submit this.
If a plant cannot live according to its nature, it dies; so a man.
Thanks Woodsmen, I've finally got it. :)

(Gamedev has been running really sluggish lately) :(
I ask for help and you give me a book? I hate book. Book is stupid.Also known as Yellow at the Dark Basic forums.

This topic is closed to new replies.

Advertisement