A better way to calc the right and up vectors?
by John Vanderbeck · in Torque Game Engine · 04/28/2004 (6:46 am) · 15 replies
I can't find a way to get anything but the forward vector from the engine. I'm not the greatest when it comes to 3d math so i've been futzing around on paper trying to determine how to get the other two vectors.
In my situation I can't count on x y 1 always being the UP vector which complicates things. At least it does in my mind, but it may not in reality.
After a lot of paper i've come up with a way I think to calc them, but it seems stupid and i'm wondering if my way is bad and there is a better way to do it (wouldn't suprise me).
What i'm doing is this:
1) Take the forward vector given from the engine, and create a new vector with the same Z component, but swapped X and Y components. E.G. a forward vector of 0.5 0.2 0 would create a new vector of 0.2 0.5 0
2) Take these two vectors and do a cross product ensuring that the first vector in the calculation is always the vector with the largest X component (if you do the one with the smallest X component first the resulting vector will be inverted). Normalize the resulting vector. The resulting vector will be the UP vector.
3) Now that we have the FORWARD and UP vectors, calculating our RIGHT vector is trivial. A simple cross product bewteen FORWARD and UP will give the RIGHT vector.
In my situation I can't count on x y 1 always being the UP vector which complicates things. At least it does in my mind, but it may not in reality.
After a lot of paper i've come up with a way I think to calc them, but it seems stupid and i'm wondering if my way is bad and there is a better way to do it (wouldn't suprise me).
What i'm doing is this:
1) Take the forward vector given from the engine, and create a new vector with the same Z component, but swapped X and Y components. E.G. a forward vector of 0.5 0.2 0 would create a new vector of 0.2 0.5 0
2) Take these two vectors and do a cross product ensuring that the first vector in the calculation is always the vector with the largest X component (if you do the one with the smallest X component first the resulting vector will be inverted). Normalize the resulting vector. The resulting vector will be the UP vector.
3) Now that we have the FORWARD and UP vectors, calculating our RIGHT vector is trivial. A simple cross product bewteen FORWARD and UP will give the RIGHT vector.
#2
I'm starting from having ONLY the front vector.
04/28/2004 (7:02 am)
Lol Breet re-read what I did.I'm starting from having ONLY the front vector.
#3
This gives you the right vector.
Now do a cross product of your forward vector and your new right vector.
This gives you the corrected up vector.
04/28/2004 (7:11 am)
Take your forward vector and do a cross product with the world up vector: (0, 0, 1).This gives you the right vector.
Now do a cross product of your forward vector and your new right vector.
This gives you the corrected up vector.
#4
That works even though 0,0,1 isn't neccesarily UP for me? I mean, that doesn't make sense. What if the camera is looking straight at the ground? Its "UP" would be the world's FORWARD.
04/28/2004 (7:17 am)
@MarkusThat works even though 0,0,1 isn't neccesarily UP for me? I mean, that doesn't make sense. What if the camera is looking straight at the ground? Its "UP" would be the world's FORWARD.
#5
First, find the major axis of your forward vector, and cross it with your forward vector. This will give you the RIGHT vector, from which you can easily calculate your UP vector.
To find tha major axis, get the absolute value of the x,y,z components, and find the largest one. If X is the largest one then your major axis is (1,0,0)... etc
You will need to check to make sure that the major axis and the forward vector are not exactly the same, otherwise you will get a result of 0,0,0. In that case, you will need to manually grab the RIGHT and UP vectors, which shouldnt be hard since you will be axis aligned; there are only 3 possibilities for you to work out ;)
Peace
04/28/2004 (7:24 am)
Hi John,First, find the major axis of your forward vector, and cross it with your forward vector. This will give you the RIGHT vector, from which you can easily calculate your UP vector.
To find tha major axis, get the absolute value of the x,y,z components, and find the largest one. If X is the largest one then your major axis is (1,0,0)... etc
You will need to check to make sure that the major axis and the forward vector are not exactly the same, otherwise you will get a result of 0,0,0. In that case, you will need to manually grab the RIGHT and UP vectors, which shouldnt be hard since you will be axis aligned; there are only 3 possibilities for you to work out ;)
Peace
#6
Thanks!
04/28/2004 (7:38 am)
Interesting. Its almost the same thing as i'm doing, but not quite. Heh. Mine will probably break in some cases, so its nice to know the "right" way to do it. I'll rewrite the code tonight after work.Thanks!
#7
let me say that I'm not a 3D math guru, but can you tell me why, where, when, you can get only the forward vector?
Do you have access to the transform matrix of the object?
If so, and if I remember well, the first column is the right vector, the second is the forward vector and the third is the up vector
Hope this help
04/28/2004 (7:51 am)
Hi John,let me say that I'm not a 3D math guru, but can you tell me why, where, when, you can get only the forward vector?
Do you have access to the transform matrix of the object?
If so, and if I remember well, the first column is the right vector, the second is the forward vector and the third is the up vector
Hope this help
#8
This is why you see code like this when interpreting a move:
04/28/2004 (8:23 am)
Davide is right, you actually have them in the transform - column 0 is right vector, column 1 is forward vector, column 2 up vector, and column 3 is the position.This is why you see code like this when interpreting a move:
Point3F vec;
mObjToWorld.getColumn(0,&vec);
mVelocity += vec * move->x * mDataBlock->moveSpeed;
mObjToWorld.getColumn(1,&vec);
mVelocity += vec * move->y * mDataBlock->moveSpeed;
mObjToWorld.getColumn(2,&vec);
mVelocity += vec * move->z * mDataBlock->moveSpeed;
#9
First, I think extra helper console methods should be added to HEAD to get the right and up vectors as well.
Having said that, there must be some way to determine the actual vectors from the getTransform console method, but I'd need some time to figure out the calculations.
04/28/2004 (8:34 am)
After re-reading this, I get the feeling you're wanting to do this in script, and you're right, there's only a console method to get the forwardVector or the transform as a position, AngularAxis and angle of rotation.First, I think extra helper console methods should be added to HEAD to get the right and up vectors as well.
Having said that, there must be some way to determine the actual vectors from the getTransform console method, but I'd need some time to figure out the calculations.
#10
- Brett
04/28/2004 (8:55 am)
Hey John... I told you I sucked at math! I was close with the cross product thing, tho! :-)- Brett
#11
The short answer is that you need at least two vectors to find the orientation of a third orthogonal vector. You need to pull more or different information to get the answer to this problem like Cory says.
I agree with Cory that some console functions for getting the right and up vector should be added to HEAD. I'm sure that this issue same has come up before with other projects. It would be nice to have these functions available in the engine itself as well to help people learn the engine and 3D math. "mObjToWorld.getColumn(0,&vec);" is a little cryptic to say the least.
This post should have been in the Mathematics forum... ;)
04/28/2004 (12:40 pm)
This is interesting because, given just the forward vector you cannot determine the up or right vectors, there just isn't enough information to find it. Think of it this way, imagine that you have the forward vector in space then you "determine" the up and right vectors by one some means. Now look back to the original known variables (the forward vector). Given what you knew originally you can hold the forward vector in place and now spin the object's other axes around it. Because of this the answer set for the right or up vector is infinite.The short answer is that you need at least two vectors to find the orientation of a third orthogonal vector. You need to pull more or different information to get the answer to this problem like Cory says.
I agree with Cory that some console functions for getting the right and up vector should be added to HEAD. I'm sure that this issue same has come up before with other projects. It would be nice to have these functions available in the engine itself as well to help people learn the engine and 3D math. "mObjToWorld.getColumn(0,&vec);" is a little cryptic to say the least.
This post should have been in the Mathematics forum... ;)
#12
Peace
04/28/2004 (1:31 pm)
That is true, but only if you are using all 6 degrees of freedom. If you need to find UP and RIGHT for a vehicle in Torque, you will need to pull the matrix. For just about anything else, you don't really need to. The theory is the same as calculating a triangle for a decal based on only a position and plane normal. Might want to have a peek at the Torque decal code to see how they do it.Peace
#13
Here is a function that will echo it to the console (if there's any easier way to get multiple "words" out of a string, let me know, because I haven't been scripting too long).
04/28/2004 (1:47 pm)
Okay - there is a console method VectorOrthoBasis that will spit out the 3x3 matrix with the right/forward/up vectors. The input is the AngAxis/Angle received from getTransform.Here is a function that will echo it to the console (if there's any easier way to get multiple "words" out of a string, let me know, because I haven't been scripting too long).
// a simple function for rotations to vectors calculations
function echoVectors(%obj) {
%transform = %obj.getTransform();
echo("Transform: " @ %transform);
%pos = getWord(%transform, 0) SPC
getWord(%transform, 1) SPC
getWord(%transform, 2);
echo("Position: " @ %pos);
%aa = getWord(%transform, 3) SPC
getWord(%transform, 4) SPC
getWord(%transform, 5) SPC
getWord(%transform, 6);
echo("Angular Axis: " @ %aa);
%tmat = VectorOrthoBasis(%aa);
echo("Transform Matrix: " @ %tmat);
%rv = getWord(%tmat, 0) SPC
getWord(%tmat, 1) SPC
getWord(%tmat, 2);
echo("Right Vector: " @ %rv);
%fv = getWord(%tmat, 3) SPC
getWord(%tmat, 4) SPC
getWord(%tmat, 5);
echo("Forward Vector: " @ %fv);
%uv = getWord(%tmat, 6) SPC
getWord(%tmat, 7) SPC
getWord(%tmat, 8);
echo("Up Vector: " @ %uv);
}
#14
04/28/2004 (6:00 pm)
Wow all this while I was at work. Thanks for the comments! I never realized you could just grab it from the matrix. Sweet!
#15
Great script. It really helped me. There is a shorter way to write it though (these are just the .
I actually used it to modify projectiles using:
%transform = %obj.getSlotTransform(%slot);
Thanks.
11/29/2004 (10:19 am)
Cory,Great script. It really helped me. There is a shorter way to write it though (these are just the .
// a simple function for rotations to vectors calculations
function echoVectors(%obj) {
%transform = %obj.getTransform();
echo("Transform: " @ %transform);
%pos = getWords(%transform, 0, 2);
echo("Position: " @ %pos);
%aa = getWords(%transform, 3, 6);
echo("Angular Axis: " @ %aa);
%tmat = VectorOrthoBasis(%aa);
echo("Transform Matrix: " @ %tmat);
%rv = getWords(%tmat, 0, 2);
echo("Right Vector: " @ %rv);
%fv = getWords(%tmat, 3, 5);
echo("Forward Vector: " @ %fv);
%uv = getWords(%tmat, 6, 8);
echo("Up Vector: " @ %uv);
} I actually used it to modify projectiles using:
%transform = %obj.getSlotTransform(%slot);
Thanks.
Torque Owner Brett Fattori
You take the front and side vector, cross them and you get the up vector.
That's what I thought.
- Brett