Summary

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. geQuaternion_s are also more numerically stable for repeated rotations than matrices.

Overview

A quaternion is a 4 element 'vector' [w,x,y,z] where:

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 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.

Reference

void geQuaternion_Add(const geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *QSum)

Description: Adds two quaternions together.

Parameters:

Q1 Input Quaternion
Q2 Input Quaternion
QSum Q1 + Q2

Returns: void

Remarks: The result of this operation is not generally a unit quaternion.

geBoolean geQuaternion_Compare(const geQuaternion *Q1, const geQuaternion *Q2, geFloat Tolerance)

Description: Compares two quaternions.

Parameters:

Q1 Input quaternion
Q2 Input quaternion
Tolerance Tolerance to compare within

Returns: GE_TRUE if all the corresponding elements of the quaternions compare within the supplied Tolerance, GE_FALSE otherwise.

void geQuaternion_Copy(const geQuaternion *QSrc, geQuaternion *QDst)

Description: Copies a quaternion.

Parameters:

QSrc Quaternion to copy from
QDst Quaternion to copy to

Returns: void

void geQuaternion_Exp(const geQuaternion *Q, geQuaternion *QExp)

Description: Calculates exp(Q).

Parameters:

Q Input quaternion
QExp Result

Returns: void

Remarks: This operation only works on pure quaternions - those in which the scalar portion is zero.

void geQuaternion_FromMatrix(const geXForm3d *XForm, geQuaternion *QDest)

Description: Builds a quaternion from a rotation transform.

Parameters:

XForm Transform to convert
QDest Quaternion to conver to

Returns: void

Remarks: Ignores any translation in the transform.

void geQuaternion_Get(const geQuaternion *Q, geFloat *W, geFloat *X, geFloat *Y, geFloat *Z)

Description: Extracts the discrete elements of a quaternion.

Parameters:

Q Quaternion to extract elements of
W Variable to place W component in
X Variable to place X component in
Y Variable to place Y component in
Z Variable to place Z component in

Returns: void

geBoolean geQuaternion_GetAxisAngle(const geQuaternion *Q, geVec3d *Axis, geFloat *Theta)

Description: Calculates an axis and a rotation angle about that axis from a quaternion.

Parameters:

Q Quaternion to convert
Axis Vector to receive the axis result
Theta Resulting rotation angle in radians

Returns: GE_TRUE if there is an axis. GE_FALSE if there is no axis, in which case Axis is set to (0, 0, 0) and Theta is set to 0.

void geQuaternion_GetVec3d(const geQuaternion *Q, geFloat *W, geVec3d *Vector)

Description: Gets the quaternion components into a scalar float, and a vector.

Parameters:

Q Quaternion to extract from
W Receives W component of Q
Vector Receives X, Y and Z components of Q

Returns: void

void geQuaternion_Inverse(const geQuaternion *Q, geQuaternion *QInv)

Description: Calculates inverse of a quaternion.

Parameters:

Q Quaternion to invert
QInv Inverted result

Returns: void

geBoolean geQuaternion_IsUnit(const geQuaternion *Q)

Description: Determines if a quaternion is a unit quaternion

Parameters:

Q Quaternion to test

Returns: GE_TRUE if the quaternion is a unit quaternion, GE_FALSE otherwise.

geBoolean geQuaternion_IsValid(const geQuaternion *Q)

Description: Determines if the quaternion is valid. This is a debugging API, primarily. It was designed to test for quaternions that contained NAN values on Intel machines, since it is easy to let NAN values slip into calculations. Since NANs do not generate hardware exceptions, it can be exceedingly difficult to determine when data has gone bad.

Parameters:

Q Quaternion to test

Returns: void

void geQuaternion_Ln(const geQuaternion *Q, geQuaternion *LnQ)

Description: Calculates Ln(Q).

Parameters:

Q Input quaternion
LnQ Ln(Q)

Returns: void

Remarks: Only works on unit quaternions.

geFloat geQuaternion_Magnitude(const geQuaternion *Q)

Description: Calculates the magnitude of a quaternion

Parameters:

Q Quaternion

Returns: Magnitude of Q.

void geQuaternion_Multiple(const geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *QProduct)

Description:

Parameters:

Q1 Input Quaternion
Q2 Input Quaternion
QProduct Result of Q1 * Q2

Returns: void

Remarks: Result is not necessarily normalized.

geFloat geQuaternion_Normalize(geQuaternion *Q)

Description: Normalizes a quaternion to a unit quaternion.

Parameters:

Q Quaternion to normalize

Returns: Magnitude of Q before normalization.

void geQuaternion_Rotate(const geQuaternion *Q, const geVec3d *Vector, geVec3d *VRotated)

Description: Rotates a vector by a quaternion.

Parameters:

Q Quaternion to rotate by
Vector Vector to rotate
VRotated Resulting rotated vector

Returns: void

void geQuaternion_Scale(const geQuaternion *Q, geFloat Scale, geQuaternion *QScaled)

Description: Scales a quaternion.

Parameters:

Q Quaternion to scale
Scale Scale value
QScaled Result of Q * Scale

Returns: void

Remarks: Result is not generally a unit quaternion.

void geQuaternion_Set(const geQuaternion *Q, geFloat W, geFloat X, geFloat Y, geFloat Z)

Description: Builds a quaternion from discrete components.

Parameters:

Q Quaternion to build
W W component
X X component
Y Y component
Z Z component

Returns: void

Remarks: Does not normalize the resulting quaternion.

void geQuaternion_SetFromAxisAngle(geQuaternion *Q, const geVec3d *Axis, geFloat Theta)

Description: Builds a quaternion from an axis and a rotation about that axis.

Parameters:

Q Quaternion to build
Axis Axis vector
Theta Rotation angle about Axis, in radians

Returns: void

void geQuaternion_SetMaximalAssertionMode(geBoolean Enable)

Description: Enables or disables strict constraint testing on transforms at runtime.

Parameters:

Enable GE_TRUE to enable strict checking, GE_FALSE otherwise.

Returns: void

Remarks: In debug builds, the quaternion library performs a number of tests on quaternions on many operations. The sum of these tests imposes a very significant performance penalty on the basic operation of the whole engine, which tends to make debug builds untenable in the development environment. Consequently, we have made the running of the most expensive of these tests conditional to the enabling of maximal assertions in the quaternion library, and defaulted to not doing these tests. If you are experiencing trouble with your quaternions becoming non-unit, or are having other difficult to track down problems with your quaternions, you may want to enable these tests. This API is not present in the release builds of the engine.

void geQuaternion_SetNoRotation(geQuaternion *Q)

Description: Sets a quaternion to a quaternion which performs no rotation.

Parameters:

Q Quaternion to set

Returns: void

Remarks: This is the analog of setting up an identity transform.

void geQuaternion_SetVec3d(geQuaternion *Q, geFloat W, const geVec3d *Vector)

Description: Builds a quaternion from a W component, and a vector.

Parameters:

Q Quaternion to build
W W component of the quaternion
Vector X, Y and Z components of the quaternion

Returns: void

Remarks: This does not normalize the resulting quaternion.

void geQuaternion_Slerp(const geQuaternion *Q0, const geQuaternion *Q1, geFloat T, geQuaternion *QT)

Description: Calculates a spherical interpolation between two quaternions.

Parameters:

Q0 Start quaternion
Q1 End quaternion
T Percentage (value from 0 through 1) between Q0 and Q1 that we need to end up at.
QT Interpolated result

Returns: void

Remarks: Returns a quaternion with a positive W, always taking the shortest route through the positive W domain.

void geQuaternion_SlerpNotShortest(const geQuaternion *Q0, const geQuaternion *Q1, geFloat T, geQuaternion *QT)

Description: Calculates a spherical interpolation between two quaternions.

Parameters:

Q0 Start quaternion
Q1 End quaternion
T Percentage (value from 0 through 1) between Q0 and Q1 that we need to end up at.
QT Interpolated result

Returns: void

Remarks: This function is the same as Quaternion_Slerp, except that we do not ensure that the resulting path is not the shortest one. Hence W can be either sign in the result.

void geQuaternion_Subtract(const geQuaternion *Q1, const geQuaternion *Q2, geQuaternion *Q2MinusQ1)

Description: Subtracts two quaternions.

Parameters:

Q1 Input quaternion
Q2 Input quaternion
Q2MinusQ1 Result of Q2 - Q1

Returns: void

Remarks: Result is not necessarily a unit quaternion.

void geQuaternion_ToMatrix(const geQuaternion *Q, geXForm3d *XForm)

Description: Builds a rotation transform from a quaternion.

Parameters:

Q Unit quaternion
XForm Transform to receive rotational equivalent of Q

Returns: void

Remarks: Any translation in XForm is lost. This function does not work correctly on non-unit quaternions.