geQuaternion

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 + zk
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')
Q 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].

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 + z1k
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}
Also,
q1 = (s1,v1) = [s1,(x1,y1,z1)]
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}
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.

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.

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?

void GENESISCC geQuaternion_Multiply(const geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *QProduct);
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)