0
101 Oct 30, 2005 at 16:37

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:

#### 14 Replies

0
101 Oct 30, 2005 at 23:55

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

0
101 Oct 31, 2005 at 09:04

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

0
101 Oct 31, 2005 at 13:47

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

0
101 Oct 31, 2005 at 22:50

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).

0
101 Nov 20, 2005 at 03:05

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;

0
101 Nov 22, 2005 at 16:17

@rockwall

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 …

0
101 Nov 23, 2005 at 00:51

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

0
101 Nov 23, 2005 at 14:37

@mysticman

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:

0
101 Nov 23, 2005 at 14:44

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

0
101 Dec 03, 2005 at 09:04

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….

0
101 Dec 03, 2005 at 11:22

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).

0
101 Dec 04, 2005 at 15:24

Here’s a nice article on the subject: http://collective.valve-erc.com/ind…691576-40315100

0
101 Dec 04, 2005 at 22:21

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

http://typhontaur.forumup.it/viewto…typhontaur#1782

:whistle:

0
101 Dec 04, 2005 at 23:49

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