PDA

View Full Version : Interpreting a Wavefront Obj...



tester
05-07-2006, 12:27 PM
I need some help interpreting a WavefrontOBJ File. For example, at its simplest, I have the following cube:

# Object "object01":
# ComRec:
g cube01
# No. points 8:
v -0.5 -0.5 -0.5
v -0.5 -0.5 0.5
v -0.5 0.5 -0.5
v -0.5 0.5 0.5
v 0.5 -0.5 -0.5
v 0.5 -0.5 0.5
v 0.5 0.5 -0.5
v 0.5 0.5 0.5

# No. normals 30:
vn 0 0 -1
vn 0 0 1
vn -1 0 0
vn 1 0 0
vn 0 1 0
vn 0 -1 0
vn 0 0 -1
vn 0 -1 0
vn -1 0 0
vn 0 0 1
vn 0 -1 0
vn -1 0 0
vn 0 0 -1
vn 0 1 0
vn -1 0 0
vn 0 0 1
vn 0 1 0
vn -1 0 0
vn 0 0 -1
vn 0 -1 0
vn 1 0 0
vn 0 0 1
vn 0 -1 0
vn 1 0 0
vn 0 0 -1
vn 0 1 0
vn 1 0 0
vn 0 0 1
vn 0 1 0
vn 1 0 0

# No. texture coordinates 8:
vt 0 0
vt 0 0
vt 0 1
vt 0 1
vt 1 0
vt 1 0
vt 1 1
vt 1 1

# No. faces 6:
f 3/3/13 7/7/25 5/5/19 1/1/7
f 6/6/22 8/8/28 4/4/16 2/2/10
f 2/2/12 4/4/18 3/3/15 1/1/9
f 7/7/27 8/8/30 6/6/24 5/5/21
f 4/4/17 8/8/29 7/7/26 3/3/14
f 5/5/20 6/6/23 2/2/11 1/1/8

The first section, the vertexes, clearly sow a cube. I can also see that I have to somehow utilise the last section, the indexes to arrange and draw them onto the screen..

Can any tell me how I can draw this cube onto the screen using OpenGL ?

k_szczech
05-07-2006, 01:27 PM
google for:
wavefront obj file format

some tips:
-the 'f' entries define index arrays for vertices, normals and texture coordinates - they're 1-based
-if there are multiple objects in the file then vertex indices do not start from 1 for each object. In other words: one .obj file cannot define two vertices having the same index.

So an example:
o test -beginning of object named 'test'
v 0.0 0.0 0.0 -vertex 1
v 1.1 2.2 3.3 -vertex 2
v 4.4 5.5 6.6 -vertex 3
vn 0.0 0.0 1.0 -normal 1
f 1/1 2/1 3/1 -a triangle (vertex/normal vertex/normal...)
f 3/1 2/1 1/1 -another triangle
o test2 -beginning of object 'test2'
v 7.7 8.8 9.9 -vertex 4
v 1.7 3.8 5.9 -vertex 5
v 2.7 4.8 6.9 -vertex 6
vn 0.0 1.0 0.0 - normal 2
vn 0.0 1.0 0.0 - normal 3
f 4/2 5/2 6/3 -triangle using 2 vertices and 2 normals

05-07-2006, 09:15 PM
f v1/vn1/t1 v2/vn2/t2 v3/vn3/t3
In its simplest form a face can consist of three vertices, making up a triangle. The first parameter gives you the vertex number. When you parse the vertices, the first vertex has index 1, the second vertex has index 2 etc. The same with the vertex normals, the first vertex normal has index 1 etc. In the above example v1 is the number of the first vertex of the face, vn1 is the corresponding vertex normal, and t1 is the corresponding texture coordinate of that vertex. Once you store each face in a data structure so that you can access these variable directly, you can render the .obj file like the following:

for each face of the model
glBegin(GL_POLYGON);
for each vertex of the face
glTexCoord1f(t);
glNormal3f(vn.x, vn.y, vn.z);
glVertex3f(v.x, v.y, v.z);
end
glEnd();
end

voila!

tester
05-09-2006, 11:22 AM
Thanks..but..

Say, For example this index: .. "2/2/10" (End of second line)

This corresponds to
2nd vertex: v -0.5 -0.5 0.5
2nd normal: vn 0 0 1
10th tex co-ord: ??

Right ? But if so, there are only 8 textureco-ordinates ?

tester
05-09-2006, 12:51 PM
EDIT: Maybe it is vertex pos/normal/tex co-ord,as opposed to vertex pos/tex co-ord/normal ?

k_szczech
05-10-2006, 04:34 AM
I just did what I suggested in my first post - googled for: wavefront obj file format. First page I've found answers your question - values are: pos/normal/tex

tester
05-10-2006, 11:12 AM
Yes, but pos/normal/tex wouldn't work ? Which is the reason for this post..

Read my last about "2/2/10" .. There isn't 10 tex co-ords, so pos/normal/tex wouldn't be possible..

tester
05-12-2006, 02:50 AM
Oh wait...

First page from google:

"A polygonal face. The numbers are indexes into the arrays of vertex positions, texture coordinates, and normals respectively"

So it seems I was right.. tis pos/tex/normal..

Thanks for the help everyone :)

05-12-2006, 03:27 AM
tex coords. and normals are optional, so you can have the following possibilities:
f 1 2 3
f 1/1 2/2 3/3
f 1//1 2//2 3//3
f 1/1/1 2/2/2 3/3/3

tester
05-12-2006, 12:24 PM
Right..

