View Full Version : Help Planes & Angles
mysticman
10-30-2005, 09:37 AM
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:
Wernaeh
10-30-2005, 04: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
mysticman
10-31-2005, 02: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:
http://typhontaur.soldier.ru/download/planeangle.jpg
Wernaeh
10-31-2005, 06:47 AM
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
mysticman
10-31-2005, 03: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).
:sad:
rockwall
11-19-2005, 08:05 PM
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;
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 ...
.oisyn
11-22-2005, 05:51 PM
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
mysticman
11-23-2005, 07:37 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:
http://img375.imageshack.us/img375/9999/planeangle2of.jpg
sorry for image:mellow:
mysticman
11-23-2005, 07:44 AM
using objects as this, the function above it works, but these objects don't have a head and a tail.... :lol:
http://img290.imageshack.us/img290/3209/mine3tk.jpg
mysticman
12-03-2005, 02: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....
http://www.webalice.it/mysticman1/download/crossbalance.jpg
http://www.webalice.it/mysticman1/download/chekgrounplane1.jpg
http://img523.imageshack.us/img523/6620/crossbalance21fa.jpg
http://img523.imageshack.us/img523/9377/crossbalance56fd.jpg
http://img357.imageshack.us/img357/3452/crossbalance61hn.jpg
Nils Pipenbrinck
12-03-2005, 04: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).
mysticman
12-04-2005, 08:24 AM
Here's a nice article on the subject: http://collective.valve-erc.com/ind...691576-40315100
mysticman
12-04-2005, 03:21 PM
ok, I have adapted the algorithm of Masahiro Sakuta for quakex
http://typhontaur.forumup.it/viewto...typhontaur#1782
:whistle:
mysticman
12-04-2005, 04:49 PM
hmhmmmmm....I have noticed that the algorithm fails when the plan and tilted a lot, while my cross balance is precise
vBulletin, Copyright ©2000-2009, Jelsoft Enterprises Ltd.