00001 
00032 #ifndef LLQUATERNION_H
00033 #define LLQUATERNION_H
00034 
00035 #include "llmath.h"
00036 
00037 class LLVector4;
00038 class LLVector3;
00039 class LLVector3d;
00040 class LLMatrix4;
00041 class LLMatrix3;
00042 
00043 
00044 
00045 
00046 
00047 
00048 static const U32 LENGTHOFQUAT = 4;
00049 
00050 class LLQuaternion
00051 {
00052 public:
00053         F32 mQ[LENGTHOFQUAT];
00054 
00055         static const LLQuaternion DEFAULT;
00056 
00057         LLQuaternion();                                                                 
00058         explicit LLQuaternion(const LLMatrix4 &mat);                            
00059         explicit LLQuaternion(const LLMatrix3 &mat);                            
00060         LLQuaternion(F32 x, F32 y, F32 z, F32 w);               
00061         LLQuaternion(F32 angle, const LLVector4 &vec);  
00062         LLQuaternion(F32 angle, const LLVector3 &vec);  
00063         LLQuaternion(const F32 *q);                                             
00064         LLQuaternion(const LLVector3 &x_axis,
00065                                  const LLVector3 &y_axis,
00066                                  const LLVector3 &z_axis);                      
00067 
00068         BOOL isIdentity() const;
00069         BOOL isNotIdentity() const;
00070         BOOL isFinite() const;                                                                  
00071         void quantize16(F32 lower, F32 upper);                                  
00072         void quantize8(F32 lower, F32 upper);                                                   
00073         void loadIdentity();                                                                                    
00074         const LLQuaternion&     setQuatInit(F32 x, F32 y, F32 z, F32 w);        
00075         const LLQuaternion&     setQuat(const LLQuaternion &quat);                      
00076         const LLQuaternion&     setQuat(const F32 *q);                                          
00077         const LLQuaternion&     setQuat(const LLMatrix3 &mat);                          
00078         const LLQuaternion&     setQuat(const LLMatrix4 &mat);                          
00079         const LLQuaternion&     setQuat(F32 angle, F32 x, F32 y, F32 z);        
00080         const LLQuaternion&     setQuat(F32 angle, const LLVector3 &vec);       
00081         const LLQuaternion&     setQuat(F32 angle, const LLVector4 &vec);       
00082         const LLQuaternion&     setQuat(F32 roll, F32 pitch, F32 yaw);          
00083 
00084         LLMatrix4       getMatrix4(void) const;                                                 
00085         LLMatrix3       getMatrix3(void) const;                                                 
00086         void            getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; 
00087         void            getAngleAxis(F32* angle, LLVector3 &vec) const;
00088         void            getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const;
00089 
00090         F32                             normQuat();                                     
00091         const LLQuaternion&     conjQuat(void);                         
00092 
00093         
00094         const LLQuaternion&     transQuat();                                                                                    
00095         void                    shortestArc(const LLVector3 &a, const LLVector3 &b);    
00096         const LLQuaternion& constrain(F32 radians);                                             
00097 
00098         
00099         friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a);                                        
00100         friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b);    
00101         friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b);    
00102         friend LLQuaternion operator-(const LLQuaternion &a);                                                   
00103         friend LLQuaternion operator*(F32 a, const LLQuaternion &q);                                    
00104         friend LLQuaternion operator*(const LLQuaternion &q, F32 b);                                    
00105         friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b);    
00106         friend LLQuaternion operator~(const LLQuaternion &a);                                                   
00107         bool operator==(const LLQuaternion &b) const;                   
00108         bool operator!=(const LLQuaternion &b) const;                   
00109 
00110         friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b);  
00111 
00112         friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot);                
00113         friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot);                
00114         friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot);              
00115 
00116         
00117         friend F32 dot(const LLQuaternion &a, const LLQuaternion &b);
00118         friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q);          
00119         friend LLQuaternion lerp(F32 t, const LLQuaternion &q);                                                         
00120         friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q);         
00121         friend LLQuaternion slerp(F32 t, const LLQuaternion &q);                                                        
00122         friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q);         
00123         friend LLQuaternion nlerp(F32 t, const LLQuaternion &q);                                                        
00124 
00125         LLVector3       packToVector3() const;                                          
00126         void            unpackFromVector3(const LLVector3& vec);        
00127 
00128         enum Order {
00129                 XYZ = 0,
00130                 YZX = 1,
00131                 ZXY = 2,
00132                 XZY = 3,
00133                 YXZ = 4,
00134                 ZYX = 5
00135         };
00136         
00137         
00138         friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order);
00139 
00140         
00141         friend const char *OrderToString( const Order order );
00142         friend Order StringToOrder( const char *str );
00143 
00144         static BOOL parseQuat(const char* buf, LLQuaternion* value);
00145 
00146         
00147         
00148 };
00149 
00150 
00151 inline BOOL     LLQuaternion::isFinite() const
00152 {
00153         return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS]));
00154 }
00155 
00156 inline BOOL LLQuaternion::isIdentity() const
00157 {
00158         return 
00159                 ( mQ[VX] == 0.f ) &&
00160                 ( mQ[VY] == 0.f ) &&
00161                 ( mQ[VZ] == 0.f ) &&
00162                 ( mQ[VS] == 1.f );
00163 }
00164 
00165 inline BOOL LLQuaternion::isNotIdentity() const
00166 {
00167         return 
00168                 ( mQ[VX] != 0.f ) ||
00169                 ( mQ[VY] != 0.f ) ||
00170                 ( mQ[VZ] != 0.f ) ||
00171                 ( mQ[VS] != 1.f );
00172 }
00173 
00174 
00175 
00176 inline LLQuaternion::LLQuaternion(void)
00177 {
00178         mQ[VX] = 0.f;
00179         mQ[VY] = 0.f;
00180         mQ[VZ] = 0.f;
00181         mQ[VS] = 1.f;
00182 }
00183 
00184 inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w)
00185 {
00186         mQ[VX] = x;
00187         mQ[VY] = y;
00188         mQ[VZ] = z;
00189         mQ[VS] = w;
00190 
00191         
00192         
00193         
00194 
00195 
00196 
00197 
00198 
00199 }
00200 
00201 inline LLQuaternion::LLQuaternion(const F32 *q)
00202 {
00203         mQ[VX] = q[VX];
00204         mQ[VY] = q[VY];
00205         mQ[VZ] = q[VZ];
00206         mQ[VS] = q[VW];
00207 
00208         normQuat();
00209         
00210 
00211 
00212 
00213 
00214 
00215 }
00216 
00217 
00218 inline void LLQuaternion::loadIdentity()
00219 {
00220         mQ[VX] = 0.0f;
00221         mQ[VY] = 0.0f;
00222         mQ[VZ] = 0.0f;
00223         mQ[VW] = 1.0f;
00224 }
00225 
00226 
00227 inline const LLQuaternion&      LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w)
00228 {
00229         mQ[VX] = x;
00230         mQ[VY] = y;
00231         mQ[VZ] = z;
00232         mQ[VS] = w;
00233         normQuat();
00234         return (*this);
00235 }
00236 
00237 inline const LLQuaternion&      LLQuaternion::setQuat(const LLQuaternion &quat)
00238 {
00239         mQ[VX] = quat.mQ[VX];
00240         mQ[VY] = quat.mQ[VY];
00241         mQ[VZ] = quat.mQ[VZ];
00242         mQ[VW] = quat.mQ[VW];
00243         normQuat();
00244         return (*this);
00245 }
00246 
00247 inline const LLQuaternion&      LLQuaternion::setQuat(const F32 *q)
00248 {
00249         mQ[VX] = q[VX];
00250         mQ[VY] = q[VY];
00251         mQ[VZ] = q[VZ];
00252         mQ[VS] = q[VW];
00253         normQuat();
00254         return (*this);
00255 }
00256 
00257 
00258 
00259 
00260 inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const
00261 {
00262         F32 cos_a = mQ[VW];
00263         if (cos_a > 1.0f) cos_a = 1.0f;
00264         if (cos_a < -1.0f) cos_a = -1.0f;
00265 
00266     F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
00267 
00268     if ( fabs( sin_a ) < 0.0005f )
00269                 sin_a = 1.0f;
00270         else
00271                 sin_a = 1.f/sin_a;
00272 
00273     *angle = 2.0f * (F32) acos( cos_a );
00274     *x = mQ[VX] * sin_a;
00275     *y = mQ[VY] * sin_a;
00276     *z = mQ[VZ] * sin_a;
00277 }
00278 
00279 inline const LLQuaternion& LLQuaternion::conjQuat()
00280 {
00281         mQ[VX] *= -1.f;
00282         mQ[VY] *= -1.f;
00283         mQ[VZ] *= -1.f;
00284         return (*this);
00285 }
00286 
00287 
00288 inline const LLQuaternion& LLQuaternion::transQuat()
00289 {
00290         mQ[VX] = -mQ[VX];
00291         mQ[VY] = -mQ[VY];
00292         mQ[VZ] = -mQ[VZ];
00293         return *this;
00294 }
00295 
00296 
00297 inline LLQuaternion     operator+(const LLQuaternion &a, const LLQuaternion &b)
00298 {
00299         return LLQuaternion( 
00300                 a.mQ[VX] + b.mQ[VX],
00301                 a.mQ[VY] + b.mQ[VY],
00302                 a.mQ[VZ] + b.mQ[VZ],
00303                 a.mQ[VW] + b.mQ[VW] );
00304 }
00305 
00306 
00307 inline LLQuaternion     operator-(const LLQuaternion &a, const LLQuaternion &b)
00308 {
00309         return LLQuaternion( 
00310                 a.mQ[VX] - b.mQ[VX],
00311                 a.mQ[VY] - b.mQ[VY],
00312                 a.mQ[VZ] - b.mQ[VZ],
00313                 a.mQ[VW] - b.mQ[VW] );
00314 }
00315 
00316 
00317 inline LLQuaternion     operator-(const LLQuaternion &a)
00318 {
00319         return LLQuaternion(
00320                 -a.mQ[VX],
00321                 -a.mQ[VY],
00322                 -a.mQ[VZ],
00323                 -a.mQ[VW] );
00324 }
00325 
00326 
00327 inline LLQuaternion     operator*(F32 a, const LLQuaternion &q)
00328 {
00329         return LLQuaternion(
00330                 a * q.mQ[VX],
00331                 a * q.mQ[VY],
00332                 a * q.mQ[VZ],
00333                 a * q.mQ[VW] );
00334 }
00335 
00336 
00337 inline LLQuaternion     operator*(const LLQuaternion &q, F32 a)
00338 {
00339         return LLQuaternion(
00340                 a * q.mQ[VX],
00341                 a * q.mQ[VY],
00342                 a * q.mQ[VZ],
00343                 a * q.mQ[VW] );
00344 }
00345 
00346 inline LLQuaternion     operator~(const LLQuaternion &a)
00347 {
00348         LLQuaternion q(a);
00349         q.conjQuat();
00350         return q;
00351 }
00352 
00353 inline bool     LLQuaternion::operator==(const LLQuaternion &b) const
00354 {
00355         return (  (mQ[VX] == b.mQ[VX])
00356                         &&(mQ[VY] == b.mQ[VY])
00357                         &&(mQ[VZ] == b.mQ[VZ])
00358                         &&(mQ[VS] == b.mQ[VS]));
00359 }
00360 
00361 inline bool     LLQuaternion::operator!=(const LLQuaternion &b) const
00362 {
00363         return (  (mQ[VX] != b.mQ[VX])
00364                         ||(mQ[VY] != b.mQ[VY])
00365                         ||(mQ[VZ] != b.mQ[VZ])
00366                         ||(mQ[VS] != b.mQ[VS]));
00367 }
00368 
00369 inline const LLQuaternion&      operator*=(LLQuaternion &a, const LLQuaternion &b)
00370 {
00371 #if 1
00372         LLQuaternion q(
00373                 b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1],
00374                 b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2],
00375                 b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0],
00376                 b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2]
00377         );
00378         a = q;
00379 #else
00380         a = a * b;
00381 #endif
00382         return a;
00383 }
00384 
00385 inline F32      LLQuaternion::normQuat()
00386 {
00387         F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
00388 
00389         if (mag > FP_MAG_THRESHOLD)
00390         {
00391                 F32 oomag = 1.f/mag;
00392                 mQ[VX] *= oomag;
00393                 mQ[VY] *= oomag;
00394                 mQ[VZ] *= oomag;
00395                 mQ[VS] *= oomag;
00396         }
00397         else
00398         {
00399                 mQ[VX] = 0.f;
00400                 mQ[VY] = 0.f;
00401                 mQ[VZ] = 0.f;
00402                 mQ[VS] = 1.f;
00403         }
00404 
00405         return mag;
00406 }
00407 
00408 LLQuaternion::Order StringToOrder( const char *str );
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 #endif