Archived

This topic is now archived and is closed to further replies.

dinotrack

Terrain rendering question

Recommended Posts

dinotrack    122
I wrote some code that reads the height value(Y) from a heightmap tga file. The heightmap is 256x256. It stores the values in an array. But I cannot figure out how to calculate and store the X and Z values. I assumed these would be stored in a 256x256 array also, and they would run from 0 through 255, but I don''t know for sure. I need to draw the terrain as GL_TRIANLES(or GL_TRIANGLE_STRIP would be better, but I want to keep it simple for now). But I don''t know how I can calculate the triangles from the arrays of vertices and draw them. So can someone please help me out. Thanks, Jonathan

Share this post


Link to post
Share on other sites
Seaman    122
If u want even spacing for the x and y, u could do something like this(plot vertexs 0.5f apart):-

for(int x=0;x<256;x++)
for(int z=0;z<256;z++)
glVertex3f(x*0.5f, height[x][z], z*0.5f);

if that makes any sense.

Should work I think.

Share this post


Link to post
Share on other sites
Curro    122
This is a section of code without variables. with this code you can display the all the terrain (no eficient).




^ .....
| .....
z .....
x-->


for(x=0; x<255; x++) {
x1 = x;
x2 = x + 1;
z = 0; // if you are in another position you need this
z1 = z;
z2 = z + 1;

glBegin(GL_TRIANGLE_STRIP);
glVertex3f(x2, y[x+1][z], z1);
glVertex3f(x1, y[x,z] ,z1);
glVertex3f(x2, y[x+1][z+1], z2);
glVertex3f(x1, y[x][z+1], z2);

for(z=2; z<255; z++) {
z1 = z;
glVertex3f(x2, y[x+1][z], z1);
glVertex3f(x1, y[x][z], z1);
}
glEnd();
}

The real code is:

void DrawTerrain(float pos_x, float pos_z, int min_x, int min_z, int max_x, int max_z)
{
register int x, z ;


glDisable(GL_NORMALIZE);

pos_x = pos_x/mapscale;
pos_z = pos_z/mapscale;

for(x=pos_x+min_x; x x1 = x*mapscale;
x2 = x*mapscale + mapscale;
z = pos_z+min_z;
z1 = z*mapscale;
z2 = z*mapscale + mapscale;


glBegin(GL_TRIANGLE_STRIP);

glNormal3f(n[INDEX(x+1,z)].x1,n[INDEX(x+1,z)].y1,n[INDEX(x+1,z)].z1);
glColor3f(c[INDEX(x+1,z)].r, c[INDEX(x+1,z)].g, c[INDEX(x+1,z)].b);
glTexCoord2f((x+1)/tetureres, (z)/tetureres);
glVertex3f(x2, y[INDEX(x+1,z)], z1);


glColor3f(c[INDEX(x,z)].r, c[INDEX(x,z)].g, c[INDEX(x,z)].b);
glTexCoord2f((x)/tetureres, (z)/tetureres);
glVertex3f(x1, y[INDEX(x,z)], z1);

glColor3f(c[INDEX(x+1,z+1)].r, c[INDEX(x+1,z+1)].g, c[INDEX(x+1,z+1)].b);
glTexCoord2f((x+1)/tetureres, (z+1)/tetureres);
glVertex3f(x2, y[INDEX(x+1,z+1)], z2);

glNormal3f(n[INDEX(x,z+1)].x2,n[INDEX(x,z+1)].y2,n[INDEX(x,z+1)].z2);
glColor3f(c[INDEX(x,z+1)].r, c[INDEX(x,z+1)].g, c[INDEX(x,z+1)].b);
glTexCoord2f((x)/tetureres, (z+1)/tetureres);
glVertex3f(x1, y[INDEX(x,z+1)], z2);


for(z=(pos_z+min_z)+2; z z1 = z*mapscale;

glNormal3f(n[INDEX(x+1,z)].x1,n[INDEX(x+1,z)].y1,n[INDEX(x+1,z)].z1);
glColor3f(c[INDEX(x+1,z)].r, c[INDEX(x+1,z)].g, c[INDEX(x+1,z)].b);
glTexCoord2f((x+1)/tetureres, (z)/tetureres);
glVertex3f(x2, y[INDEX(x+1,z)], z1);

glNormal3f(n[INDEX(x,z)].x2,n[INDEX(x,z)].y2,n[INDEX(x,z)].z2);
glColor3f(c[INDEX(x,z)].r, c[INDEX(x,z)].g, c[INDEX(x,z)].b);
glTexCoord2f((x)/tetureres, (z)/tetureres);
glVertex3f(x1, y[INDEX(x,z)], z1);

}

glEnd();
}

}

