Drawing from a vertex array

I’m creating a simple program that draws data from a vertex array using glDrawArrays(), in the array are single points that will be used to make a heightmap. However the only way I can get an understandable output is to draw GL_POINTS, if I use any other primitive, i.e. GL_QUADS, I get lots of random polygons. I’m assuming this is because you need to group the data in the vertex array? e.g. the first 4 points would make up the 4 corners of a quad, the second 4 would make another quad. However this would involve creating extra entries in the array because when the quads are next to each other they will share the same point.

Now my problem is that my array will be huge (possibly hundreds of thousands of points) so I want to limit repeated entries. So my other choice is to use an index array and use glDrawElements() or something simlar, but then I would have 2 huge arrays; vertex and indices.

What would be the best way to go about this?
Thanks for any advice?

If you use a index array you can reuse a vertex 4 to 7 times. So both arrays together would be smaller than the single one.

Originally posted by oc2k1:
If you use a index array you can reuse a vertex 4 to 7 times. So both arrays together would be smaller than the single one.
I will be using it for a heightmap so in essence it will be hundreds of quads “alongside”, so I would use each vertex in the 4 surrounding quads so I guess that would be better, thanks. How would I specify the colour for each quad though, because at the moment I have a color array which is called automatically with glDrawArrays (each color will be set depending on the z coordinate value for that particular point). Is there an equivalent function I could use alongside glDrawElements() that would give the same result?

glDrawArrays and glDrawElements do the same thing in terms of any GL_*_ARRAY enabled client states. The only difference is that one draws everything while the other uses an index lookup.

Use triangle or quad strips instead of quads(Quads are rendered as triangles anyway).This way you will index each vertex only twice.
I used to use quads in one my programs for heightmaps too. When I switched to strips I saw a substantial performance gain.

After a break I’ve come back to this program but I still can get it to work. I have the following 12 vertices in a vertex array:

0.000, 0.000, 0
0.000, -2.000, 0
0.000, -4.000, 0
2.000, 0.000, 0
2.000, -2.000, 2
2.000, -4.000, 2
4.000, 0.000, 0
4.000, -2.000, 4
4.000, -4.000, 4
6.000, 0.000, 0
6.000, -2.000, 4
6.000, -4.000, 4

And then I’ve created an index array which looks like:

index[] = {0, 1, 3, 4, 
	        1, 2, 4, 5,
		3, 4, 6, 7,
		4, 5, 7, 8,
		6, 7, 9, 10,
		7, 8, 10, 11};

Then I draw it using:
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, index);

But this isnt drawing it ‘properly’. Its roughly the right shape but there’s triangle gaps everywhere and it just doesn’t look right in general. However if I draw it using GL_POINTS it looks perfect. I know there is something really dumb I am overlooking but I cant for the life of me work out what it is :frowning:

Any ideas? Thanks.

My 50 cents: consider using TRIANGLE_STRIP or QUAD_STRIP for terrain. This way DrawElements won’t be needed.

And to your problem… Does it look right if you draw the array “manually” - by looping through the index array and submitting the vertices with glVertex? If yes, there will be some problems with your array setup (for example, are you sure that index is a byte array?).

Even with TRIANGLE_STRIP, DrawElements can be useful. You can draw an entire strip of terrain without repeated vertexes, but if you draw the strip next to it, you’ll have to repeat half of the ones you just drew. You can connect these two with a degenerate triangle, of course.

I notice 2 things are not right in your index array.
First, each quad is not a coplanar (4 vertices are not on a same plane.). Second, the order of verteices in index array are not counter clock wise. (Yours are more like triangle strip vertex sequence, zig-zag.)

The solution of the first issue is using GL_TRIANGLES or GL_TRIANGLE_STRIP, instead of GL_QUADS. And, rearrange index order as CCW to resolve the second issue.

Here is a quick fix using GL_TRIANGLES , but, please consider GL_TRIANGLE_STRIP, that others mentioned.

GLubyte index[] = {
0, 1, 4,
0, 4, 3,
1, 2, 5,
1, 5, 4,
3, 4, 7,
3, 7, 6,
4, 5, 8,
4, 8, 7,
6, 7, 10,
6, 10, 9,
7, 8, 11,
7, 11, 10

// draw VA
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, index);