QUAT

advertisement
*************************************************************************
****
* Laurent Schmalen aka BlackAxe / Kolor proudly presents
*
* A freeware Quaternion class for use in all non-commercial programs
*
*************************************************************************
****
Hi guys...
You're playing with .3ds keyframing? You are sick of Euler Angles to
represent
rotations? Then this is the right thing for you. A Quaternion Class :=)
1.) What the heck are Quaternions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Quaternions are hyper-complex numbers. You surely know what a complex
number
is. If not, let's refresh the theory of them a bit. Complex numbers were
invented to solve quadratic equations. They are formed of a real part and
an
imaginary part and are written like this: a + bi
A is the real part, B is the imaginary part, i is the imaginary number,
it has
been chosen so that i^2 = -1 or i = sqrt(-1) which is impossible in
normal
maths, but here it is :)
Hyper complex numbers are complex numbers with 3 imaginary units. They
were
invented by Sir William Hamilton. He has been trying for a long time to
extend
complex numbers to define a multiplication with sense on triples (3dimensional
vectors). The October 16th 1843 while he was driving to the Royal British
Academy, he got a brain-flash and realized that a multiplication on
triples
would be impossible but it would be possible on complex numbers with 3
imaginary units, so he took his knife and used it to write his theory in the
Broome
Bridge in Dublin, where it is still today :)
He called the number q = xi + yj + zk + w a "Quaternion". W is the RealPart
of q. Normally the imaginary party is used as a vector
->
q = (w, v ) = w + v i + v j + v k
x
y
z
2.) How to use this class
~~~~~~~~~~~~~~~~~~~~~~~~~
Now as you know the basics of Quaternions, let's start with how to use
them.
you define a Quaternion like a normal C++ class or var.
Quaternion q;
Or if you want it to be pre-initialised
Quaternion q(1, 2.0, 3.1, 6.66);
If you look in the .H file, you see that there are default arguments, you
only needs to specify the real part, if the imaginary parts are not
specified
then they are supposed to be 0.0
so these work too:
Quaternion q(1,2,3);
Quaternion q(1,2);
Quaternion q = 5.5;
imaginary
// this sets the real part to 5.5 and the
// parts to 0.0
You can print a Quaternion using the normal cout streams as seen in
Example.cpp
cout << q << endl;
// works fine ...
Now you can also multiplicate Quaternions. The way to multiplicate
Quaternions
is rather complex and i don't want to explain it in all details, check
the
source-code for it ...
you can just do
Quaternion a(1,2,3,4);
Quaternion b(4,3,2,1);
Quaternion result = a*b;
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!
! Note that quaternion multiplication is not commutative, so a*b gives
another
! result than b*a
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!
you can also do
a *= b;
this is the same than a = a*b; (of course :))
you can also use Quaternion multiplication to mul normal floats, but i
wonder
how would want that :)
Quaternion q(14);
Quaternion result = 2*q;
however :)
the operator ~ gives the conjugate of a quaternion
just call
Quaternion a;
~a;
// now a is conjugated :)
Quaternion b = ~a;
// b is the conjugate of a
the same way you use the operator - that is used to invert a quaternion
Quaternion b = -a;
-b;
and so on :)
you can normalize a Quaternion using the member function Normalize();
Quaternion q(1,2,3,4);
q.Normalize();
q is now an unit Quaternion
Normalize returns the Quaternion that it is actually called for, this can
be
handy when printing quat's
Quaternion q;
cout << q.Normalize() << endl;
prints you the normalized quaternion, and q is normalized from now
on!!!!!!
the same way, the quaternion can be exponented and logarithmed ...
Quaternion q(1,2,3),a;
q.exp();
a.log();
this comes in handy when doing Spline Quaternion interpolation.
3.) How to use Quaternions in practice
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ok, now you know stuff like multiplying quaternions etc, but how to use
them.
Well, let's start with rotations ...
You can convert the rotation you have in [Angle,Axis] representation
easily
into a Quaternion ...
Let's say you want to rotate and object around the Axis (0.5, 1.0, 0.25);
you simply do
Quaternion Rotation;
float Angle = 90.0;
Rotation.FromAxis(Angle*PI/180, 0.5, 1.0, 0.25);
note thata the angle must be in radians, so you need to convert first,
the
3 other parameters are the (x,y,z) of the axis.
Fine. Now you have a rotation Quaternion, but what to do with it ??
simply do
float RotationMatrix[3][3];
Rotation.ToMatrix(RotationMatrix);
now you can transform your vertices usingt this matrix ... easy huh? :)
4.) How to use this in .3ds ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
First off, i want to send big thanks to MRi/DoomsDay and Kombat/Immortals
for
helping me out with this subject.
In .3ds the rotation is described as an Angle,Axis representation. Note
that
the Y,Z are swapped in .3ds
you just do
for(int i=0; i < NrOfKeys; i++)
{
ReadAllStuffFromFile();
RotationKeys[i].FromAxis(Angle, Axis.x, Axis.z, Axis.y);
if (i > 0)
RotationKeys[i] = RotationKeys[i-1] * RotationKeys[i];
}
you must multiply the current quaternion with the previous one, as the
rotation
is relative to the rotation in the previous Key, expect for Key 0 (frame
0)
where the rotation is correct ...
5.) Interpolating Quaternions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interpolating between Euler Angles is very ugly, you might get the
"Glimbal
Lock", an error that occurs very often and gives bad results. That's a
reason
to use Quaternions which give good results when interpolated.
Let's come back to our .3ds example
Let's say you have a Quaternion Rot1 at Frame 10, and a Quaternion Rot2
at
frame 30.
now you want to get the Rotation Quaternion at frame 17. How to do this?
very easy :)
float t = (17-10) / (30-10);
or if you like this more
float t = (ActualFrame - KeyFrame1) / (KeyFrame2 - KeyFrame1);
// t must be between 0 and 1 therefor this little hack
// now you do
Quaternion ThisFrameRot;
ThisFrameRot.Slerp(Rot1, Rot2, t);
and you have your rotation at frame 17. You just need to do a ToMatrix
now and
you can transform your vertices ... Kinda easy, hu :))
6.) The final bit
~~~~~~~~~~~~~~~~~
Greet/Credit me and my group (KoLoR that is) if you use this in your
products.
I guess you won't be that arrogant/egoistic to use this without greeting,
a
little greet in the infofile won't hurt, guys! Keep friendship alive!
This thing should be compilable with all kind of Compiles, as it doesn't
use
any compiler specific functions. I had no problems to get it running
under
Watcom C++ 10.x and 11.0 and Borland C++ 3.1. And i haven't had the
possibility to test others.
Even though i have tested this class quite alot, there might still be
some
errors. If you find errors and you have suggestions/problems/critics,
please
don't be shy, and contact me.
E-Mail:
IRC
:
Laurent.Schmalen@Ci.Educ.Lu
#coders on IRCNET (irc.stealth.net)
#luxusbuerg on UNDERNET (us.undernet.org, de.undernet.org)
see juu later
blackaxe/kolor aka Laurent Schmalen
Download