Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / Calculating exact height of point on mesh terrain

Author
Message
Lewis999
13
Years of Service
User Offline
Joined: 23rd Oct 2010
Location:
Posted: 27th Jun 2012 21:11 Edited at: 29th Jun 2012 21:01
Hello!
This is more of a maths question than anything else, but I don't know were else to post it >.<
Basically, I want to make a function like the get terrain height function, but that takes the data from a height map/array instead of a matrix.

I've just started an A-level maths course in school, and I can generally figure out stuff like this, but I've had my notepad out for over an hour trying to figure it out, and I'm still clueless.

So..
Does anyone know how the "get terrain height" function works, or an alternative way of figuring this out?
I'll keep trying, but some help would be useful ^.^
I guess I could just keep the data in a matrix and hide it, but that's still a little slow (also, how do you hide a matrix? >.<

Thanks, </Lewis>


edit:
wait a second...
would this work?
a,b and c are the heights of the 3 points in the triangle

a\
|--\
|----\
|----o-\
|--------\
b---------c

AB = 1
BC = 1

o is the point the player is on

px = x position of o relative to b (0 to 1)
py = y position of o relative to b (0 to 1)

height of o = 1/2*(b*px+a*(1-px)) + 1/2*(b*py+c*(1-py))

>.<

I'll test it now and edit with the results...



:/
It kind of works, but it's not smooth...
BMacZero
18
Years of Service
User Offline
Joined: 30th Dec 2005
Location: E:/ NA / USA
Posted: 27th Jun 2012 22:53 Edited at: 27th Jun 2012 22:58
If you assume that the player is in the triangle and that the triangle is a right triangle, you can imagine it as a rectangle with imaginary point "D" forming another right triangle opposite the first. In that case, the height would be a bilinear combination of B with C and A with D

height = (1-px) * (py*c + (1-py)*d) + (px) * (py*b + (1-py)*a)

That seems close to what you have, however you've assumed that the player is halfway between the X and Y axis (i.e. px and py are the same).

Also,
d = (a+c)/2 - b + (a+c)/2
d = a + c - b

This is a good illustration of what's going on here:
http://en.wikipedia.org/wiki/Bilinear_interpolation


Latch
17
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 27th Jun 2012 23:25 Edited at: 27th Jun 2012 23:51
Hello,

There are a couple of ways to do it. It's easiest if the triangles that make up the terrain are uniform in size and not just a triangle soup. We'll assume uniform triangles.

The general idea is this:
1. You have to find which triangle you are currently over
2. You find the face normal of the triangle. You can use the cross product of 2 sides of the triangle to find this.
3. You use the dot product with the normal and the x,z position on the triangle you want to find the height to.

What we're really doing is finding the distance between a point and a plane.

If you want to calculate this directly from the height map, you have to scale the values to what they would be if they were a terrain. For example, a height map may have gray scale heights ranging from 0 to 255. The distance between each pixel is only 1 unit. If think of the 3d coordinates of X and Z corresponding to the X and Y 2d coordinates of the height map, then the 3D Y is represented by the gray scale value.

The x and z size won't change cell to cell if you are using a rectangular or square height map as the source. So you only have to get those values once.

For the Y value, you can either calculate each y height based on the maximum terrain height allowed and the value in the height map; for example:

a gray scale map may have a minimum value of 0 and a max of 255 and your terrain may have a height from 0 to 10000

3d Y =(gray value * 10000.0)/255.0

The X and Z would just be the maximum 3D unit dimensions of your terrain divided by the number of cell tiles. Let's say we have a 1000 by 1000 unit size and a 10 by 10 cell size:

3d x = 1000/10 = 100
3d z = 1000/10 = 100

Again, you only have to calculate the x and z once. The y value will change with the gray scale values of the height map.

To find which triangle you are over, you have to get your 3d world X and Z position, and divided that by the tile dimensions we caluclated earlier:

tilex = int(posx/100)
tilez = int(posz/100)

Tilex and tilez can be matched up in you height map. If we look at the 2d height map matching up to the terrain at the lower left corner, we will consider that as 3d location (0,0,0). Tilex and tilez will give the lower left hand position of each cell so you can find it in your height map.

Once you know the position in the height map, you can now use the cross product to find your face normals. Usually you would normalize your normals after finding them but in this case, I don't think you want to - because you want to maintain their scale relative to the cell size. Also remember that there are 2 triangles in each cell so you'll have to find out which one you are on. Since the cell is divided diagonally, it splits the cell right in half. You should be able to figure out which triangle you are over given your 3D xpos and zpos.

Then use the dot product to find your height.

Does this help get you started? It sounds like a lot, but the explanation is more complicated than the code. Do you think you can start figuring things out? The pseudo code might look like this:



