2012-02-14 16 views
6

Me pregunto si alguien puede ayudarme a entender cómo funcionan los índices con glDrawElements. En el siguiente ejemplo (tomado de http://www.everita.com/lightwave-collada-and-opengles-on-the-iphone) el autor menciona que sólo se puede tener un conjunto de índices, en este casoOpenGL ES - glDrawElements - Trouble Understanding Indices

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

};

Mi pregunta es ¿qué describen estos índices? ¿Estoy en lo cierto al pensar que las tres primeras son las posiciones de vértice, las segundas tres son las normales correspondientes y las tres últimas las coordenadas de textura?

¡Gracias de antemano!

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

Respuesta

26

Todos y cada uno de los valores del conjunto de índices apunta a mismo tiempo para una posición, una coordenada normal y una de textura.

Se organizan solo en grupos de 3 porque simplemente están describiendo los vértices de un triángulo, por lo que 3 vértices = 1 triángulo, por supuesto.

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

Así que vamos a elegir el primer valor de estos índices, es .

Esto significa:

escoger el número de posición de vértice 0

También, escoja el vértice número normal 0

y recoger las coordenadas de textura número 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, 
… 
}; 

Así que esta información se envía al sombreador de vértices:

VertexPosition: 0,176567, 0,143711, 0,264963

VertexNormal: -0.425880, -0.327633, 0,350967

VertexTextureCoordinates: 0,867291, 0,359728

...

Si lo hace no índices de uso, OpenGL enviará los datos de vértice de forma lineal, por lo que después de enviar los datos de vértice número 0, que enviará los datos en la posición 1 de las matrices, a continuación, 2, 3, 4, etc ..

Eso es bueno, pero a veces tus triángulos terminan con uno o dos vértices idénticos. Considere esto:

enter image description here

Se puede ver 2 triángulos que forman un cuadrado, y tienen 2 vértices en común, 0 y 2. Así que en lugar de tener 6 vértices, siendo 3 de cada triángulo, sólo tenemos 4 y los 2 traingles usan los mismos datos para 2 de sus vértices. Eso es bueno para el rendimiento, especialmente cuando tienes modelos grandes con cientos de triángulos.

Para dibujar el primer triángulo, necesitamos los vértices número 0, 1 y 2 y para el segundo triángulo que necesitamos los vértices número 0, 2 y 3.

See, sin una matriz de índice, OpenGL Intentaría usar los vértices 0, 1 y 2 (está bien para el primer triángulo) pero para el segundo triángulo, OpenGL buscaría los vértices 3, 4 y 5. Lo cual es incorrecto.

Y es por eso que creamos la matriz de índices, por lo que opengl puede enviar los vértices correctos para el sombreador de vértices. En nuestro caso, nuestro conjunto de índices se vería así:

const GLushort tigerBottomIndices[] = { 
0,1,2, 
0,2,3, 
} 
+3

Gracias, exactamente la explicación clara que necesitaba. – GuybrushThreepwood

+0

Una de las mejores explicaciones que he visto. Thx –

+0

Gran explicación – dbryson

1

Los índices se entienden en el sentido de índices de elementos en una matriz. El índice 0 se dirige al primer elemento de una matriz, el índice 1 al segundo y así sucesivamente.

En su ejemplo los primeros índices 0, 1, 2 dirección de los primeros tres vértices, que tienen las posiciones de los tres Vertex3D primeros elementos de array tigerBottomPositions, las normales de los tres primeros elementos de tigerBottomNormals (con 3 flotadores formando una vector normal) y lo mismo para las coordenadas de la textura.

El primer argumento en la llamada glDrawElements le dice a OpenGL cómo formar primitivas desde los vértices indexados. GL_TRIANGLES significa que cada tres vértices indexados forman un triángulo.

Así que los vértices con los índices 0, 1, 2 forman un triángulo, 3,0,4 forman el siguiente, 1,5,6 forman otro triángulo y así sucesivamente.

+0

Gracias haffax, pero todavía estoy confundido. Entonces, ¿en los primeros índices (0,1,2) está describiendo solo la información del vértice, o también la información del código normal y de la textura? – GuybrushThreepwood

+0

Los tres atributos de vértice: Posición, Normal, TexCoord. Con las funciones glXxxPointer usted define el inicio de las matrices para cada atributo. Los índices cuentan desde este comienzo. – haffax