0
101 Nov 27, 2007 at 00:34

I need to calculate the slope/angle of a triangle, for my terrain engine.

Is this the right way to do it:

n = calcFaceNormal(v0, v1, v2);

angle = acos(worldYAxis.dot(n))


It seems to give me the correct results however I don’t get any sign information, so I don’t know if the face is sloping down or up :/
I guess I can get that information by checking the vertices, but is there another way? A more math correct way err..?

Thanks.

#### 9 Replies

0
167 Nov 27, 2007 at 02:31

I think what you want is: sqrt(n.x*n.x + n.z*n.z) / n.y
Assuming the Y axis is up, this number will be 0 if the triangle is perfectly horizontal, increasing to 1 where the triangle is at a 45 degree angle with horizontal, increasing to infinity where the triangle is perfectly vertical. If you want an angle instead, try atan2(n.y, sqrt(n.x*n.x + n.z*n.z)). This angle will be 0 when the triangle is horizontal, to pi/2 when it is vertical.

Regarding “sloping down or up”…assuming your triangle are all facing upwards (as they should be for terrain triangles), this question has no meaning. It’ll be up if you move along the triangle one way, down if you move the other way. The triangle by itself has no intrinsic upness or downness.

Now, if some triangles face up and some face down, the above expressions will give you negative results for the down-facing ones. But I don’t think that’s quite what you want.

0
102 Nov 27, 2007 at 02:56

Is the front of a hill sloping up and the backside sloping down? Err.. or is it the other way around? What if I’m coming from the other side? ;)

0
101 Nov 27, 2007 at 03:05

I think what you want is: sqrt(n.x*n.x + n.z*n.z) / n.y
Assuming the Y axis is up, this number will be 0 if the triangle is perfectly horizontal, increasing to 1 where the triangle is at a 45 degree angle with horizontal, increasing to infinity where the triangle is perfectly vertical. If you want an angle instead, try atan2(n.y, sqrt(n.x*n.x + n.z*n.z)). This angle will be 0 when the triangle is horizontal, to pi/2 when it is vertical.

Hm.. I tried the atan2() and it gives the same result as 90 minus my acos() function. So the angle actually gets bigger when it should get smaller and gets smaller when it should get biggger, at least imo.
So:
atan2(n.y, sqrt(n.x*n.x+n.z*n.z)) == 90.0 - acos(worldYAxis.dot(n))

Of course, converting to degrees before that, I just excluded that from that piece.
So is that atan2 thing really right?

I have setup a window with a view of a single triangle where I do my testing. And there I have a triangle with these coordinates: v0[-1, 10, -1] v1[-1, 0, 1] v2[1, 0, 1].
And these are the results:

my acos = 78.69007

If i change v0 to v0 [-1, 2, -1] both give me 45 degrees. And if I change to v0 [-1, 0, -1] I get 90 from your atan2 and 0 from my acos. So to me it looks like my way is the right way :/

Regarding “sloping down or up”…assuming your triangle are all facing upwards (as they should be for terrain triangles), this question has no meaning. It’ll be up if you move along the triangle one way, down if you move the other way. The triangle by itself has no intrinsic upness or downness.

Hehe, you’re right :D Dunno what I was thinking hehe…

0
102 Nov 27, 2007 at 06:49

Are you absolutely sure you want to work with angles? :huh: It makes formulas more complex, less accurate, and slower.

0
101 Nov 27, 2007 at 08:24

@Nick

Are you absolutely sure you want to work with angles? :huh: It makes formulas more complex, less accurate, and slower.

Hm.. so what’s your suggestion? :huh:

0
102 Nov 27, 2007 at 10:40

@pago

Hm.. so what’s your suggestion? :huh:

Instead of using acos(worldYAxis.dot(n)), use just worldYAxis.dot(n) and adjust all depending formulas accordingly. Chances are that the next thing you do with the angle as take the cosine, making the whole conversion pointless…

On road signs they also typically indicate the slope in percentage instead of an angle. For example at 5% you know that after a kilometer you’ve climed 50 meters.

It’s just another way of thinking about slope. You almost never need trigonometric functions in any game code.

0
101 Nov 27, 2007 at 18:01

Do you actually want the gradient in one axis ? - I usually find that the vector
with maximum gradient (‘grad’) is more useful, mathematically this is the vector whose components are the individual gradients in the respective axes. This
gives a good direction for things ‘sliding’ off the plane, etc.

0
167 Nov 28, 2007 at 00:22

@pago

So is that atan2 thing really right?

I might’ve switched the arguments. I can never remember whether it is atan2(y,x) or atan2(x,y)…

0
101 Nov 28, 2007 at 04:08

atan2(y,x). “Confusing programmers for 30 years!” (tm)