A questions regarding glDrawElements

I am having a difficult time with this function. I am using an indexed vertex array, and an array of texture coordinates.
When I use glDrawElements, the polygons draw all in the proper place, but the textures look like hell.

I checked the arrays, and the values in them are perfect (well, the vertex arrays are for sure since they have no problem drawing in the right places). I thought there must be something wrong with my arrays, but when I unrolled them into a glBegin(GL_QUADS) … glEnd() structure, everything including the textures drew perfectly.

Does anyone have any code showing how this function is supposed to work?

Maybe the api doesn’t like a texture array along with an indexed vertex array?

The render code looks like this:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindTexture(GL_TEXTURE_2D, TextureID);

glVertexPointer(3, GL_FLOAT, 0, pVertexData);
glTexCoordPointer(2, GL_FLOAT, 0, pTriTextureCoordData);
glDrawElements(GL_TRIANGLES, TriCount*3, GL_UNSIGNED_SHORT, pTriBuffer);

Set up code for the texture looks like this:

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Like I said, I made a loop that would spew out a glDraw(GL_TRIANGLES) text block with the array data as it was in memory, and all was perfect.

Thanx for any help…

P.S. When I changed the stride in glTexCoordPointer from 0 to another number, there was noticable difference with how the texture looked. I changed it to sizeof(float)*2 thinking it needed to know the distance between each array, but I saw no change in texture.

The problem is probably either in the declaration/set-up of your texture coordinate array, or in the data you put in there. Without more code to look at, all I can suggest is checking these out.

Note that changing the 0 for texcoord stride to 2sizeof(float) should not change anything – the 0 means “tightly packed” which is 2sizeof(float) in this case.

Your post also mentions GL_QUADS in one place, but uses GL_TRIANGLES in the call to DrawElements().

Another thing that sometimes trip you up is the fact that most modelers have a separate texture coordinate array/index set from the vertex coordinate array/index set, and you need to match them up and split them out for them to work with OpenGL vertices.

Sorry, yes. I mentioned quads. SHould have been triangles. (My objects are split up into 2 different primitive types - blame the obj file format for that one)

Someone was mentioning that the arrays need to be the same type as far as number of elements or something for glDrawElements to work? Not sure what that means. He was saying there is a single array pointer that passes through the arrays, so they need to be the same size?

The vertex array contains 3 floats for each 3d point. The indexes to them is an array of shorts (1 array of indexes for tris, and another array of indexes for quads), the texture coordinate array have 2 floats each (again a seperate array of them for tris, and a seperate array of them for the quads).

The arrays are synced together. In other words, if I unroll the vertex indexes as well as the texture coordinates into a glBegin(GL_TRIANGLES)…glEnd() block, they work out to be perfect.

I am only using the tris as an example here. If I do the same things with the quad arrays, I get the same results.

The person who said that the arrays have to have the same number of elements was right. It’s also what jwatte was hinting at when he said most modellers have separate texture coordinate and vertex coordinate arrays/index.

I’m making some assumptions about your model data, but hopefully I’m right. Think about it like this: If you count the number of vertex coordinates you have, and the number of texture coordinates you have, they probably aren’t the same number right now. So how will glDrawElements be able to index through both arrays, if the don’t have the same count of elements? It won’t work correctly, and that is why the model shape is correct, but the textures aren’t.

But why does it work in immediate mode? You are accessing the data differently, but just didn’t notice it. You probably thought you could just use the same data arrays from immediate mode and plop them into glDrawElements, but you can’t. And this has to do with how your modeller saves it’s data.

Most modellers will us a “front” mesh and a “back mesh” of some sort to map the skin, or maybe several mapping meshes. But lets assume a front and back for now. The mesh coordinates will have an associated model vertex, and these are associated by the fact that the faces of the mesh and the faces of the model use the same indexing. But this doesn’t give a one-to-one correspondence between each mesh vertex and each model vertex. Think about the “seam” of the front and back mesh. Here, you will have two mesh vertices map to one model vertex. Now when you go through the glDrawElement array, your mesh vertices don’t line up with your model vertices. There are more mesh vertices than model vertices, because of the seam.

To fix this, you have to find model vertices that have multiple mesh vertices mapped to them, and duplicate them so you can index your models with a one-to-one correspondence between mesh vertices and model vertices.

I know exactly what your problem, and the people who responded already explained it to you. I will explain also.

glDrawElements only cares about the vertex indices. So all array elements should be aligned to be indexed by the vertex indices.

Wow! Heh heh. I am trying to wrap (no pun intended) my head around this concept. Thank you all for your feedback. I’ll have to scrawl on a piece of paper some test numbers to fully grasp this. =)

As long as you can see a reason for it working when I unravel it as compared to when I use glDrawElements, then I have some hope there is a solution.

Lemme just throw this out to see if I am getting this yet.

When using glDrawElements, if it grabs index 5 for example from the index table, it then grabs the 3 vertices at location 5 in the vertex table. It then grabs the 5th entry in the texture coordinate array, and uses that for it’s data?

The way I have it set up, in order for it to get the right texture coordinate, it needs to go through the texture coordinate array from beginning to end regardless of what index it pulls.

