Types:
geQuaternion;
typedef struct{
geFloat W;
geFloat X,Y,Z;
//geVec3d QuatV;
} geQuaternion;(this is ripped right from the Genesis 3D header file quatern.h)
The quatern module contains basic support for a quaternion object.
Quaternions are an extension of complex numbers that allows an expression for rotation that can be easily interpolated. geQuaternions are also more numericaly stable for repeated rotations than matrices.
A quaternion is a 4 element 'vector' [w,x,y,z] where:
q = w + xi + yj + zkQ can be expressed by w + xi + yj + zk or [w,x,y,z] or as in this implementation (s,v) where s=w, and v=[x,y,z].
i*i = -1
j*j = -1
k*k = -1
i*j = -j*i = k
j*k = -k*j = i
k*i = -i*k = j
q' (conjugate) = w - xi - yj - zk
||q|| (magnitude) = sqrt(q*q') = sqrt(w*w + x*x + y*y + z*z)
unit quaternion ||q|| == 1; this implies q' == qinverse
quaternions are associative (q1*q2)*q3 == q1*(q2*q3)
quaternions are not commutative q1*q2 != q2*q1
qinverse (inverse (1/q) ) = q'/(q*q')Quaternions can represent a rotation. The rotation is an angle t, around a unit vector u. q = (s,v); s = cos(t/2); v = u*sin(t/2).
Quaternions can apply the rotation to a point. Let the point be p [px,py,pz] and let P be a quaternion(0,p). Protated = q*P*qinverse (Protated = q*P*q' if q is a unit quaternion)
Concatenation of rotations is similar to matrix concatenation. Given two rotations q1 and q2, to rotate by q1, then q2: let qc = (q2*q1), then the combined rotation is given by qc*P*qcinverse (= qc*P*qc' if q is a unit quaternion)Multiplication:
q1 = w1 + x1i + y1j + z1kAlso,
q2 = w2 + x2i + y2j + z2k
q1*q2 = q3 = (w1*w2 - x1*x2 - y1*y2 - z1*z2) {w3}
(w1*x2 + x1*w2 + y1*z2 - z1*y2)i {x3}
(w1*y2 - x1*z2 + y1*w2 + z1*x2)j {y3}
(w1*z2 + x1*y2 + y1*x2 + z1*w2)k {z3}q1 = (s1,v1) = [s1,(x1,y1,z1)]Interpolation - it is possible (and sometimes reasonable) to interpolate between two quaternions by interpolating each component. This does not quarantee a resulting unit quaternion, and will result in an animation with non-linear rotational velocity.
q2 = (s2,v2) = [s2,(x2,y2,z2)]
q1*q2 = q3 = (s1*s2 - dot_product(v1,v2), {s3}
(s1*v2 + s2*v1 + cross_product(v1,v2)) {v3}Spherical interpolation: (slerp) treat the quaternions as vectors find the angle between them (w = arccos(q1 dot q2) ). Given 0<=t<=1, q(t) = q1*(sin((1-t)*w)/sin(w) + q2 * sin(t*w)/sin(w). Since q == -q, care must be taken to rotate the proper way.
This implementation uses the notation quaternion q = (quatS,quatV) where quatS is a scalar, and quatV is a 3 element vector.
Constants:
QUATERNION_PI;
#define QUATERNION_PI (GE_PI)
Functions:
void GENESISCC geQuaternion_Add(const geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *QSum);
This function adds Q1 to Q2 returning the result in QSum.Returns: nothing.
Notes:
from QUATERN.H: QSum = Q1 + Q2 (result is not generally a unit quaternion!)
geBoolean GENESISCC geQuaternion_Compare(geQuaternion
*Q1, geQuaternion *Q2, geFloat Tolerance);
This function checks whether Q1 and Q2 differ by no more than Tolerance. The check is done element by element, if anyone element differs by more than tolerance then GE_FALSE is returned.Returns: GE_TRUE if Q1 and Q2 differ by no more than Tolerance, otherwise GE_FALSE.
Notes:
from QUATERN.H: return GE_TRUE if quaternions differ elementwise by less than Tolerance.
GENESISAPI void GENESISCC geQuaternion_Copy(const
geQuaternion *QSrc, geQuaternion *QDst);
This function copies the contents of QSrc in QDst. QDst must not be NULL.Returns: nothing.
Notes:
from QUATERN.H: copies quaternion QSrc into QDst
void GENESISCC geQuaternion_Exp(const geQuaternion
*Q, geQuaternion *ExpQ);
This function calculates eQ. Q.W must equal 0.0.Returns: nothing.
Notes:
from QUATERN.H: exp(Q) for pure quaternion only! (zero scalar part (W))
void GENESISCC geQuaternion_FromMatrix(const
geXForm3d *RotationMatrix, geQuaternion *QDest);
This function sets up QDest from the transformat RotationMatrix. The resulting quaternion will only have the rotational transform part of the transformation matrix.Returns: nothing.
Notes:
from QUATERN.H: takes upper 3 by 3 portion of matrix (rotation sub matrix) and generates a quaternion.
void GENESISCC geQuaternion_Get(const geQuaternion
*Q, geFloat *W, geFloat *X, geFloat *Y, geFloat *Z);
This function returns the components of Q in (W,X,Y,Z).Returns: nothing.
Notes:
from QUATERN.H: get quaternion components into W,X,Y,Z
geBoolean GENESISCC geQuaternion_GetAxisAngle(const
geQuaternion *Q, geVec3d *Axis, geFloat *Theta);
This function returns the rotational transformation represented by Q as an angle Theta and axis of rotation Axis.Returns: GE_TRUE on success, GE_FALSE otherwise.
Notes:
from QUATERN.H: gets an axis and angle of rotation around the axis from a quaternion. returns GE_TRUE if there is an axis. returns GE_FALSE if there is no axis (and Axis is set to 0,0,0, and Theta is 0)
void GENESISCC geQuaternion_GetVec3d(const
geQuaternion *Q, geFloat *W, geVec3d *V);
This function returns the components of Q as a scalar W and a vector V.Returns: nothing.
Notes:
from QUATERN.H: get quaternion components into W and V
void GENESISCC geQuaternion_Inverse(const
geQuaternion *Q, geQuaternion *QInv);
This function calculates the inverse of Q and returns it as QInv.Returns: nothing.
Notes:
from QUATERN.H: sets QInv to the inverse of Q.
geBoolean GENESISCC geQuaternion_IsUnit(const
geQuaternion *Q);
This function checks to see the Q is a unit quaternion.Returns: GE_TRUE of Q is a unit quaternion, GE_FALSE otherwise.
Notes:
from QUATERN.H: returns GE_TRUE if q is a unit quaternion. GE_FALSE otherwise.
geBoolean GENESISCC geQuaternion_IsValid(const
geQuaternion *Q);
This function checks that all the elements of Q are real numbers.Returns: GE_TRUE of Q is valid, GE_FALSE otherwise.
Notes:
from QUATERN.H: return GE_TRUE if Q is non null and for has no NAN's in its components
void GENESISCC geQuaternion_Ln(const geQuaternion
*Q, geQuaternion *LnQ);
This function calculates the natural logarithm of Q returning the result in LnQ. Q must be a unit quaternion.Returns: nothing.
Notes:
from QUATERN.H: ln(Q) for unit quaternion only!
geFloat GENESISCC geQuaternion_Magnitude(const
geQuaternion *Q);
This function calculates the Magnitude of Q and returns it.void GENESISCC geQuaternion_Multiply(const geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *QProduct);Returns: The magnitude of Q.
Notes:
from QUATERN.H: returns Magnitude of Q.Questions:
What does the Magnitude of a Quaternion represent? What is it useful for?
This function multiplies Q1 by Q2 returning the result in QProduct.Returns: nothing.
Notes:
from QUATERN.H: multiplies q1 * q2, and places the result in q. No failure. Renormalization not automatic
GENESISAPI geFloat GENESISCC geQuaternion_Normalize(geQuaternion
*Q);
This function normalizes Q and returns its original magnitude. Q is modified by the resulting normalization.Returns: the inital magnitude of Q.
Notes:
from QUATERN.H: normalizes q to be a unit quaternion. returns original magnitude of q
void GENESISCC geQuaternion_Rotate(const
geQuaternion *Q, const geVec3d *V, geVec3d *VRotated);
This function rotates a vector V by the quaternion Q returning the resulting rotated vector in VRotated.Returns: nothing.
Notes:
from QUATERN.H: Rotates V by the quaternion Q, places the result in VRotated.
void GENESISCC geQuaternion_Scale(const
geQuaternion *Q, geFloat Scale, geQuaternion *QScaled);
This function scales the quaternion Q by Scale returning the result in QScaled.Returns: nothing.
Notes:
from QUATERN.H: Q = Q * Scale (result is not generally a unit quaternion!)
void GENESISCC geQuaternion_Set(geQuaternion
*Q, geFloat W, geFloat X, geFloat Y, geFloat Z);
This function sets the components of Q to (W,X,Y,Z).Returns: nothing.
Notes:
from QUATERN.H: set quaternion components. Doesn't normalize.
GENESISAPI void GENESISCC geQuaternion_SetFromAxisAngle(geQuaternion
*Q, const geVec3d *Axis, geFloat Theta);
This function sets up the quaternion Q to a rotation about the axis Axis by the angle Theta.Returns: nothing.
Notes:
from QUATERN.H: set a quaternion from an axis and a rotation around the axis
void GENESISCC geQuaternion_SetNoRotation(geQuaternion
*Q);
This function sets Q to be a quaternion with NO rotation.Returns: nothing.
Notes:
from QUATERN.H: sets Q to be a quaternion with no rotation (like an identity matrix)
void GENESISCC geQuaternion_SetVec3d(geQuaternion
*Q, geFloat W, const geVec3d *V);
This function sets the components of Q using the scalar W and the vector V.Returns: nothing.
Notes:
from QUATERN.H: set quaternion components. Doesn't normalize
void GENESISCC geQuaternion_Slerp(const
geQuaternion *Q0, const geQuaternion *Q1, geFloat T, geQuaternion *QT);
This function uses spherical interpolation to interpolate betwen Q0 and Q1 at T (0 <= T <= 1) returning the result in QT. At T=0 QT=Q0, at T=1 QT=Q1. QT will always be returned with a positive W (this implies that the route taken is always the shortest through the positive W domain).Returns: nothing.
Notes:
from QUATERN.H: Spherical interpolation between q0 and q1. 0<=t<=1 resulting quaternion is 'between' q0 and q1 with t==0 being all q0, and t==1 being all q1. returns a quaternion with a positive W - always takes shortest route through the positive W domain.
void GENESISCC geQuaternion_SlerpNotShortest(const
geQuaternion *Q0, const geQuaternion *Q1, geFloat T, geQuaternion
*QT);
This function uses spherical interpolation to interpolate betwen Q0 and Q1 at T (0 <= T <= 1) returning the result in QT. I'm not sure exactly how this differs from the standard Slerp above.Returns: nothing.
Notes:
from QUATERN.H: spherical interpolation between q0 and q1. 0<=t<=1 resulting quaternion is 'between' q0 and q1 with t==0 being all q0, and t==1 being all q1.
void GENESISCC geQuaternion_Subtract(const
geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *QDifference);
This function subtracts Q2 from Q1 returning the result in QDifference.Returns: nothing.
Notes:
from QUATERN.H: QDifference = Q1 - Q2 (result is not generally a unit quaternion!)
GENESISAPI void GENESISCC geQuaternion_ToMatrix(const
geQuaternion *Q, geXForm3d *RotationMatrixDest);
This function calculates the transformation matrix RotationMatrixDest resulting from the quaternion Q.Returns: nothing.
Notes:
from QUATERN.H: takes a unit quaternion and makes RotationMatrixDest an equivelant rotation xform. (any translation in RotationMatrixDest will be lost)