![]()
geQuaternion
Description: Quaternion mathematical system interface
Source file: \genis3d\OpenSource\Source\Math\quatern.h
API Functions: Copy, Normalize, SetFromAxisAngle, ToMatrix
Other Functions: Add, Compare, Exp, FromMatrix, Get, GetAxisAngle, GetVec3d, Inverse, IsUnit, IsValid, Ln, Magnitude, Multiply, Rotate, Scale, Set, SetNoRotation, SetVec3d, Slerp, SlerpNotShortest, Subtract,
Types: geQuaternion
Constants: QUATERNION_PI
Notes: view
Changes for Genesis3D v1.6: None
![]()
Types:
typedef struct{
geFloat W;
geFloat X,Y,Z;
// geVec3d QuatV;
} geQuaternion;
![]()
Constants:
#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 BasetypesIndexed.htm - NULLNULL.
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.
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.
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)
![]()
KDTOP Notes:
Quaternions were extremely confusing when I first encountered them. I read "an extension of complex numbers" and thought, "forget it!" I was reasonably good at college math, but I've forgotten much of it. And who needs them anyway? I didn't --at least at first.
Then I ran into the problem of trying to create a rotation matrix that would rotate an actor around an arbitrary axis. I knew how to rotate about the world's X, Y, or Z axis, but how could I rotate about some other axis? I was simulating a ball that my actor could throw. I thought, "wouldn't it be cool if, upon landing, it rolled like a real ball?" But what a headache to figure out a matrix that would do that! So I started reading graphics-for-games books, and guess what I found? You guessed it, quaternions.
So here is the overview of what I've learned about quaternions:
- They can hold all the information needed to rotate points, just as a matrix can.
- It is easy to set the axis of rotation to ANY desired axis
- They are numerically more stable, and faster to compute, than a matrix
- They can be converted to a standard matrix--so the result can be used for geActor_SetPose()
LOOK AT THIS... Here is a great page that helped me understand: view
Note: some of these these quanternion functions are not part of the Genesis3d API (notice the lack of GENESISAPI in front of some functions.) So to get access to the full library, the code must be included in one's project.
Here's a great little function that uses quaternions to rotate a matrix about any arbitrary axis. view
Now, here are some original notes...
(The following was ripped 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.
![]()