Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

quatern.h

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  QUATERN.H                                                                           */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                */
00005 /*  Description: Quaternion mathematical system interface                               */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*  Genesis3D Version 1.1 released November 15, 1999                                 */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #ifndef GE_QUATERNION_H
00023 #define GE_QUATERNION_H
00024 
00025 /***************************************************************************
00026 
00027         The quatern module contains basic support for a quaternion object.
00028 
00029         quaternions are an extension of complex numbers that allows an
00030         expression for rotation that can be easily interpolated.  geQuaternion_s are also 
00031         more numericaly stable for repeated rotations than matrices.
00032 
00033         
00034         A quaternion is a 4 element 'vector'  [w,x,y,z] where:
00035 
00036         q = w + xi + yj + zk
00037         i*i = -1
00038         j*j = -1
00039         k*k = -1
00040         i*j = -j*i = k
00041         j*k = -k*j = i
00042         k*i = -i*k = j
00043         q' (conjugate) = w - xi - yj - zk
00044         ||q|| (magnitude) = sqrt(q*q') = sqrt(w*w + x*x + y*y + z*z)
00045         unit quaternion ||q|| == 1; this implies  q' == qinverse 
00046         quaternions are associative (q1*q2)*q3 == q1*(q2*q3)
00047         quaternions are not commutative  q1*q2 != q2*q1
00048         qinverse (inverse (1/q) ) = q'/(q*q')
00049         
00050         q can be expressed by w + xi + yj + zk or [w,x,y,z] 
00051         or as in this implementation (s,v) where s=w, and v=[x,y,z]
00052 
00053         quaternions can represent a rotation.  The rotation is an angle t, around a 
00054         unit vector u.   q=(s,v);  s= cos(t/2);   v= u*sin(t/2).
00055 
00056         quaternions can apply the rotation to a point.  let the point be p [px,py,pz],
00057         and let P be a quaternion(0,p).  Protated = q*P*qinverse 
00058         ( Protated = q*P*q' if q is a unit quaternion)
00059 
00060         concatenation rotations is similar to matrix concatenation.  given two rotations
00061         q1 and q2,  to rotate by q1, then q2:  let qc = (q2*q1), then the combined 
00062         rotation is given by qc*P*qcinverse (= qc*P*qc' if q is a unit quaternion)
00063 
00064         multiplication: 
00065         q1 = w1 + x1i + y1j + z1k
00066         q2 = w2 + x2i + y2j + z2k
00067         q1*q2 = q3 =
00068                         (w1*w2 - x1*x2 - y1*y2 - z1*z2)     {w3}
00069                 (w1*x2 + x1*w2 + y1*z2 - z1*y2)i        {x3}
00070                         (w1*y2 - x1*z2 + y1*w2 + z1*x2)j    {y3}
00071                         (w1*z2 + x1*y2 + y1*x2 + z1*w2)k        {z3}
00072 
00073         also, 
00074         q1 = (s1,v1) = [s1,(x1,y1,z1)]
00075         q2 = (s2,v2) = [s2,(x2,y2,z2)]
00076         q1*q2 = q3      =       (s1*s2 - dot_product(v1,v2),                    {s3}
00077                                         (s1*v2 + s2*v1 + cross_product(v1,v2))  {v3}
00078 
00079 
00080         interpolation - it is possible (and sometimes reasonable) to interpolate between
00081         two quaternions by interpolating each component.  This does not quarantee a 
00082         resulting unit quaternion, and will result in an animation with non-linear 
00083         rotational velocity.
00084 
00085         spherical interpolation: (slerp) treat the quaternions as vectors 
00086         find the angle between them (w = arccos(q1 dot q2) ).
00087         given 0<=t<=1,  q(t) = q1*(sin((1-t)*w)/sin(w) + q2 * sin(t*w)/sin(w).
00088         since q == -q, care must be taken to rotate the proper way.  
00089 
00090         this implementation uses the notation quaternion q = (quatS,quatV) 
00091           where quatS is a scalar, and quatV is a 3 element vector.
00092 
00093 ********************************************/
00094 
00095 #include "basetype.h"
00096 #include "xform3d.h"
00097 
00098 #ifdef __cplusplus
00099 extern "C" {
00100 #endif
00101 
00102 typedef struct 
00103 {
00104         geFloat W;
00105         geFloat   X,Y,Z;
00106         //geVec3d   QuatV;
00107 } geQuaternion;
00108 
00109 
00110 #define QUATERNION_PI   (GE_PI)
00111 
00112 geBoolean GENESISCC geQuaternion_IsValid( const geQuaternion *Q );
00113         // return GE_TRUE if Q is non null and for has no NAN's in its components
00114 
00115 void GENESISCC geQuaternion_Set( geQuaternion *Q, geFloat W, geFloat X, geFloat Y, geFloat Z);
00116         // set quaternion components.  Doesn't normalize
00117 void GENESISCC geQuaternion_SetVec3d( geQuaternion *Q, geFloat W, const geVec3d *V);
00118         // set quaternion components.  Doesn't normalize
00119 GENESISAPI void GENESISCC geQuaternion_SetFromAxisAngle(geQuaternion *Q, const geVec3d *Axis, geFloat Theta);
00120         // set a quaternion from an axis and a rotation around the axis
00121 geBoolean GENESISCC geQuaternion_GetAxisAngle(const geQuaternion *Q, geVec3d *Axis, geFloat *Theta);
00122         // gets an axis and angle of rotation around the axis from a quaternion
00123         // returns GE_TRUE if there is an axis.  
00124         // returns GE_FALSE if there is no axis (and Axis is set to 0,0,0, and Theta is 0)
00125 
00126 void GENESISCC geQuaternion_Get( const geQuaternion *Q, 
00127                                         geFloat *W, geFloat *X, geFloat *Y, geFloat *Z);
00128         // get quaternion components into W,X,Y,Z
00129 void GENESISCC geQuaternion_GetVec3d( const geQuaternion *Q, geFloat *W, geVec3d *V);
00130         // get quaternion components into W and V
00131 
00132 void GENESISCC geQuaternion_FromMatrix(
00133         const geXForm3d         *RotationMatrix,
00134               geQuaternion      *QDest);
00135         // takes upper 3 by 3 portion of matrix (rotation sub matrix) 
00136         // and generates a quaternion
00137 
00138 GENESISAPI void GENESISCC geQuaternion_ToMatrix(
00139         const geQuaternion      *Q, 
00140                   geXForm3d             *RotationMatrixDest);
00141         // takes a unit quaternion and makes RotationMatrixDest an equivelant rotation xform.
00142         // (any translation in RotationMatrixDest will be list)
00143 
00144 void GENESISCC geQuaternion_Slerp(
00145         const geQuaternion              *Q0, 
00146         const geQuaternion              *Q1, 
00147         geFloat                                 T,              
00148         geQuaternion                    *QT);
00149         // spherical interpolation between q0 and q1.   0<=t<=1 
00150         // resulting quaternion is 'between' q0 and q1
00151         // with t==0 being all q0, and t==1 being all q1.
00152         // returns a quaternion with a positive W - always takes shortest route
00153         // through the positive W domain.
00154 
00155 void GENESISCC geQuaternion_SlerpNotShortest(
00156         const geQuaternion              *Q0, 
00157         const geQuaternion              *Q1, 
00158         geFloat                                 T,              
00159         geQuaternion                    *QT);
00160         // spherical interpolation between q0 and q1.   0<=t<=1 
00161         // resulting quaternion is 'between' q0 and q1
00162         // with t==0 being all q0, and t==1 being all q1.
00163 
00164 
00165 void GENESISCC geQuaternion_Multiply(
00166         const geQuaternion      *Q1, 
00167         const geQuaternion      *Q2, 
00168         geQuaternion                    *QProduct);
00169         // multiplies q1 * q2, and places the result in q.
00170         // no failure.  renormalization not automatic
00171 
00172 void GENESISCC geQuaternion_Rotate(
00173         const geQuaternion      *Q, 
00174         const geVec3d       *V, 
00175         geVec3d                         *VRotated);
00176         // Rotates V by the quaternion Q, places the result in VRotated.
00177 
00178 geBoolean GENESISCC geQuaternion_IsUnit(const geQuaternion *Q);
00179         // returns GE_TRUE if q is a unit quaternion.  GE_FALSE otherwise.
00180 
00181 GENESISAPI geFloat GENESISCC geQuaternion_Normalize(geQuaternion *Q);
00182         // normalizes q to be a unit quaternion.  returns original magnitude of q
00183 
00184 GENESISAPI void GENESISCC geQuaternion_Copy(const geQuaternion *QSrc, geQuaternion *QDst);
00185         // copies quaternion QSrc into QDst
00186 
00187 void GENESISCC geQuaternion_SetNoRotation(geQuaternion *Q);
00188         // sets Q to be a quaternion with no rotation (like an identity matrix)
00189 
00190 void GENESISCC geQuaternion_Ln(
00191         const geQuaternion *Q, 
00192         geQuaternion *LnQ);
00193         // ln(Q) for unit quaternion only!
00194 
00195 void GENESISCC geQuaternion_Exp(
00196         const geQuaternion *Q,
00197         geQuaternion *ExpQ);
00198         // exp(Q) for pure quaternion only!  (zero scalar part (W))
00199 
00200 void GENESISCC geQuaternion_Scale(
00201         const geQuaternion *Q,
00202         geFloat Scale,
00203         geQuaternion *QScaled);
00204         // Q = Q * Scale  (result is not generally a unit quaternion!)
00205 
00206 void GENESISCC geQuaternion_Add(
00207         const geQuaternion *Q1,
00208         const geQuaternion *Q2,
00209         geQuaternion *QSum);
00210         // QSum = Q1 + Q2  (result is not generally a unit quaternion!)
00211 
00212 void GENESISCC geQuaternion_Subtract(
00213         const geQuaternion *Q1, 
00214         const geQuaternion *Q2, 
00215         geQuaternion *QSum);
00216         // QSum = Q1 - Q2  (result is not generally a unit quaternion!)
00217 
00218 void GENESISCC geQuaternion_Inverse(const geQuaternion *Q, geQuaternion *QInv);
00219         // sets QInv to the inverse of Q.  
00220 
00221 geFloat GENESISCC geQuaternion_Magnitude(const geQuaternion *Q);
00222         // returns Magnitude of Q.  
00223 
00224 geBoolean GENESISCC geQuaternion_Compare( geQuaternion *Q1, geQuaternion *Q2, geFloat Tolerance );
00225         // return GE_TRUE if quaternions differ elementwise by less than Tolerance.
00226 
00227 
00228 #ifndef NDEBUG
00229 void GENESISCC geQuaternion_SetMaximalAssertionMode( geBoolean Enable );
00230 #endif
00231 
00232 #ifdef __cplusplus
00233 }
00234 #endif
00235 
00236 
00237 #endif // GE_QUATERNION_H

Generated on Tue Sep 30 12:36:15 2003 for GTestAndEngine by doxygen 1.3.2