Search code examples
iphoneobjective-cxcodeopengl-esindices

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);

Solution

  • 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,
    }