Vertex Arrays and Texture Coordinates

Greetings again all,

I’m trying to use a vertex array to render a texture-mapped cube. It has the 8 points in it and I use glDrawElements as follows:

GLubyte front[] = {4, 5, 6, 7};
GLubyte back[] = {0, 3, 2, 1};
GLubyte left[] = {0, 4, 7, 3};
GLubyte right[] = {1, 2, 6, 5};
GLubyte top[] = {2, 3, 7, 6};
GLubyte bottom[] = {0, 1, 5, 4};

glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, front);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, back);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, left);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, right);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, top);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, bottom);

The problem is, I can’t just give it 8 texture coordinates that correspond to the 8 vertices because the texture coordinates varies with the side that’s being drawn.

The only thing I can think of to solve this problem would be to use the stride feature and define 3 texture coordinates per vertex, then before drawing a side set glTextureCoordPointer to the proper “offset”. That would take a bit of work I’d think.

Is there an easier/better solution?

Thanks
Joe

I posted this on another forum too and someone recommended just going ahead and declaring 24 vertices, that way the texture coordinates could match up and I could render the whole prism with one call to DrawElements instead of 6. I can see merit to that, but doesn’t declaring 24 vertices defeat the purpose of vertex arrays? I mean, wasn’t the purpose of their design so that you could share like what I describe?

Thanks

I think what they were saying is that you have 6 arrays with index info. You could make a 2D array GLubyte cube[6][4] = {(a1,a2,a3,a4),(b1,b2,b3,b4), etc…}
and call glDrawElements once.

As far as your problem with the texture, I am not sure. I assume you have a square texture that you want to map to the entire surface of the cube? Depends on how distorted you do or don’t want it to look.

Thanks shin,

Yes that’s exactly what they were saying. But my question is, if you end up declaring 24 vertices anyway doesn’t that defeat the purpose of vertex arrays? What I’m saying is I was under the impression that the whole point of vertex arrays is being able to share vertices - that is, having an array of 8 vertices instead of an array of 24. The drawback being, if you only declare 8 vertices you will end up needing more than one normal vector and/or texture coordinate per vertex.

Maybe I should word the question like this - if I were to render a textured cube using arrays of 24 vertices, 24 normals and 24 texture coordinates would it be considered an “inefficient design”, i.e. would it have been better if I could have tried to do the same job with only 8 vertices?

That make a little more sense what I’m getting at?

Thanks

Yes, you are correct, but you aren’t declaring 24 vertices. You still only have the 8 vertices you started with. You are just making 1 call to glDrawElements instead of 6 calls by consolidating your 6 arrays shown above into a 2D array.

Instead of this:

GLubyte front[] = {4, 5, 6, 7};
GLubyte back[] = {0, 3, 2, 1};
GLubyte left[] = {0, 4, 7, 3};
GLubyte right[] = {1, 2, 6, 5};
GLubyte top[] = {2, 3, 7, 6};
GLubyte bottom[] = {0, 1, 5, 4};

glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, front);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, back);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, left);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, right);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, top);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, bottom);

you have:

GLubyte cube[6][4] = {(4, 5, 6, 7), (0, 3, 2, 1), (0, 4, 7, 3), (1, 2, 6, 5), (2, 3, 7, 6), (0, 1, 5, 4)};

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, cube[0]);//one of my compilers will not accept just cube, the other will, so cube[0] or cube could right dependent on your compiler

No extra vertices are created, just 1 call to glDrawElements.

edit…
added 1 comment to code

[This message has been edited by shinpaughp (edited 02-28-2003).]

Hmmmm. Just reread your posts again. I do see what you are saying. There are many ways of constructing the primitives that make up an object. Which is best overall and most efficient. That is your question? Good question, too.

I’ve seen many posts about the advantages and disadvantages of immediate mode, display lists, elements, vertex/normal/etc arrays, and interleaved arrays. Should you use glDrawElements or should you use glDrawArrays or glInterleaved arrays or display lists? I dunno. Yes, in the end to make a cube there will be 24 vertices used whether you reference them directly or by indexes or just use glVertex calls making quads. Of course there are quad strips and triangle strips and triangle fans which allow fewer vertices to be referenced. So, you could use 2 quad strips which would allow you to make the cube with 16 vertices.

The truth is, I cannot answer that question. I really don’t think that there is a definitive answer because too much is dependent on the hardware with results varying greatly by GPU, CPU and software by OS, drivers, implementation of code (efficiency of code itself not just which gl functions used), etc, from what I have read and seen.

I think that it is best to find what you are most comfortable with, especially as you might get into rendering large numbers of vertices for more detailed and complex objects. Do you really want to be setting indices into an array by hand. In that respect I like arrays better than elements, but your memory consumption is greater.

Just looked at the book and saw that there is the example you showed, along with the consolidated array. Again, you might as well try them all out, and find what you like best. And, if you are doing quads see if you can use quad strips instead, and for triangles see if you can use triangle strips or fans instead.

I’ve rambled for far too long.
Good luck with it all.