Now thats over, it leads me onto my next section ..

How can I use the indices to draw _this_ cube using OpenGL (preferabbly OpenGL|ES, so no glBegin/glEnd calls, just vertex arrays..) ??

oh and btw: Thanks all.. :)

k_szczech
05-13-2006, 02:33 AM
Hehe - I messed up my answer about pos/normaltex, sorry. Good thing that you did google for that document and corrected my error yourself. Greetz!

tester
05-13-2006, 12:16 PM
Thanks k_szczech.. No worries..

Any info on the second part of the question tho ?

tester
05-14-2006, 10:57 AM
Anyone ?

I want to how I can draw this cube (See first post)in OpenGL ?

Swiftless
05-16-2006, 04:29 AM
What are you reading your information into?

Are you reading it into an array of some sort?

If you are, I recommend using either Vertex Arrays or Vertex Buffer Objects.

tester
05-16-2006, 10:58 AM
Yes, Vertex Arrays..

I can load the vertices quite simply into an array, but how do I use 'em ?

There are only 8 vertices .. To draw a cube you would need 24.. ?

I know it has something to do with faces, but .. ?

k_szczech
05-16-2006, 12:33 PM
Well, if you want to use normals and texture coordinates, then you will have to reorganise your vertex array.
Your vertex array will have 24 vertices, 24 normals and 24 texcoords. First load vertex coordinates, normals and texcoords to temporary arrays (directly from file). Then create new vertex arrays - copy vertices from your temporary arrays in order specified by faces.
To render a cube just call glDrawArrays.
If you do not use texture coordinates, then you can use only one normal vector for each face. This way you can have vertex array with just 8 vertices and call glNormal3fv and then glDrawElements once for each face. In this case you would only have vertex array (no texcoord array, and normals passed separately from CPU).

Each corner of a cube is a corner of 3 faces sharing one vertex, but unfortunately each of these faces has different normal vector.
A sphere for example is a continous (smooth) surface - you can share vertices between faces. In this case you can use glDrawElements instead of glDrawArrays.

tester
05-16-2006, 03:50 PM
Thanks ever so much k_szczech..

I think I know what to do now..

Just.., could you explain a lil more about: "glDrawElements" ? I've always used glDrawArrays before, and never glDrawElements..

k_szczech
05-16-2006, 04:23 PM
Ok, I think simple example will be better than 1000 wise-wannabe words, so here goes:
Imagine a simple quad - so we have vertices 0-3.

glBegin(GL_QUADS);
glVertex3f( <vertex0> );
glVertex3f( <vertex1> );
glVertex3f( <vertex2> );
glVertex3f( <vertex3> );
glEnd();When using glDrawArrays:

glDrawArrays(GL_QUADS, 0, 4);Now imagine that you want to use 2 triangles instead of one quad:

glBegin(GL_QUADS);
glVertex3f( <vertex0> );
glVertex3f( <vertex1> );
glVertex3f( <vertex2> );

glVertex3f( <vertex2> );
glVertex3f( <vertex3> );
glVertex3f( <vertex0> );
glEnd();Vertex 0 and Vertex2 are used twice - they're shared between these two triangles.
And now glDrawElements:

unsigned long indexArray[6] = {0, 1, 2, 2, 3, 0};
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexArray);In other words - glDrawArrays will use vertices in exactly the same order they're placed in vertex array and glDrawElements allows you to pass an array of integers. This array defines the order of vertices.

tester
05-17-2006, 06:59 AM
Hmm..

glDrawElements is still getting the vertices data from array tho (using glVertexPointer) ?

Thanks for the explanation btw .. :)

tester
05-19-2006, 01:04 PM
Anyone ?

05-19-2006, 01:23 PM
just skimming over the thread it seems a lot of ground has been covered. Could you sorta recap your current dilemma for us?

tester
05-19-2006, 02:05 PM
"glDrawElements is still getting the vertices data from array tho (using glVertexPointer) ?"

Third last post ..

tester
05-19-2006, 02:56 PM
:( :( :(

I tried what k_szczech said, but to no avail :(

Here's the code, can anyone see where I've gone wrong ?

void DrawFlippinSquare()
{
float triangle1[] = {
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};

float indexArray[6] = {0, 1, 2, 2, 3, 0};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glVertexPointer(3, GL_FLOAT, 0, triangle1);

glDrawElements(GL_TRIANGLES, 6, GL_FLOAT, indexArray);
}

Works perfectly with glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);

but not glDrawElements :(

05-19-2006, 03:09 PM
void DrawFlippinSquare(){

float verts[] = {
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
};

float indexArray[6] = {0, 1, 2, 2, 3, 0};
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glVertexPointer(3, GL_FLOAT, verts);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLES, 6, GL_FLOAT, indexArray);
}You had a vertex duplicated, which lead to a degenerate triangle. Remember that each vertex should be unique when using elements. You create a unique set of vertices, then just index them for your primitives, whatever they may be :) .

05-19-2006, 03:14 PM
And the index array should be one of

GL_UNSIGNED_BYTE,
GL_UNSIGNED_SHORT,
GL_UNSIGNED_INT.

Almost slipped past me, but it's is in the docs.

You should read the docs carefully, and double-check your code, before you post ;)

tester
05-20-2006, 12:20 PM
Yeah, I changed it too "GL_UNSIGNED_BYTE" and it works now :D

"You had a vertex duplicated" .. Which ? they were all unique ?

Anyhow, it's all good now...

Before I leave, must say a big thanks to everyone who helped.. :)

Thanks all!!! :lol: