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