Share this post


Link to post
Share on other sites
dinotrack    122
I think I can figure it out if I can arrange the data differently.

The heightdata, the Y value, is in a huge 256x256 array.

How would I put this in a 2-dimensional [256][256] array?

I''ve been trying to figure it out, but I just cant work out how to make a loop that will do it.

Share this post


Link to post
Share on other sites
zedzeek    529
do what seaman said.

alternativly

float height[256][256];

for(int x=0;x<256;x++)
{for(int z=0;z<256;z++)
glVertex3f(x*0.5f, height[x][z], z*0.5f);

sorry bout posting this
(is there a way i can use a tab key as a tab key when i type in stuff)

Edited by - zedzeek on July 25, 2000 6:32:23 PM

Share this post


Link to post
Share on other sites
zedzeek    529
do what seaman said.

alternativly

    
float height[256][256];
VERTEX landsclape[256][256];

for(int x=0;x<256;x++)
{ for(int z=0;z<256;z++)
{ landscape = VERTEX(x*0.5f, height[x][z], z*0.5f);
}
}

Share this post


Link to post
Share on other sites
dinotrack    122
My height data is in just a 1-dimensional array, that is heightdata[65536].

But, I don''t know how I can put these values into a 2d array.

Any suggestions? I can''t figure out a loop that can work.

Share this post


Link to post
Share on other sites
ralphe    122
change height[x][y] to height[(x << 8) + y].

this totally depends on how you stored the original (1-dimensional) array, ie. ordered by rows or columns first.

normally one would create multiple rows of columns, where y addresses a row and x a column. then you would get: (height[y][x] ->) height[(y << 8] + x].

Hope that makes everything clear.

Share this post


Link to post
Share on other sites
bosco    122
I think you're looking for this..

        
for(x=0; x<256; x++)
{
for(y=0; y<256; y++)
{
NewArray[x][y] = OriginalArray[(x*256)+y]
}
}


That should do it.. I tried to do it with as few outside parameters as possible.. therefore it's prone to errors.. But, it should work.. let me know if that's what you wanted..


bosco()




--
leader of the free world .. or something ..

Edited by - bosco on July 25, 2000 11:53:57 PM

Share this post


Link to post
Share on other sites
dinotrack    122
Hi, its me again.

Well, I drew the terrain as GL_POINTS. It looked okay, a grid of points at different elevations, corresponding to the heightmap.

However, I would like to draw the terrain as a solid mesh now.

I tried drawing it as triangles, triangle strip, polygon, quads, quad strip.

But they all look pretty much the same, terrible. They are just rows, not even half-connected, with holes in them, and floating in mid air all over the place.

I don''t know how to draw them as a solid mesh of triangles, or whatever.

Any ideas?

Share this post


Link to post
Share on other sites
Gladiator    127
        
for (int x = 0; x < 255; x++)
{
for (int z = 0; z < 255; z++)
{
SetVertex(V1, x*5, height_map[x ][z ], z*5);
SetVertex(V2, x*5+5, height_map[x+1][z ], z*5);
SetVertex(V3, x*5+5, height_map[x+1][z+1], z*5+5);
SetVertex(V4, x*5, height_map[x ][z+1], z*5+5);

WorldToCamera(V1, Camera);
WorldToCamera(V2, Camera);
WorldToCamera(V3, Camera);
WorldToCamera(V4, Camera);

ProjectPoint(V1);
ProjectPoint(V2);
ProjectPoint(V3);
ProjectPoint(V4);

color = RGB(height_map[x][z], height_map[x][z], height_map[x][z]);

DrawTriangle(hDC, V1, V2, V4, color);
DrawTriangle(hDC, V2, V3, V4, color);
}
}


That's how you do it.. you basically connect two points from the height_map....

and make a triangle out of it...

-------------------------------
That's just my 200 bucks' worth!

..-=gLaDiAtOr=-..

Edited by - Gladiator on July 26, 2000 11:03:19 AM

Share this post


Link to post
Share on other sites
bosco    122
Hey,

Glad that snippet of code helped.. Reminds me of the days when you had to reference the screen 320x240 by doing a 320*x + y..

Anyway, back to the point.. It's funny you're asking these questions because I just got my targa loader to work ( right anyway.. ) the other day and I'll be headed in this direction as soon as I get off my lazy ass..

As far as drawing the terrain as simple quads, have you checked out tutorial 11? I know it may not be obvious, but in fact it's very applicable in the way I draw the grid.. It's a 45x45 instead of 256x256 but it's relatively the same concept.

As far as drawing triangles and/or triangle strips, I don't have a lot of experience, but let me throw one idea at you.

Once you can draw the array as quads, the step to triangle strips shouldn't be a great one. The following is prone to errors as I've never done it, but I believe it's correct. Triangle strips are drawn with the first three vertices being the first triangle and then every point after that making a triangle. N-2 triangles are drawn.

                
1------------3-------------5
| | |
| | |
| | |
| | |
2------------4-------------6


So imagine this as two quads side by side. You would do this in psuedocode OpenGL code.


glBegin( GL_TRIANGLE_STRIP );
Vertex( 1 );
Vertex( 2 );
Vertex( 3 );
Vertex( 4 );
Vertex( 5 );
Vertex( 6 );
glEnd();



Of course, what you want to remember now, is that the code I gave earlier for sorting your array was simply for rows and columns. What you may have noticed from this post is that you may want to either have a seperate array or sort the one you have now so it's advantageous for drawing this way.. In other words ordered so you can feed a glBegin( GL_TRIANGLE_STRIP ) with vertices in order of your array (i.e. MyArray[0..1..2..3] instead of coming up with some unique reference scheme each time.. Alternately you could write all this as a class ( are you?? ) and have handler functions..

Whew.. hope this is all right.. Written from the sleeve of my shirt so who knows.. But, send me an email if you want more help or post here..


bosco()


--
leader of the free world .. or something ..

Edited by - bosco on July 26, 2000 10:44:20 AM

Edited by - bosco on July 26, 2000 10:45:13 AM

Share this post


Link to post
Share on other sites
zedzeek    529
i wouldnt draw a landscape with quads use triangles. quads give u nasty things when a polygon is clipped with the normals.

but if u wanna use quads try this

        
for (x=0;x<WORLDSIZE;x++)
{ for (y=0;y<WORLDSIZE;y++)
{ glBindTexture(GL_TEXTURE_2D, mapSquare[x][y].terrain_texture);

glBegin(GL_QUADS);
glNormal3fv(mapSquare[x][y].normal); glTexCoord2f (0, 1); glVertex3f(x*SQUARESIZE ,mapSquare[x][y].height , y*SQUARESIZE);
glNormal3fv(mapSquare[x][y+1].normal); glTexCoord2f (1, 1); glVertex3f(x*SQUARESIZE ,mapSquare[x][y+1].height , (y+1)*SQUARESIZE);
glNormal3fv(mapSquare[x+1][y+1].normal); glTexCoord2f (1, 0); glVertex3f((x+1)*SQUARESIZE ,mapSquare[x+1][y+1].height , (y+1)*SQUARESIZE);
glNormal3fv(mapSquare[x+1][y].normal); glTexCoord2f (0, 0); glVertex3f((x+1)*SQUARESIZE ,mapSquare[x+1][y].height , y*SQUARESIZE);
glEnd();
}
}



mapSquare[x+1][y] == mapSquare[x<<8+1+y]

Edited by - zedzeek on July 26, 2000 6:19:00 PM

Share this post


Link to post
Share on other sites
dinotrack    122
Thanks everyone for your help. I finally got it working!

I used triangle strips for drawing the terrain.

Now I guess I better implement some texture mapping and LOD.

See ya,
Jonathan



Share this post


Link to post
Share on other sites