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