Sign in to follow this  
leonardteo

Need help with vertex normal arrays when using glVertexPointer glDrawElements

Recommended Posts

Hi guys,

I'm moving from immediate mode drawing in OpenGL to using vertex arrays and glDrawElements (gradually moving towards using vertex buffer objects).

I'm having a really hard time with vertex normals. I just don't know how they are supposed to be stored so that they can be called by glDrawElements. I've tried a variety of different things and my normals (and hence shading) are all messed up at render time. I have this working in immediate mode rendering, but I'd really like some help in understanding how the vertex normals are intended to be stored when using glVertexPointer.

Thanks in advance!

Leonard

Here's my rendering code:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, this->vertexArray);
glNormalPointer(GL_FLOAT, 0, this->normalArray);

glDrawElements(GL_TRIANGLES, 3*this->numFaces, GL_UNSIGNED_BYTE, this->indexArray);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);


Some stats:
fileName: models/cube.obj
Vertices: 8
Vertex Normals: 24
Faces: 12 //Triangulated cube


Vertex array:
{
-2.894048, -2.894048, 2.894048,
2.894048, -2.894048, 2.894048,
-2.894048, 2.894048, 2.894048,
2.894048, 2.894048, 2.894048,
-2.894048, 2.894048, -2.894048,
2.894048, 2.894048, -2.894048,
-2.894048, -2.894048, -2.894048,
2.894048, -2.894048, -2.894048,
}

Index array:
{
0, 1, 2,
2, 1, 3,
2, 3, 4,
4, 3, 5,
4, 5, 6,
6, 5, 7,
6, 7, 0,
0, 7, 1,
1, 7, 3,
3, 7, 5,
6, 0, 4,
4, 0, 2,
}


Vertex normals as read from the OBJ file:
{
0.000000 0.000000 1.000000
0.000000 0.000000 1.000000
0.000000 0.000000 1.000000
0.000000 0.000000 1.000000
0.000000 1.000000 0.000000
0.000000 1.000000 0.000000
0.000000 1.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 -1.000000
0.000000 0.000000 -1.000000
0.000000 0.000000 -1.000000
0.000000 0.000000 -1.000000
0.000000 -1.000000 0.000000
0.000000 -1.000000 0.000000
0.000000 -1.000000 0.000000
0.000000 -1.000000 0.000000
1.000000 0.000000 0.000000
1.000000 0.000000 0.000000
1.000000 0.000000 0.000000
1.000000 0.000000 0.000000
-1.000000 0.000000 0.000000
-1.000000 0.000000 0.000000
-1.000000 0.000000 0.000000
-1.000000 0.000000 0.000000
}

Share this post


Link to post
Share on other sites
Looking at your code, I see that you have 8 vertices but 24 vertex normals. You need to find a one to one correspondent between each of the vertex and a normal, i.e. if you have n-vertices, then you need to have n-normals. If you use your index array, you can figure it out easy.Hint.. there are duplicate entries in the normal array.

Share this post


Link to post
Share on other sites
Sorry, forgive me for being a bit dense, but I still don't get it....

There are 8 vertices because each face shares the vertices.

As defined by the OBJ file:
v -2.894048 -2.894048 2.894048
v 2.894048 -2.894048 2.894048
v -2.894048 2.894048 2.894048
v 2.894048 2.894048 2.894048
v -2.894048 2.894048 -2.894048
v 2.894048 2.894048 -2.894048
v -2.894048 -2.894048 -2.894048
v 2.894048 -2.894048 -2.894048

There are 24 vertex normals because we need a vertex normal at every vertex that we draw on a triangle. 8 faces, 3 vertices each = 24 vertex normals.

There are duplicates in the Vertex Normals but this is the data that is being given in an exported OBJ from Maya. I want to retain the vertex normal data from the OBJ file.

You said that I need to have a corresponding vertex and vertex normal, (i.e. if numNormals = n, numVertices = n also) This would mean that to preserve all the vertex normals, we would need to duplicate the vertices, then the index would be a straight march (1,2,3,4,5,6,...) -- then what would be the point of having an index?

Again, sorry for being dense...

Share this post


Link to post
Share on other sites
Quote:

You said that I need to have a corresponding vertex and vertex normal, (i.e. if numNormals = n, numVertices = n also) This would mean that to preserve all the vertex normals, we would need to duplicate the vertices, then the index would be a straight march (1,2,3,4,5,6,...) -- then what would be the point of having an index?

Again, sorry for being dense...


No problem, this trips up a lot of people when they first play with OBJs.

Lets describe the term "element" as referring to the combination of all attributes that define a vertex (position + normal + texcoord + whateverAttrib). All of these together is one "element".

In your mesh you have 24 elements. Even if position, texcoord, and whateverAttrib are the same, if the normal is different then you copy ALL parts of the element into a new element.

So when you are drawing, you need to have an array of 24 vertex positions, 24 normals, 24 texcoords, and 24 of any other attrib you want to have.

The obj format compresses these to cut down on file size, but you need to reexpand them to use them with glDrawElements.

As to "what is the point of having an index", in your simple cube case, there isn't. However when you have more detailed meshes it might not be uncommon for two points to have all the attributes the same. Because your cube has sharp edges it is necessary for each face to have its own normal, but if you had say a finely tesselated plane instead of a cube, a lot of vertices would share the same normals. In those cases you can utilize indexes to cut down on the number of elements.

Share this post


Link to post
Share on other sites
Yes! Got it working. Thanks so much for the detailed response.

Another "gotcha" is in the type of the indices. All the examples in the Red Book and around on the net uses GL_UNSIGNED_BYTE, which means that your index only gets to 255. I spent another 20 minutes banging my head when larger models weren't rendering. Changed to GL_UNSIGNED_INT and it's all working good now.

Thanks again.

Leonard

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this