OpenGL ES - glDrawElements - Trouble Understanding Indices
Asked Answered
A

2

6

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);
Athalia answered 14/2, 2012 at 10:8 Comment(0)
R
27

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,
}
Rustcolored answered 14/2, 2012 at 15:36 Comment(1)
One of the best explanations I have seen. ThxNopar
M
1

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.

Macdougall answered 14/2, 2012 at 12:55 Comment(2)
Thanks haffax, but I'm still confused. So in the first indices (0,1,2) is this describing just the vertice information, or also the normal and texture co-ord information ?Athalia
All three vertex attributes: Position, Normal, TexCoord. With the glXxxPointer functions you define the start of the arrays for each attribute. The indices count from this start.Macdougall

© 2022 - 2024 — McMap. All rights reserved.