# per triangle terain height

This topic is 4425 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, Until now I was doing my height lookup through a bilinear interpolation. I'm now trying to do it per triangle for accuracy, so it matches the visual terrain. But I sort of got stuck. When the two triangles normals are not parallel, the code below gives bad result (point at center is either above or below the surface in that case). I know why, but I can't really figure a way how to do it right. I think the last lerp is wrong.
float CTerrain::GetHeight(float x, float z) const
{
float p1;
float p2;
float p3;
float p4;
float dx;                // [0-1] x coordinate
float dz;                // [0-1] z coordinate
float h_top;             // p1 to p2
float h_btm;             // p3 to p4
int fx = floor(x);
int fz = floor(z);
p1 = GetHeight(fx,     fz);
p2 = GetHeight(fx + 1, fz);
p3 = GetHeight(fx,     fz + 1);
p4 = GetHeight(fx + 1, fz + 1);
dx = x - fx;
dz = z - fz;
if (dx + dz < 1) {
// triangle A
h_top = Lerp(p1, p2, dx);
h_btm = p3;
} else {
// triangle B
h_top = p2;
h_btm = Lerp(p3, p4, dx);
}
return Lerp(h_top, h_btm, dz);
}


Triangle A is top left (x-,z-), triangle B is bottom right (x+,z+). Source/pseudo code is highly appreciated, for I completely suck at math theory.

##### Share on other sites
I didn't look at your code too carefully, but the easiest way is probably to:

1. Identify the triangle corresponding to the point (I think you're already doing this?)

2. Use the plane equation of the triangle to solve for the height given the 2D point coordinates

You can test the first part by drawing the target triangle in a different color, just to make sure that you're getting the right one. The calculation in step 2 is pretty easy, but post back if you have any problems with it.

##### Share on other sites
extern float getheight(float x,float z){   float r=0;//only r   int ix=(int) x, iz=(int) z;   if( ix<0 || iz<0 || ix+1>=heightmapx || iz+1>=heightmapz);   else{      x-=(float)ix;      z-=(float)iz;      float oneminusx=1-x;      float oneminusz=1-z;      r+=oneminusx*(heightmap[(ix+(iz*heightmapx))]);      r+=oneminusz*(heightmap[(ix+(iz*heightmapx))]);      r+=oneminusx*(heightmap[(ix+((iz+1)*heightmapx))]);      r+=z*(heightmap[(ix+((iz+1)*heightmapx))]);      r+=x*(heightmap[((ix+1)+((iz+1)*heightmapx))]);      r+=z*(heightmap[((ix+1)+((iz+1)*heightmapx))]);      r+=x*(heightmap[((ix+1)+(iz*heightmapx))]);      r+=oneminusz*(heightmap[((ix+1)+(iz*heightmapx))]);      r/=4;      return(r);   }   return(0);}

Though I later optimised it this results in per tri height.

##### Share on other sites
Allright, I figured it out.

Here's the code:
float CTerrain::GetHeight(float x, float z) const{ float p1; float p2; float p3; float p4; float dx; float dz; int fx = floor(x); int fz = floor(z); p1 = GetHeight(fx,     fz); p2 = GetHeight(fx + 1, fz); p3 = GetHeight(fx,     fz + 1); p4 = GetHeight(fx + 1, fz + 1); dx = x - fx; dz = z - fz; if (dx + dz < 1) {  return p1 + ((p2 - p1) * dx) + ((p3 - p1) * dz); } else {  return p4 + ((p3 - p4) * (1 - dx)) + ((p2 - p4) * (1 - dz)); }}

The idea is that (in case of triangle A) you calculate two vectors from p1 to p2 and p3, and use those two to 'transform' the point at (x,z). E.g.:

vx = p2 - p1
vz = p3 - p1
height = p1 + (vx * dx) + (vz * dz)

@Th0ughtCr1me: Doesn't your code do just a bilerp or something?

##### Share on other sites
No it's per triangle, and based on classic rasterization techniques. as is it results in a:

glBegin(GL_TRIANGLE_STRIP);
glVertex3f(1,0,0);
glVertex3f(0,0,0);
glVertex3f(1,0,1);
glVertex3f(0,0,1);
glEnd();

order, and is faster than a straight triangle check.

I'm Glad you got yours working though :)

1. 1
Rutin
29
2. 2
3. 3
4. 4
5. 5

• 13
• 13
• 11
• 10
• 13
• ### Forum Statistics

• Total Topics
632959
• Total Posts
3009468
• ### Who's Online (See full list)

There are no registered users currently online

×

## Important Information

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!