# Help Planes & Angles

14 replies to this topic

### #1mysticman

Member

• Members
• 95 posts

Posted 30 October 2005 - 04:37 PM

Do you know a way of positioning a model in base to the plan where it is, respecting the current angles of the model?

I have tried this old function, but it doesn't work well


void vectoanglenormaled (vec3_t value1, float angleyaw, vec3_t angles)

{

float	forward, yaw, pitch;

yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);

forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);

pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);

if (pitch < 0)

pitch += 360;

angles[PITCH] = -pitch;

angles[YAW] =  yaw;

angles[ROLL] = yaw - angleyaw;

}



an example of call

vectoanglenormaled (plane.normal, 0, angles);
:whistle:

### #2Wernaeh

Senior Member

• Members
• 368 posts

Posted 30 October 2005 - 11:55 PM

Hi there!

Could you maybe rephrase your question a little bit ?

It's not really obvious what you want to do (ie. what input do you have, and what output). Also, naming a function parameter value1 isn't actually helpful in regards to code readability.

Do you want to get an angle representation of the model's viewing vector ?

Cheers,
- Wernaeh

### #3mysticman

Member

• Members
• 95 posts

Posted 31 October 2005 - 09:04 AM

From the moment that I express badly me in English, we see if I succeed in making to understand you with an image...:lol:

### #4Wernaeh

Senior Member

• Members
• 368 posts

Posted 31 October 2005 - 01:47 PM

Hi there again =)

I think I understand your problem now.

You have a polygon on your terrain, given by its plane equation (i.e. normal and distance). Then you want to orientate your model so that it is looking into a given direction, but rotate it so its viewing vector is parallel to the terrain plane.

Well, first I have bad news for you. There is no _comfortable_, _universally applicable_ way to do this using euler angles.

First, one thing that has a large influence on your problem is what order you perform your rotations in (i.e. first yaw, then roll, then pitch, or another sorting).
Also, there are various problems when dealing with angles (mainly gimbal lock, google for it).

Now, the usual way to handle this would be either matrices or quaternions.

I'll describe a way that uses matrices internally to solve the problem, you then will need to transform the matrix back to your angle representation.

Each orientation can - apart from 3 angles - also be described by 3 perpendicular vectors, the "up", "right" and "front" vectors respectively. If you think of the room you are in as the world coordinate system, the "up" vector of yourself would point straight up to the ceiling, the "right" vector is the direction your right arm points into if you raise it straight up, and your nose points into the "front" direction.

First, you know that your new model rotation should have the plane normal as the "up" vector. (Think about it: the vertical axis of your model should be the same as the plane normal).
Then, you have a given "semifront" vector (i.e. a vector that indicates the direction your model should face into, yet not parallel to the plane, and not perpendicular to the "up" vector)
However, you can use "semifront" and "up" to build the "right" vector of your model by using the cross product on them. Then, you can use the resulting "right" vector, and calculate it's cross product with the "up" vector to get a new "front" vector that is parallel to the plane and perpendicular to both "up" and "front".

Place these vectors into a 3x3 matrix.
You can directly use this matrix to represent the object's orientation, as required for instance in OpenGl or DirectX api calls.

Now follows the difficult part - extracting angles from these vectors.

Build (by hand, on paper, using sine and cosine, and the yaw, pitch, and roll angles, or use maple or similiar) the compound rotation matrix that performs yaw, pitch, and roll operations in the order you use. You will, from the resulting matrix, be able to figure out your angles one by one, using inverse sines and cosines mostly. There are several exceptional cases to look out for, mainly gimbal lock related.
(google for the hexagon / flipcode Matrix faq for more details and an implementation for one rotation order)

Getting this operation to be numerically robust and glitchfree is another issue though.
However, I simply would advise you to keep to either matrices or quaternions.

Finally, consider if you actually want to do what you are doing. If you walk up a slope, do you actually change your up vector ? No you don't, but your ankles "bend" to keep you pointing directly upwards.

So unless you have a sophisticated bone system in place, I'd advise to keep your objects aligned to the y-axis even on sloped terrain, and have them slightly sink into the terrain to hide that they actually don't have their feet aligned to it. This looks more realistic than having your objects "stick" to the terrain's slope. (Cars and other automotives (and most "manmade" objects) are an exception to this rule though !)

Hope this helps =)
Feel free to ask if you run into any problems,
Cheers,
- Wernaeh

### #5mysticman

Member

• Members
• 95 posts

Posted 31 October 2005 - 10:50 PM