So, if the 10th index contains a 8 for the vertex array, I am expecting it to pull the 10th entry from the texture coordinates, but you are all saying it will actually pull the 8th texture coordinate because the index it pulls needs to be that same as the texture coordinate entry.

God, I hope that is right. haha

OK, let me explain this very simply.

When you manually unroll your array, does the code look something like this:

glBegin(GL_TRIANGLES)
for(i = 0; i < NumberOfFaceIndicies; i++)
{
glTextCoord2fv(&TextureCoordArray[IndexArray[i]]);
glVertex3fv(&VertexArray[IndexArray[i]]);
}
glEnd();

Notice that the index for the TextureCoordArray and the VertexArray are the same for each vertex. Basically, if you wrote the vertex and texture coord elements down in a list, each vertex position would match with one and only one texture coordinate. It sounds to me like you are saying that instead of glTextCoord2fv(&TextureCoordArray[IndexArray[i]]), you want glTextCoord2fv(&TextureCoordArray[i]).

Now, if this is not the case, then you will have to duplicate some vertex positions to make this be the case. I use the term Unique Vertices for this, because each set of vertex attributes (position, normal, texture coord, etc) is specified once. OpenGL’s vertex arrays require an array of unique vertices. That’s why everybody’s asking if your texture coord array and your vertex position array are the same length.

[This message has been edited by Korval (edited 05-30-2001).]

are you sure that your texcoordarray is like this:

float tcarray[ ] =
{
u0, v0,
u1, v1,
u2, v1,
etc…
};

and no stride in…

oh… and pTriTextutreCoordData… why is it called Tri? what data is there stored in really?

cause you have to have it somehow like this:

float vertex_array[ ] =
{
v0x, v0y, v0z,
v1x, v1y, v1z,
etc…
};

and the same for the texarray

float tex_coord_array[ ] =
{
v0u, v0v,
v1u, v1v,
etc…
};

then it should work…

Sorry. It’s hard for me to explain how the data is set up.

I have 3 arrays. A texture coordinate array, a vertex array, and a triangle index table which accesses the vertex array

So,

TextureCoords:
[0] 0.12345, 0.23456
[1] 0.34567, 0.45678
[2] 0.56789, 0.90123
.
.
.

Vertices:
[0] 0.12345, 0.23456, 0.34567
[1] 0.45678, 0.56789, 0.90123
[2] 0.01234, 0.12345, 0.23456
.
.
.

TriangleIndexes:
[0] 2, 8, 7
[1] 6, 5, 4
[2] 3, 2, 1
.
.
.

Setup is like this:

// Pre-setup
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, Vertices);

// Draw…
glTexCoordPointer(2, GL_FLOAT, 0, TextureCoords);
glDrawElements(GL_TRIANGLES, TriCount*3, GL_UNSIGNED_SHORT, TriangleIndexes);

Now, here is the question I asked previously. See how the first triangle index is 2? The way the texture coordinate data is set up in my code, opengl would need to map the first entry in the texture coords with the 2nd entry in the vertices:

glBegin(GL_TRIANGLES);
glTexCoord2f(0.12345, 0.23456); glVertex3f(0.01234, 0.12345, 0.23456);
.
.
.
glEnd();

Currently, if I continue to the next index (8), I would map the second texture coordinate in the table (0.34567, 0.45678) with the 8th entry in the vertices.

If I unroll the data like that while stepping through the texture coordinates from beginning to end linearly (regardless of the indexes I pull), it is perfect.

So, if I grab index 123, are you saying that the texture coords for that point MUST be at the 123rd entry in the texture coords? In essence, is the index number I pull out not only used for getting the vertex, but is it also linked to the texture coords table in the same way?

Because the way the data is set up now, if on my 5th iteration, I grab an index of 123, the texture coordinate for it is in the 5th position in the texture coords (I have them set up for linear stepping)

I assumed that if I am stepping through the index table, I would set the texture coords table up that same way for linear stepping (again, regardless of the indexes that come out)

And yes, if I can unroll the data into the tables and draw it fine, there must be the same amount of vertex indexes and texture coordinates.

[This message has been edited by OpenGLRox (edited 05-30-2001).]

“I assumed that if I am stepping through the index table, I would set the texture coords table up that same way for linear stepping (again, regardless of the indexes that come out)”

Why would you assume that? It doesn’t make any sense for any indexing method to work that way, especially if that indexing method provides for strips and fans in addition to simple triangle lists.

Ya know, I wouldn’t mind the name vertex arrays if they had called glVertexPointer glPositionPointer instead. Just know that, in the following, when I say Vertex, I mean all the vertex’s data (position, texture coords, color, normal, etc). When I say position, I mean just the position.

So, when you use glDrawElements, it gets the particular indices out of each array. If the first index in the array you send to glDrawElements is 12, then it will pull out the 12th value out of each of the arrays. Hence the need for using arrays of unique vertices.

Thank you Korval. A long winded YES, but a yes nonetheless.

“Why would you assume that? It doesn’t make any sense for any indexing method to work that way, especially if that indexing method provides for strips and fans in addition to simple triangle lists.”

Dude, there are nicer ways to help people out than to get in their face about a simple mistake. I suggest if you want to help people in the future, re-read your messages and make sure they don’t come off snotty like that last paragraph.

And for the rest of you, thank you for your time. =) I appreciate the way you tried to help me with the examples.