and how to actually use them.

incomplete, under construction


In most cases in computer graphics when you use quaternion, or axis and angle, or 3x3 matrix, you actually want to deal with 3D rotations. In a good design, interface (rotation) should be abstracted from internal representation (quaternion or 3x3 matrix).
Let's think what operations that are defined on rotations : and so on and so forth.


It is reasonable to use operator*(Rotation, Rotation) for that. (Why not '+'? Because that'll screw up your algebra a lot. You have + already defined on vectors.)
So, (B*A) defines rotation by A followed by rotation by B (or, reference frame A as child of reference frame B. More on why this order is preferred below).
There you can see that it's like same old multiplication of matrices or quaternions.
So you can ask "what's the point in defining same thing again". What is very important to understand is that multiplication of matrices or quaternions do more than concatenation of rotations. For example, it can be used for scaling, or shearing.
Computational inprecision, over time, leads to de-orthonormalization of matrix, or to non-unit-length quaternion, which not only rotates but also distorts or scales the object.
You can add normalization of quaternions into this operator*(Rotation, Rotation), to ensure stability. Or you can add debugmode assertion of 1-epsilon>= |Q| <=1+epsilon, to simplify debugging of computational instability problems.


There things get much more interesting.
You dont need to really compute inverse of quaternion or 3x3 matrix to inverse rotation!
You only need transpose of 3x3 matrix, or negation of real part of quaternion (it's actually -conjugate(Q). Remeber that -Q stores same rotation as Q, so -conjugate(Q) and conjugate(Q) define same rotation).
While with matrices and quaternions your code would need to use different functions, transpose and conjugate, Rotation class could neatly hide and abstract those details as Inverse.
Note that it really does hide implementation details from rest of code (unlike accessors like get_X and set_X for instance which hide nothing).

Euclidean transform (almost)

That is all nice but usually you want something more than rotations. You want rotation and translation.
That is euclidean transform, sans the reflections. I called it CoordSys in my math library.
How do we do that with our Rotation class? Easily, store rotation and vector for translation.
There we do have a slight problem. What is multiplication and what is inverse for our euclidean transform class?
The transform is defined as:


where T is translation vector and R is rotation.
Naturally, concatenation of transform T1 R1 followed by T2 R2 is

v'=T2+R2*(T1+R1*v) = T2 + R2*T1 + R2*R1*v

For composite rotation we have

T = T2+R2*T1
R = R2*R1

That is, we can write our multiplication operator as something like
CoordSys operator*(const CoordSys &c1, const CoordSys &c2)
    CoordSys result;
#ifndef dont_normalize
    return result;


The transform, again, is


using some simple algebra on it to solve for v:

inverse(R)*(v' - T) = inverse(R)*R*v = v
v = -inverse(R)*T +inverse(R)*(v')

and in code it is similarly trivial:
CoordSys Inverse(const CoordSys &c1)
    CoordSys result;
    result.position= -(result.orientation*c1.position);
    return result;
Now, you can use CoordSys in place of 4x4 matrix for your transformations, using quaternion for the rotation. It takes up over 2x less space than 4x4 matrix, it does not suffer from as many numerical problems (it can not store unwanted transformations such as shear), and quaternion rotations are easier to interpolate than matrices.

incomplete, under construction

Todo: clean up my implementation and publish (under BSD license).


MathWorld: Quaternion.
EuclideanSpace.com: Maths - Combined Rotation and Translation (great site, BTW.)
http://gandalf-library.sourceforge.net/ some library that includes Euclidean transformations as well.
Geometric Transformations

(C) 2004..2014 Dmytry Lavrov.
Want to say something or ask some question? Contact:

[an error occurred while processing this directive]