I thank you for your help!!!
Forgive me, but mathematics is already a hell, then the English....! :blush:
I thought that the solution was easier, but quake2 doesn't work with the quaternions.

Situation :

1) I am working on the engine of quake2.
2) I have The model with his position and his angles (PITCH, YAW, ROLL)
3) I have the normal one of the plan on which the model is.

For quake2, the angle PITCH is our head that says yes. :p
While the angle YAW is the to turn to the left or to the right. Finally the angle ROLL is that to lean to the left or to the right.

The position stays fixed that that is.
I have only to change the angle PITCH and the angle ROLL. While the angle YAW stays what is.

I know that it is ridiculous to position a biped in that way, but for a quadruped the thing is correct (or a car as you say you).

### #6rockwall

New Member

• Members
• 10 posts

Posted 20 November 2005 - 03:05 AM

just a good thing to know, u use the code
if (pitch < 0)
pitch += 360;
to keep the angle from being negative. to keep the angle between 0 and 360,
use this
pitch = pitch % 360;

### #7Goz

Senior Member

• Members
• 575 posts

Posted 22 November 2005 - 04:17 PM

rockwall said:

just a good thing to know, u use the code
if (pitch < 0)
pitch += 360;
to keep the angle from being negative. to keep the angle between 0 and 360,
use this
pitch = pitch % 360;

You sure? Modulo is a hellishly slow operation. Besides "pitch" is a float so you'd need to fmodf ...

### #8.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 23 November 2005 - 12:51 AM

Not more slower than a sqrt(), and it's probably peanuts compared to the rest of the game. But as atan2 always returns it's value in the range (-pi, pi], it will never be larger than 180 so the sole check for being negative works fine.

And note that a modulo won't keep it from being negative on most platforms
-
Currently working on: the 3D engine for Tomb Raider.

### #9mysticman

Member

• Members
• 95 posts

Posted 23 November 2005 - 02:37 PM

mysticman said:

From the moment that I express badly me in English, we see if I succeed in making to understand you with an image...:lol:

sorry for image:mellow:

### #10mysticman

Member

• Members
• 95 posts

Posted 23 November 2005 - 02:44 PM

using objects as this, the function above it works, but these objects don't have a head and a tail.... :lol:

### #11mysticman

Member

• Members
• 95 posts

Posted 03 December 2005 - 09:04 AM

Ok! I have resolved with one idea of mine without mathematics and algebra!
The method cross balance is 10 times faster than any operation with vectors and matrixes.
This method can also position models in "dead" animation....

### #12Nils Pipenbrinck

Senior Member

• Members
• 597 posts

Posted 03 December 2005 - 11:22 AM

Looks good.

I've written such a code a couple of days myself. I place objects (rotated around local y) in a world where I trace the exact position (so they rest on ground). Along with the intersection point I get the plane normal.

The code was pretty easy and somewhat looked like this:

sMatrix GetMatrix (const sVector a_normal, const float a_YRotation)

{

if (a_normal.y <=0)

{

printf ("sorry, I can't put models on walls and ceilings\n");

return;

}

// Assume a forward vector

sVector forward = sVector (0,0,1);

// Build Right-Vector that's perpendicular to normal and forward:

sVector right = a_normal % forward; // crossproduct.

// correct assumed  forward vector (must be perpendicular to right and normal)

forward = right % a_normal;

// combine the 3 vectors into a matrix (they are all perpendicular, so they place the

// object into the "normal pointing"-space:

sMatrix NormalMat;

NormalMat.SetRow (0, right);

NormalMat.SetRow (1, a_normal);

NormalMat.SetRow (2, forward);

// build rotation:

sMatrix RotMat;

RotMat.MakeYRotation(a_YRotation);

// concat matrices and we're done:

return RotMat * NormalMat;

}

I've typed this out of my head. Maybe it's nessesary to change the order of the crossproducts (easy to do, just pass a normal of <0,1,0>, trace into the code and flip order of crossproduct until we get a identiy matrix).

### #13mysticman

Member

• Members
• 95 posts

Posted 04 December 2005 - 03:24 PM

Here's a nice article on the subject: http://collective.va...691576-40315100

### #14mysticman

Member

• Members
• 95 posts

Posted 04 December 2005 - 10:21 PM

ok, I have adapted the algorithm of Masahiro Sakuta for quakex

http://typhontaur.fo...typhontaur#1782

:whistle:

### #15mysticman

Member

• Members
• 95 posts

Posted 04 December 2005 - 11:49 PM

hmhmmmmm....I have noticed that the algorithm fails when the plan and tilted a lot, while my cross balance is precise

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users