Making a .MIS Exporter, need some help with Math
by Cinder Games · in Torque Game Engine · 04/04/2006 (4:38 pm) · 8 replies
Hi everyone, I'm working on making a .MIS editor for Lightwave 8.5. I'm having trouble figuring out how to convert Lightwaves Native Rotation to the format that Torque Uses.
Lightwave uses Euler Angles(Heading, Pitch, Bank), and Torque Uses Quanternions.
I need help figuring out the formula to convert from one to the other.
I'm writing this in a language called LScript, It's a c like sytanx and almost just like torque script.
This is the code i have so far i pieced together from a sample Javascript code found here:
www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/in...
I'm assuming Torque Uses X Y Z W, where W is the rotational amount. Using that, i get what seems to be a quanternion, but it doesn't seem to match what Torque Uses.
So what's the point of this Post? Well i'm pretty much asking for someone to show me in basic code how to convert from a Euler Angle to a torque ready Quaternion. Lscript support most basic math functions.
Lightwave uses Euler Angles(Heading, Pitch, Bank), and Torque Uses Quanternions.
I need help figuring out the formula to convert from one to the other.
I'm writing this in a language called LScript, It's a c like sytanx and almost just like torque script.
pos= obj.getPosition(0); rot = obj.getRotation(0); scl = obj.getScaling(0); MPI = 3.14159265358979323846; //Conversion into Radians heading=((rot.x * MPI) / (180)); attitude=((rot.y * MPI) / (180)); bank=((rot.z * MPI) / (180)); // Convesion to Quaterions c1 = cos(heading); s1 = sin(heading); c2 = cos(attitude); s2 = sin(attitude); c3 = cos(bank); s3 = sin(bank); w = sqrt(1.0 + c1 * c2 + c1*c3 - s1 * s2 * s3 + c2*c3) / 2.0; w4 = (4.0 * w); x = (c2 * s3 + c1 * s3 + s1 * s2 * c3) / w4 ; y = (s1 * c2 + s1 * c3 + c1 * s2 * s3) / w4 ; z = (-s1 * s3 + c1 * s2 * c3 +s2) / w4 ;
This is the code i have so far i pieced together from a sample Javascript code found here:
www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/in...
I'm assuming Torque Uses X Y Z W, where W is the rotational amount. Using that, i get what seems to be a quanternion, but it doesn't seem to match what Torque Uses.
So what's the point of this Post? Well i'm pretty much asking for someone to show me in basic code how to convert from a Euler Angle to a torque ready Quaternion. Lscript support most basic math functions.
#2
04/04/2006 (5:35 pm)
Ah, thanks. I'll try using you code and see if it'll work better. I'll post some results.
#3
I think i got it going. Perhaps a little more understanding of how these things work would help. correct if i'm wrong, but the first 3 digits represent a rotational amount -1 to 1. and the 4th number is applied to the other 3 numbers.
1 0 0 90 will mean a rotation of 90 degress to X
this one looks trickier, i rotated 90 on Heading, and 90 on Pitch
0.57735 0.57735 -0.57735 120.061
that one is harder to understand I only rotate 2 axis, so why does it generate a 3rd number?
here's my fuction using your code now.
04/04/2006 (6:15 pm)
One note, you use 3.14 when figuring you angle, that results in a little less then perfection. like i'd get 90.0456 or something like that. not much, but not accurate.I think i got it going. Perhaps a little more understanding of how these things work would help. correct if i'm wrong, but the first 3 digits represent a rotational amount -1 to 1. and the 4th number is applied to the other 3 numbers.
1 0 0 90 will mean a rotation of 90 degress to X
this one looks trickier, i rotated 90 on Heading, and 90 on Pitch
0.57735 0.57735 -0.57735 120.061
that one is harder to understand I only rotate 2 axis, so why does it generate a 3rd number?
here's my fuction using your code now.
pos= obj.getPosition(0);
rot = obj.getRotation(0);
scl = obj.getScaling(0);
// Convesion to Quaterions
MPI = 3.14159265358979323846;
//Heading
radX=((rot.x * MPI) / (180));
//Pitch
radY=((rot.y * MPI) / (180));
//Bank
radZ=((rot.z * MPI) / (180));
c1 = cos(radY/2);
s1 = sin(radY/2);
c2 = cos(radZ/2);
s2 = sin(radZ/2);
c3= cos(radX/2);
s3 = sin(radX/2);
c1c2 = c1*c2;
s1s2 = s1*s2;
w =c1c2*c3 - s1s2*s3;
x =c1c2*s3 + s1s2*c3;
y =s1*c2*c3 + c1*s2*s3;
z =c1*s2*c3 - s1*c2*s3;
angle = 2 * acos((c1*c2*c3) - (s1*s2*s3));
angle = (angle*180)/3.14;
norm = x*x+y*y+z*z;
if (norm < 0.001){
x=1;
y=z=0;
}
else {
norm = sqrt(norm);
x = x / norm;
y = y / norm;
z = z / norm;
}
result = (string(x) + " " + string(z) + " " + string(y) + " " + string(angle));
#4
04/04/2006 (6:26 pm)
I know can verify working results, how to also keep the angle value from being turned into a degree. Thanks for the assit.
#5
torque's "quaternion" should be written as "Vx Vy Vz Theta", and has two parts.
first a unit vector: Vx Vy Vz,
and then the amount to rotate around that vector: Theta.
theta is in radians, i believe.
the vector must be normalized to unit length.
04/04/2006 (6:40 pm)
Looks like you're on top of this stuff, but FTR,torque's "quaternion" should be written as "Vx Vy Vz Theta", and has two parts.
first a unit vector: Vx Vy Vz,
and then the amount to rotate around that vector: Theta.
theta is in radians, i believe.
the vector must be normalized to unit length.
#6
04/04/2006 (8:47 pm)
Uh oh, i got a problem. When objects are rotated in torque, their position changes! So when they are loaded with a rotation, the angle is correct, but their positions are not. after manually rotating items, i noticed the position changes.
#7
04/04/2006 (9:57 pm)
That doesn't seem to really matter much it seems. Well i believe i've hit a landmark. Everythint seems to export position and rotation wise correctly. Thaks for helping.
#8
04/07/2006 (7:59 pm)
Turns out i am having issues with rotation on all three axis's. everything is perfect if i only pick two of the axis's and export, but adding it a third causes it to rotate in directions it's not supposed to. Perhaps Juan can lend me a hand?
Torque Owner Mayor McCheese
global proc string getROT(string $item)
{
float $data[] = 'xform -q -ws -ro';
float $radX = ($data[0]*3.14)/180;
float $radY = ($data[1]*3.14)/180;
float $radZ = ($data[2]*3.14)/180;
float $c1 = cos($radY/2);
float $s1 = sin($radY/2);
float $c2 = cos($radZ/2);
float $s2 = sin($radZ/2);
float $c3 = cos($radX/2);
float $s3 = sin($radX/2);
float $c1c2 = $c1*$c2;
float $s1s2 = $s1*$s2;
float $w =$c1c2*$c3 - $s1s2*$s3;
float $x =$c1c2*$s3 + $s1s2*$c3;
float $y =$s1*$c2*$c3 + $c1*$s2*$s3;
float $z =$c1*$s2*$c3 - $s1*$c2*$s3;
float $angle = 2 * acos(($c1*$c2*$c3) - ($s1*$s2*$s3));
$angle = ($angle*180)/3.14;
float $norm = $x*$x+$y*$y+$z*$z;
if ($norm < 0.001)
{
$x=1;
$y=$z=0;
} else {
$norm = sqrt($norm);
$x = $x / $norm;
$y = $y / $norm;
$z = $z / $norm;
}
string $result = ($x + " " + $z + " " + $y + " " + $angle);
//print $result;
//print "\n";
return $result;
}