Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL ES - glDrawElements - Trouble Understanding Indices

I wonder if anyone can help me understand how indices work with glDrawElements. In the below example (taken from http://www.everita.com/lightwave-collada-and-opengles-on-the-iphone) the author mentions that you can only have one set of indices, in this case

const GLushort tigerBottomIndices[] = {
0,1,2,
3,0,4,
1,5,6,
…

};

My question is what do these indices describe ? Am I right in thinking that the first three are the vertice positions, the second three are then the corresponding normals and the last three the texture co-ords ?

Thanks in advance !

#import "OpenGLCommon.h"

const Vertex3D tigerBottomPositions[] = {
{0.176567, 0.143711, 0.264963},
{0.176567, 0.137939, 0.177312},
{0.198811, 0.135518, 0.179324},
…
};
const Vertex3D tigerBottomNormals[] = {
{-0.425880, -0.327633, 0.350967},
{-0.480159, -0.592888, 0.042138},
{-0.113803, -0.991356, 0.065283},
…
};
const GLfloat tigerBottomTextureCoords[] = {
0.867291, 0.359728,
0.779855, 0.359494,
0.781798, 0.337223,
…
};
const GLushort tigerBottomIndices[] = {
0,1,2,
3,0,4,
1,5,6,
…
};

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);    

glBindTexture(GL_TEXTURE_2D, tigerTextures[5]);
glVertexPointer(3, GL_FLOAT, 0, tigerBottomPositions);
glNormalPointer(GL_FLOAT, 0, tigerBottomNormals);
glTexCoordPointer(2, GL_FLOAT, 0, tigerBottomTextureCoords);
glDrawElements(GL_TRIANGLES, 210, GL_UNSIGNED_SHORT, tigerBottomIndices);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableEnableClientState(GL_TEXTURE_COORD_ARRAY);
like image 746
GuybrushThreepwood Avatar asked Feb 14 '12 10:02

GuybrushThreepwood


2 Answers

Each and every value in the index array points at the same time for a position, a normal and a texture coordinate.

They are only organized in groups of 3 because they are simply discribing the vertices of a triangle, so 3 vertices = 1 triangle, of course.

const GLushort tigerBottomIndices[] = {
0,1,2, // #1 Triangle
3,0,4, // #2 Triangle
1,5,6, // #3 Triangle
…

So let's pick the first value of these indices, it's 0.

This means:

Pick the vertex position number 0

Also, pick the vertex normal number 0

And pick the texture coordinates number 0

const Vertex3D tigerBottomPositions[] = {
{0.176567, 0.143711, 0.264963}, // This is the position number 0
{0.176567, 0.137939, 0.177312},
{0.198811, 0.135518, 0.179324},
…
};
const Vertex3D tigerBottomNormals[] = {
{-0.425880, -0.327633, 0.350967}, // This is the normal number 0
{-0.480159, -0.592888, 0.042138},
{-0.113803, -0.991356, 0.065283},
…
};
const GLfloat tigerBottomTextureCoords[] = {
0.867291, 0.359728, // These are the tex-coords number 0
0.779855, 0.359494,
0.781798, 0.337223,
…
};

So this information gets sent to the vertex shader:

VertexPosition: 0.176567, 0.143711, 0.264963

VertexNormal: -0.425880, -0.327633, 0.350967

VertexTextureCoordinates: 0.867291, 0.359728

...

If you do not use indices, opengl will send those vertex data linearly, so after sending vertex data number 0, it would send the data at position 1 of the arrays, then 2, 3, 4 etc...

That's good but sometimes your triangles end up with one or two identical vertices. Consider this:

enter image description here

You can see 2 triangles forming a square, and they have 2 vertices in common, 0 and 2. So instead of having 6 vertices, being 3 for each triangle, we have only 4 and the 2 traingles use the same data for 2 of their vertices. That's good for performance, especially when you have big models with hundreds of triangles.

In order to draw the first triangle, we need the vertices number 0, 1 and 2 and for the second triangle we need the vertices number 0, 2 and 3.

See, without an index array, opengl would try to use vertices 0, 1 and 2 (ok for the first triangle) but for the second triangle opengl would look for the vertices 3, 4 and 5. Which is wrong.

And that's why we create the index array, so opengl can send the right vertices for the vertex shader. In our case our index array would look like this:

const GLushort tigerBottomIndices[] = {
0,1,2,
0,2,3,
}
like image 117
Delta Avatar answered Sep 28 '22 10:09

Delta


The indices are meant in the sense of indices of elements in an array. Index 0 addresses the first element in an array, index 1 the second and so on.

In your example the first indices 0, 1, 2 address the first three vertices, which have the positions of the first three Vertex3D items of array tigerBottomPositions, the normals of the first three elements of tigerBottomNormals (with 3 floats forming one normal vector) and same for texture coordinates.

The first argument in the glDrawElements call tells OpenGL how to form primitives from the indexed vertices. GL_TRIANGLES means every three indexed vertices form a triangle.

So vertices with indices 0, 1, 2 form a triangle, 3,0,4 form the next, 1,5,6 form another triangle and so on.

like image 43
haffax Avatar answered Sep 28 '22 10:09

haffax