Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Rendering a height map with GL_TRIANGLE_STRIP

Credits go to Inphernic for helping out!
This thread is locked; no one can reply to it. rss feed Print
Rendering a height map with GL_TRIANGLE_STRIP
H
Member #1,673
November 2001
avatar

I have a height map, that is an array of height values, that I want to render (with OpenGL) as fast as possible. I figured using vertex arrays with GL_TRIANGLE_STRIP would be fast, but I have problems figuring out the order of the vertices for OpenGL to interpret the triangle strip correctly.
First of all, I do have to use a second array for vertex indices, right? Or is there some way to render the whole thing without specifying the same vertex several times?
Second, rendering one column is no problem, but how do I continue? Here's a picture to illustrate the problem:
http://user.tninet.se/~qjx696p/heightmap.jpg
If I start at the green point and triangle strip myself upwards, I will end up drawing a triangle from the two red points. How can I continue to the next column?

Billybob
Member #3,136
January 2003

Ok, here is how I would figure out what points to use.

*1 *2
*3 *4
*5 *6

Imagine those dots numbered like that, I'm sure you can number them the way you did, but I like it this way.

Ok, take dots 1, 2, 3 and make the triangle. Then increase this 3-set by one so you have 2, 3, 4. Then 3, 4, 5, then 4, 5, 6. Simple pattern, easily done is C++

int Verts[3];
for(int i = 0; i < 3, i++) Verts<i>++;

That'll find the next triangle. Start the array at 1, 2, 3(well accually 0, 1, 2, but whatever). And do a height map lookup with those.

Ok, now how about the next column? SIMPLE

int Col = 0;

Every time you go to a new column increase Col by one. Then wehn you do heightmap lookups:

x = Col + (Verts<i> & 1);
y = Verts<i> >> 1;
Vertexes<i> = Heightmap[x][y];

BTW, this above code accually goes by the convention of starting at 0, 1, 2, not 1, 2, 3. Got to think C/C++ here.
OK, so give the above code Verts<i> and it'll give you the vertex of that vert. Notice how Col is added, thus shifting over to the correct column.

That's my theory, should work great, plus it uses bit operations >8~).

I hope that helped. As for the vertex array of OpenGL, not sure. I think you might have to repeat vertexes, but not sure.

H
Member #1,673
November 2001
avatar

I'm not sure I understand your code completely. In this fragment:

int Verts[3];
for(int i = 0; i < 3, i++) Verts<i>++;

Shouldn't the contents of Verts be initialized? What's the point of just increasing them all?

And here:

x = Col + (Verts<i> & 1);
y = Verts<i> >> 1;
Vertexes<i> = Heightmap[x][y];

What is Vertexes supposed to hold? The indices?

I think you might have misunderstood my question. What I want is an array to draw with glVertexPointer and glDrawElements. The problem is that when I move on to a new column, GL_TRIANGLE_STRIP will draw a triangle from the red points in the picture, which is not what I want, that would screw the whole thing up.

Oh, by the way, I did number my points wrong. They should be in the order you said.

gillius
Member #119
April 2000

H you can't draw it all in a single call. You might be able to do it with the strip hack... I've never used it but I sort of heard about it where you can insert a triangle that has no area.

I just drew each column in separate calls.

Gillius
Gillius's Programming -- https://gillius.org/

Inphernic
Member #1,111
March 2001

Quote:

H you can't draw it all in a single call.

Wrong, I have code for that lying around somewhere on my CDs.. I might post it if I come across with it. :)

edit: Here, it might not be the best example but at least it works.

1void drawscene(void) {
2 sideswitch=0;
3 glBegin(GL_TRIANGLE_STRIP);
4 for (x=0; x<mapwidth-1; x++) {
5 if(sideswitch) {
6 for (y=mapheight-2; y>=0; y--) {
7 glVertex3f((x*trisize),heightofcell(x,y),z);
8 glVertex3f((x*trisize)+trisize,heightofcell(x+1,y),z);
9 }
10 }
11 else {
12 for (y=0; y<mapheight-1; y++) {
13 glVertex3f((x*trisize)+trisize,heightofcell(x+1,y),z);
14 glVertex3f((x*trisize),heightofcell(x,y),z);
15 }
16 }
17 sideswitch++;
18 if (sideswitch>1) sideswitch=0;
19 }
20 glEnd();
21}

H
Member #1,673
November 2001
avatar

Thanks, Inphernic, that seems to work. But it's still not a single function call. Isn't it possible to draw a height field with glDrawElements?

Korval
Member #1,538
September 2001
avatar

Quote:

Isn't it possible to draw a height field with glDrawElements?

Then turn his code into a list of indices.

H
Member #1,673
November 2001
avatar

Quote:

Then turn his code into a list of indices.

Hmmm...you do have a point there. That's a bit stupid of me::)
I'll see if I can get it to work.

Billybob
Member #3,136
January 2003

My method is just used to output all the triangles that need to be drawn, which seems fine to me, but if that's not what you want then oh well.

EDIT: BTW, yes you have to initalize the array. My code was more of a hint as to what needed to be coded, then accual code.

X-G
Member #856
December 2000
avatar

You could try inserting a degenerate triangle after the last one in each column, but you would still end up specifying the same vertices several times, although you could reduce it to a single call.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

gillius
Member #119
April 2000

Oh yes specifying the verts multiple times.

I forgot about even mentioning that.

In direct3D I uploaded the heightmap verts into the video card using a vertex buffer for each area of my terrain (I used a quadmap to break it down, there was no algorithm like ROAM). Then I uploaded sets of index buffers into the video card for each tri strip. then I setthe vbuf and the ibuf and drew each column of the terrain. I used culling to cull out the rectangular areas...

OK to explain it I took the terrain and cut it up into square pieces, then I used culling on the level of these pieces and rendered each piece in the view. When I rendered the piece I used the ibufs and vbufs to render column by column.

All data resided on the video card so there was no transfer over the AGP except for the requests. It is extremely fast and I didn't need to use an algorithm like ROAM to break it down as I was getting like 500+ fps.

Gillius
Gillius's Programming -- https://gillius.org/

Bob
Free Market Evangelist
September 2000
avatar

Use indices isntead of specifying vertex data over and over again. It also makes better use of the vertex cache on-board. Degenerate triangels can be culled pretty quickly, as long as you don't have too many of then (ie: normal_triangles / degenerate_triangles >= 2).

--
- Bob
[ -- All my signature links are 404 -- ]

gillius
Member #119
April 2000

Yep and I realized after my post that I used only one index buffer. In Direct3D you can set where the "starts" of the buffers are, so I used the same index buffer (representing a column) then "moved" it across my global vertex buffer. Between each column a row of verts would be shared.

Gillius
Gillius's Programming -- https://gillius.org/

Go to: