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
1.3.2