Enjoy your day.
Lewis999
13
Years of Service
User Offline
Joined: 23rd Oct 2010
Location:
Posted: 29th Jun 2012 21:00
Thanks for the help guys, but I still don't seem to be able to get it to work...

@BMacZero
Yeah, I originally intended to use this, but as I said above the movement is very jumpy, even using the code you posted, and the formula on the Wikipedia page...
Here's a quick demo showing what I mean, I'm using object based terrain in my game, but this just uses matrices to make it simpler.


press 1,2 and 3 to switch between functions
1 = the one you posted
2 = one on wikipedia
3 = get ground height

any help?


@latch
I understood everything up to the "using the normals to calculate height" part.
I can't figure out how normals give you the answer, I've heard many people talking about it before, but I don't know how.
>.<

can you explain it please?


Thanks , Lewis
BMacZero
18
Years of Service
User Offline
Joined: 30th Dec 2005
Location: E:/ NA / USA
Posted: 29th Jun 2012 21:52
Well, with a bit of twiddling I got it to work by moving the terms around into this formula:



I didn't try to figure out why exactly they should be in that order, but it looks like it works.

Lewis999
13
Years of Service
User Offline
Joined: 23rd Oct 2010
Location:
Posted: 29th Jun 2012 21:58
It works perfectly. Thanks so much ^.^
Latch
17
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 30th Jun 2012 01:32 Edited at: 30th Jun 2012 02:21
Quote: "I understood everything up to the "using the normals to calculate height" part.
I can't figure out how normals give you the answer, I've heard many people talking about it before, but I don't know how.
>.<

can you explain it please?"

No problem. I know it all sounds like mashed potatoes, or maybe just the way I'm trying to explain it!

Ultimately, we want to find the distance from a point to a plane. The plane, in this case, is any one of the triangles that make up a cell on the terrain. If we think of sea level at a height of ZERO units, then each triangle is above or below this height. It's from sea level, that we want to find the height at any place on these triangles. Thus finding the distance between a point and a plane.

The triangles are also tilted. They aren't just flat. Their tilt creates the bumpiness of the terrain. This tilt is at some angle. This angle is described by the normals of the plane - i.e. the normals of any triangle we are interested in. What a normal is, is a vector - an arrow/ray - pointing away from the face of our triangle at a 90 degree angle to the tilt. So this normal is telling us what the angle of the tilt is.

You can think of this normal as telling us a percentage of change over x,y and z. It's this percentage of change that allows us to determine the height at any point of the triangle.

If our normal was pointing straight up, it could look like this:
(0,1,0) where nx=0 , ny=1, and nz=0

This is describing a flat triangle that is parallel to sea level. No matter what our X and Z position we want to find, the height will always be the same. Note that since we are trying to find the ypos on the triangle, we use the sea level height ZERO as our starting point for the distance to the plane. ypos = 0

ht = (xpos * nx) + (ypos * ny) + (zpos *nz)

You can see here that if our normal is pointing straight up (0,1,0) then the height HT is always 0.

What if our triangle tilted up as if it were rotated 45 degrees around the x axis? The normal could look like:
(0,1,1)

What would our height be?

ht = (xpos * 0) + (ypos * 1) + (zpos * 1)

Here we know ypos is always zero and nx is zero in this case so the height would be based on the Z influence. I mentioned in the previous post that you shouldn't normalize the normals when trying to find the height. That is because the normal will be scaled based on the x and z dimensions of the triangle. The examples above are based on a 1 unit by 1 unit triangle so the normals kinda look like they have been normalized. They aren't, though if they were, their values would be (0,.7071,.7071).

Once you have your ht, you then add that value to the height of the point on the triangle from which you were measuring XPOS and ZPOS. That will tell you how high from sea level (assuming sea level is at ZERO for our examples) the point on your triangle is.

There's one more thing that might throw a bit of a monkey wrench in the machinery: we are measuring from BELOW the terrain to the surface of the terrain. That means the normal value for Y that we are actually interested in is pointing in the OPPOSITE direction. To adjust our ht (before adding it to our starting triangle y height) we have to divide our calculated HT value by -ny . Not too bad, but very important to get the correct height. Are you interested in finding out how we got -NY besides just saying the normal should be in the opposite direction?

Does this make sense?

Enjoy your day.
Lewis999
13
Years of Service
User Offline
Joined: 23rd Oct 2010
Location:
Posted: 30th Jun 2012 14:15
Yeah, I understand it now
Thanks, I've been wondering about that for a while

Login to post a reply

Server time is: 2024-04-27 07:39:18
Your offset time is: 2024-04-27 07:39:18