00001 
00032 #include "linden_common.h"
00033 
00034 #include "llquaternion.h"
00035 
00036 #include "llmath.h"     
00037 
00038 #include "v3math.h"
00039 #include "v3dmath.h"
00040 #include "v4math.h"
00041 #include "m4math.h"
00042 #include "m3math.h"
00043 #include "llquantize.h"
00044 
00045 
00046 
00047 const LLQuaternion LLQuaternion::DEFAULT;
00048  
00049 
00050 
00051 LLQuaternion::LLQuaternion(const LLMatrix4 &mat)
00052 {
00053         *this = mat.quaternion();
00054         normQuat();
00055 }
00056 
00057 LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
00058 {
00059         *this = mat.quaternion();
00060         normQuat();
00061 }
00062 
00063 LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
00064 {
00065         LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
00066         v.normVec();
00067 
00068         F32 c, s;
00069         c = cosf(angle*0.5f);
00070         s = sinf(angle*0.5f);
00071 
00072         mQ[VX] = v.mV[VX] * s;
00073         mQ[VY] = v.mV[VY] * s;
00074         mQ[VZ] = v.mV[VZ] * s;
00075         mQ[VW] = c;
00076         normQuat();
00077 }
00078 
00079 LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
00080 {
00081         LLVector3 v(vec);
00082         v.normVec();
00083 
00084         F32 c, s;
00085         c = cosf(angle*0.5f);
00086         s = sinf(angle*0.5f);
00087 
00088         mQ[VX] = v.mV[VX] * s;
00089         mQ[VY] = v.mV[VY] * s;
00090         mQ[VZ] = v.mV[VZ] * s;
00091         mQ[VW] = c;
00092         normQuat();
00093 }
00094 
00095 LLQuaternion::LLQuaternion(const LLVector3 &x_axis,
00096                                                    const LLVector3 &y_axis,
00097                                                    const LLVector3 &z_axis)
00098 {
00099         LLMatrix3 mat;
00100         mat.setRows(x_axis, y_axis, z_axis);
00101         *this = mat.quaternion();
00102         normQuat();
00103 }
00104 
00105 
00106 void    LLQuaternion::quantize16(F32 lower, F32 upper)
00107 {
00108         F32 x = mQ[VX];
00109         F32 y = mQ[VY];
00110         F32 z = mQ[VZ];
00111         F32 s = mQ[VS];
00112 
00113         x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper);
00114         y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper);
00115         z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper);
00116         s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper);
00117 
00118         mQ[VX] = x;
00119         mQ[VY] = y;
00120         mQ[VZ] = z;
00121         mQ[VS] = s;
00122 
00123         normQuat();
00124 }
00125 
00126 void    LLQuaternion::quantize8(F32 lower, F32 upper)
00127 {
00128         mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper);
00129         mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper);
00130         mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
00131         mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
00132 
00133         normQuat();
00134 }
00135 
00136 
00137 
00138 
00139 
00140 
00141 const LLQuaternion&     LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z)
00142 {
00143         LLVector3 vec(x, y, z);
00144         vec.normVec();
00145 
00146         angle *= 0.5f;
00147         F32 c, s;
00148         c = cosf(angle);
00149         s = sinf(angle);
00150 
00151         mQ[VX] = vec.mV[VX]*s;
00152         mQ[VY] = vec.mV[VY]*s;
00153         mQ[VZ] = vec.mV[VZ]*s;
00154         mQ[VW] = c;
00155 
00156         normQuat();
00157         return (*this);
00158 }
00159 
00160 const LLQuaternion&     LLQuaternion::setQuat(F32 angle, const LLVector3 &vec)
00161 {
00162         LLVector3 v(vec);
00163         v.normVec();
00164 
00165         angle *= 0.5f;
00166         F32 c, s;
00167         c = cosf(angle);
00168         s = sinf(angle);
00169 
00170         mQ[VX] = v.mV[VX]*s;
00171         mQ[VY] = v.mV[VY]*s;
00172         mQ[VZ] = v.mV[VZ]*s;
00173         mQ[VW] = c;
00174 
00175         normQuat();
00176         return (*this);
00177 }
00178 
00179 const LLQuaternion&     LLQuaternion::setQuat(F32 angle, const LLVector4 &vec)
00180 {
00181         LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
00182         v.normVec();
00183 
00184         F32 c, s;
00185         c = cosf(angle*0.5f);
00186         s = sinf(angle*0.5f);
00187 
00188         mQ[VX] = v.mV[VX]*s;
00189         mQ[VY] = v.mV[VY]*s;
00190         mQ[VZ] = v.mV[VZ]*s;
00191         mQ[VW] = c;
00192 
00193         normQuat();
00194         return (*this);
00195 }
00196 
00197 const LLQuaternion&     LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw)
00198 {
00199         LLMatrix3 rot_mat(roll, pitch, yaw);
00200         rot_mat.orthogonalize();
00201         *this = rot_mat.quaternion();
00202                 
00203         normQuat();
00204         return (*this);
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 }
00253 
00254 
00255 
00256 
00257 
00258 
00259 LLMatrix3       LLQuaternion::getMatrix3(void) const
00260 {
00261         LLMatrix3       mat;
00262         F32             xx, xy, xz, xw, yy, yz, yw, zz, zw;
00263 
00264     xx      = mQ[VX] * mQ[VX];
00265     xy      = mQ[VX] * mQ[VY];
00266     xz      = mQ[VX] * mQ[VZ];
00267     xw      = mQ[VX] * mQ[VW];
00268 
00269     yy      = mQ[VY] * mQ[VY];
00270     yz      = mQ[VY] * mQ[VZ];
00271     yw      = mQ[VY] * mQ[VW];
00272 
00273     zz      = mQ[VZ] * mQ[VZ];
00274     zw      = mQ[VZ] * mQ[VW];
00275 
00276     mat.mMatrix[0][0]  = 1.f - 2.f * ( yy + zz );
00277     mat.mMatrix[0][1]  =           2.f * ( xy + zw );
00278     mat.mMatrix[0][2]  =           2.f * ( xz - yw );
00279 
00280     mat.mMatrix[1][0]  =           2.f * ( xy - zw );
00281     mat.mMatrix[1][1]  = 1.f - 2.f * ( xx + zz );
00282     mat.mMatrix[1][2]  =           2.f * ( yz + xw );
00283 
00284     mat.mMatrix[2][0]  =           2.f * ( xz + yw );
00285     mat.mMatrix[2][1]  =           2.f * ( yz - xw );
00286     mat.mMatrix[2][2]  = 1.f - 2.f * ( xx + yy );
00287 
00288         return mat;
00289 }
00290 
00291 LLMatrix4       LLQuaternion::getMatrix4(void) const
00292 {
00293         LLMatrix4       mat;
00294         F32             xx, xy, xz, xw, yy, yz, yw, zz, zw;
00295 
00296     xx      = mQ[VX] * mQ[VX];
00297     xy      = mQ[VX] * mQ[VY];
00298     xz      = mQ[VX] * mQ[VZ];
00299     xw      = mQ[VX] * mQ[VW];
00300 
00301     yy      = mQ[VY] * mQ[VY];
00302     yz      = mQ[VY] * mQ[VZ];
00303     yw      = mQ[VY] * mQ[VW];
00304 
00305     zz      = mQ[VZ] * mQ[VZ];
00306     zw      = mQ[VZ] * mQ[VW];
00307 
00308     mat.mMatrix[0][0]  = 1.f - 2.f * ( yy + zz );
00309     mat.mMatrix[0][1]  =           2.f * ( xy + zw );
00310     mat.mMatrix[0][2]  =           2.f * ( xz - yw );
00311 
00312     mat.mMatrix[1][0]  =           2.f * ( xy - zw );
00313     mat.mMatrix[1][1]  = 1.f - 2.f * ( xx + zz );
00314     mat.mMatrix[1][2]  =           2.f * ( yz + xw );
00315 
00316     mat.mMatrix[2][0]  =           2.f * ( xz + yw );
00317     mat.mMatrix[2][1]  =           2.f * ( yz - xw );
00318     mat.mMatrix[2][2]  = 1.f - 2.f * ( xx + yy );
00319 
00320         
00321 
00322         return mat;
00323 }
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b)
00333 {
00334         
00335         LLVector3 vec_a = a;
00336         LLVector3 vec_b = b;
00337 
00338         
00339         
00340         F32 vec_a_mag = vec_a.normVec();
00341         F32 vec_b_mag = vec_b.normVec();
00342         if (vec_a_mag < F_APPROXIMATELY_ZERO ||
00343                 vec_b_mag < F_APPROXIMATELY_ZERO)
00344         {
00345                 
00346                 
00347                 loadIdentity();
00348                 return;
00349         }
00350 
00351         
00352         LLVector3 axis = vec_a % vec_b;
00353         F32 cos_theta  = vec_a * vec_b;
00354 
00355         
00356         if (cos_theta > 1.0 - F_APPROXIMATELY_ZERO)
00357         {
00358                 
00359                 loadIdentity();
00360         }
00361         else if (cos_theta < -1.0 + F_APPROXIMATELY_ZERO)
00362         {
00363                 
00364                 
00365                 
00366                 
00367                 
00368                 LLVector3 proj = vec_a.mV[VX] / (vec_a * vec_a) * vec_a;
00369                 LLVector3 ortho_axis(1.f, 0.f, 0.f);
00370                 ortho_axis -= proj;
00371                 
00372                 
00373                 F32 ortho_length = ortho_axis.normVec();
00374                 
00375                 
00376                 if (ortho_length < F_APPROXIMATELY_ZERO)
00377                 {
00378                         
00379                         ortho_axis.setVec(0.f, 0.f, 1.f);
00380                 }
00381 
00382                 
00383                 mQ[VX] = ortho_axis.mV[VX];
00384                 mQ[VY] = ortho_axis.mV[VY];
00385                 mQ[VZ] = ortho_axis.mV[VZ];
00386                 mQ[VW] = 0.f;
00387         }
00388         else
00389         {
00390                 
00391                 
00392                 F32 theta = (F32)acos(cos_theta);
00393 
00394                 setQuat(theta, axis);
00395         }
00396 }
00397 
00398 
00399 const LLQuaternion &LLQuaternion::constrain(F32 radians)
00400 {
00401         const F32 cos_angle_lim = cosf( radians/2 );    
00402         const F32 sin_angle_lim = sinf( radians/2 );    
00403 
00404         if (mQ[VW] < 0.f)
00405         {
00406                 mQ[VX] *= -1.f;
00407                 mQ[VY] *= -1.f;
00408                 mQ[VZ] *= -1.f;
00409                 mQ[VW] *= -1.f;
00410         }
00411 
00412         
00413         if( mQ[VW] < cos_angle_lim )
00414         {
00415                 mQ[VW] = cos_angle_lim;
00416                 F32 axis_len = sqrtf( mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] ); 
00417                 F32 axis_mult_fact = sin_angle_lim / axis_len;
00418                 mQ[VX] *= axis_mult_fact;
00419                 mQ[VY] *= axis_mult_fact;
00420                 mQ[VZ] *= axis_mult_fact;
00421         }
00422 
00423         return *this;
00424 }
00425 
00426 
00427 
00428 std::ostream& operator<<(std::ostream &s, const LLQuaternion &a)
00429 {
00430         s << "{ " 
00431                 << a.mQ[VX] << ", " << a.mQ[VY] << ", " << a.mQ[VZ] << ", " << a.mQ[VW] 
00432         << " }";
00433         return s;
00434 }
00435 
00436 
00437 
00438 LLQuaternion    operator*(const LLQuaternion &a, const LLQuaternion &b)
00439 {
00440 
00441 
00442         LLQuaternion q(
00443                 b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1],
00444                 b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2],
00445                 b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0],
00446                 b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2]
00447         );
00448         return q;
00449 }
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 LLVector4               operator*(const LLVector4 &a, const LLQuaternion &rot)
00462 {
00463     F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
00464     F32 rx =   rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
00465     F32 ry =   rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ];
00466     F32 rz =   rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX];
00467 
00468     F32 nx = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
00469     F32 ny = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
00470     F32 nz = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
00471 
00472     return LLVector4(nx, ny, nz, a.mV[VW]);
00473 }
00474 
00475 LLVector3               operator*(const LLVector3 &a, const LLQuaternion &rot)
00476 {
00477     F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
00478     F32 rx =   rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
00479     F32 ry =   rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ];
00480     F32 rz =   rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX];
00481 
00482     F32 nx = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
00483     F32 ny = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
00484     F32 nz = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
00485 
00486     return LLVector3(nx, ny, nz);
00487 }
00488 
00489 LLVector3d              operator*(const LLVector3d &a, const LLQuaternion &rot)
00490 {
00491     F64 rw = - rot.mQ[VX] * a.mdV[VX] - rot.mQ[VY] * a.mdV[VY] - rot.mQ[VZ] * a.mdV[VZ];
00492     F64 rx =   rot.mQ[VW] * a.mdV[VX] + rot.mQ[VY] * a.mdV[VZ] - rot.mQ[VZ] * a.mdV[VY];
00493     F64 ry =   rot.mQ[VW] * a.mdV[VY] + rot.mQ[VZ] * a.mdV[VX] - rot.mQ[VX] * a.mdV[VZ];
00494     F64 rz =   rot.mQ[VW] * a.mdV[VZ] + rot.mQ[VX] * a.mdV[VY] - rot.mQ[VY] * a.mdV[VX];
00495 
00496     F64 nx = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
00497     F64 ny = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
00498     F64 nz = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
00499 
00500     return LLVector3d(nx, ny, nz);
00501 }
00502 
00503 F32 dot(const LLQuaternion &a, const LLQuaternion &b)
00504 {
00505         return a.mQ[VX] * b.mQ[VX] + 
00506                    a.mQ[VY] * b.mQ[VY] + 
00507                    a.mQ[VZ] * b.mQ[VZ] + 
00508                    a.mQ[VW] * b.mQ[VW]; 
00509 }
00510 
00511 
00512 
00513 #if 0
00514 
00515 LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q)
00516 {
00517         LLQuaternion r;
00518         r = t * (q - p) + p;
00519         r.normQuat();
00520         return r;
00521 }
00522 #endif
00523 
00524 
00525 LLQuaternion lerp(F32 t, const LLQuaternion &q)
00526 {
00527         LLQuaternion r;
00528         r.mQ[VX] = t * q.mQ[VX];
00529         r.mQ[VY] = t * q.mQ[VY];
00530         r.mQ[VZ] = t * q.mQ[VZ];
00531         r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f;
00532         r.normQuat();
00533         return r;
00534 }
00535 
00536 LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q)
00537 {
00538         LLQuaternion r;
00539         F32 inv_t;
00540 
00541         inv_t = 1.f - t;
00542 
00543         r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]);
00544         r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]);
00545         r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]);
00546         r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]);
00547         r.normQuat();
00548         return r;
00549 }
00550 
00551 
00552 
00553 LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b )
00554 {
00555         
00556         F32 cos_t = a.mQ[0]*b.mQ[0] + a.mQ[1]*b.mQ[1] + a.mQ[2]*b.mQ[2] + a.mQ[3]*b.mQ[3];
00557         
00558         
00559         int bflip;
00560         if (cos_t < 0.0f)
00561         {
00562                 cos_t = -cos_t;
00563                 bflip = TRUE;
00564         }
00565         else
00566                 bflip = FALSE;
00567 
00568         
00569         
00570         F32 alpha;      
00571         F32 beta;               
00572         if (1.0f - cos_t < 0.00001f)
00573         {
00574                 beta = 1.0f - u;
00575                 alpha = u;
00576         }
00577         else
00578         {
00579                 F32 theta = acosf(cos_t);
00580                 F32 sin_t = sinf(theta);
00581                 beta = sinf(theta - u*theta) / sin_t;
00582                 alpha = sinf(u*theta) / sin_t;
00583         }
00584 
00585         if (bflip)
00586                 beta = -beta;
00587 
00588         
00589         LLQuaternion ret;
00590         ret.mQ[0] = beta*a.mQ[0] + alpha*b.mQ[0];
00591         ret.mQ[1] = beta*a.mQ[1] + alpha*b.mQ[1];
00592         ret.mQ[2] = beta*a.mQ[2] + alpha*b.mQ[2];
00593         ret.mQ[3] = beta*a.mQ[3] + alpha*b.mQ[3];
00594 
00595         return ret;
00596 }
00597 
00598 
00599 LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b)
00600 {
00601         if (dot(a, b) < 0.f)
00602         {
00603                 return slerp(t, a, b);
00604         }
00605         else
00606         {
00607                 return lerp(t, a, b);
00608         }
00609 }
00610 
00611 LLQuaternion nlerp(F32 t, const LLQuaternion &q)
00612 {
00613         if (q.mQ[VW] < 0.f)
00614         {
00615                 return slerp(t, q);
00616         }
00617         else
00618         {
00619                 return lerp(t, q);
00620         }
00621 }
00622 
00623 
00624 LLQuaternion slerp(F32 t, const LLQuaternion &q)
00625 {
00626         F32 c = q.mQ[VW];
00627         if (1.0f == t  ||  1.0f == c)
00628         {
00629                 
00630                 return q;
00631         }
00632 
00633         LLQuaternion r;
00634         F32 s, angle, stq, stp;
00635 
00636         s = (F32) sqrt(1.f - c*c);
00637 
00638     if (c < 0.0f)
00639     {
00640         
00641         
00642         
00643         
00644         
00645         angle   = (F32) acos(-c); 
00646         stp     = -(F32) sin(angle * (1.f - t));
00647         stq     = (F32) sin(angle * t);
00648     }   
00649     else
00650     {
00651                 angle   = (F32) acos(c);
00652         stp     = (F32) sin(angle * (1.f - t));
00653         stq     = (F32) sin(angle * t);
00654     }
00655 
00656         r.mQ[VX] = (q.mQ[VX] * stq) / s;
00657         r.mQ[VY] = (q.mQ[VY] * stq) / s;
00658         r.mQ[VZ] = (q.mQ[VZ] * stq) / s;
00659         r.mQ[VW] = (stp + q.mQ[VW] * stq) / s;
00660 
00661         return r;
00662 }
00663 
00664 LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order)
00665 {
00666         LLQuaternion xQ( xRot*DEG_TO_RAD, LLVector3(1.0f, 0.0f, 0.0f) );
00667         LLQuaternion yQ( yRot*DEG_TO_RAD, LLVector3(0.0f, 1.0f, 0.0f) );
00668         LLQuaternion zQ( zRot*DEG_TO_RAD, LLVector3(0.0f, 0.0f, 1.0f) );
00669         LLQuaternion ret;
00670         switch( order )
00671         {
00672         case LLQuaternion::XYZ:
00673                 ret = xQ * yQ * zQ;
00674                 break;
00675         case LLQuaternion::YZX:
00676                 ret = yQ * zQ * xQ;
00677                 break;
00678         case LLQuaternion::ZXY:
00679                 ret = zQ * xQ * yQ;
00680                 break;
00681         case LLQuaternion::XZY:
00682                 ret = xQ * zQ * yQ;
00683                 break;
00684         case LLQuaternion::YXZ:
00685                 ret = yQ * xQ * zQ;
00686                 break;
00687         case LLQuaternion::ZYX:
00688                 ret = zQ * yQ * xQ;
00689                 break;
00690         }
00691         return ret;
00692 }
00693 
00694 const char *OrderToString( const LLQuaternion::Order order )
00695 {
00696         char *p = NULL;
00697         switch( order )
00698         {
00699         default:
00700         case LLQuaternion::XYZ:
00701                 p = "XYZ";
00702                 break;
00703         case LLQuaternion::YZX:
00704                 p = "YZX";
00705                 break;
00706         case LLQuaternion::ZXY:
00707                 p = "ZXY";
00708                 break;
00709         case LLQuaternion::XZY:
00710                 p = "XZY";
00711                 break;
00712         case LLQuaternion::YXZ:
00713                 p = "YXZ";
00714                 break;
00715         case LLQuaternion::ZYX:
00716                 p = "ZYX";
00717                 break;
00718         }
00719         return p;
00720 }
00721 
00722 LLQuaternion::Order StringToOrder( const char *str )
00723 {
00724         if (strncmp(str, "XYZ", 3)==0 || strncmp(str, "xyz", 3)==0)
00725                 return LLQuaternion::XYZ;
00726 
00727         if (strncmp(str, "YZX", 3)==0 || strncmp(str, "yzx", 3)==0)
00728                 return LLQuaternion::YZX;
00729 
00730         if (strncmp(str, "ZXY", 3)==0 || strncmp(str, "zxy", 3)==0)
00731                 return LLQuaternion::ZXY;
00732 
00733         if (strncmp(str, "XZY", 3)==0 || strncmp(str, "xzy", 3)==0)
00734                 return LLQuaternion::XZY;
00735 
00736         if (strncmp(str, "YXZ", 3)==0 || strncmp(str, "yxz", 3)==0)
00737                 return LLQuaternion::YXZ;
00738 
00739         if (strncmp(str, "ZYX", 3)==0 || strncmp(str, "zyx", 3)==0)
00740                 return LLQuaternion::ZYX;
00741 
00742         return LLQuaternion::XYZ;
00743 }
00744 
00745 const LLQuaternion&     LLQuaternion::setQuat(const LLMatrix3 &mat)
00746 {
00747         *this = mat.quaternion();
00748         normQuat();
00749         return (*this);
00750 }
00751 
00752 const LLQuaternion&     LLQuaternion::setQuat(const LLMatrix4 &mat)
00753 {
00754         *this = mat.quaternion();
00755         normQuat();
00756         return (*this);
00757 }
00758 
00759 void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const
00760 {
00761         F32 cos_a = mQ[VW];
00762         if (cos_a > 1.0f) cos_a = 1.0f;
00763         if (cos_a < -1.0f) cos_a = -1.0f;
00764 
00765     F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
00766 
00767     if ( fabs( sin_a ) < 0.0005f )
00768                 sin_a = 1.0f;
00769         else
00770                 sin_a = 1.f/sin_a;
00771 
00772     *angle = 2.0f * (F32) acos( cos_a );
00773     vec.mV[VX] = mQ[VX] * sin_a;
00774     vec.mV[VY] = mQ[VY] * sin_a;
00775     vec.mV[VZ] = mQ[VZ] * sin_a;
00776 }
00777 
00778 
00779 
00780 void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
00781 {
00782         LLMatrix3 rot_mat(*this);
00783         rot_mat.orthogonalize();
00784         rot_mat.getEulerAngles(roll, pitch, yaw);
00785 
00786 
00787 
00788 
00789 
00790 
00791 
00792 
00793 
00794 
00795 
00796 
00797 
00798 
00799 
00800 
00801 
00802 
00803 
00804 }
00805 
00806 
00807 LLVector3 LLQuaternion::packToVector3() const
00808 {
00809         if( mQ[VW] >= 0 )
00810         {
00811                 return LLVector3( mQ[VX], mQ[VY], mQ[VZ] );
00812         }
00813         else
00814         {
00815                 return LLVector3( -mQ[VX], -mQ[VY], -mQ[VZ] );
00816         }
00817 }
00818 
00819 
00820 void LLQuaternion::unpackFromVector3( const LLVector3& vec )
00821 {
00822         mQ[VX] = vec.mV[VX];
00823         mQ[VY] = vec.mV[VY];
00824         mQ[VZ] = vec.mV[VZ];
00825         F32 t = 1.f - vec.magVecSquared();
00826         if( t > 0 )
00827         {
00828                 mQ[VW] = sqrt( t );
00829         }
00830         else
00831         {
00832                 
00833                 
00834                 mQ[VW] = 0;
00835         }
00836 }
00837 
00838 BOOL LLQuaternion::parseQuat(const char* buf, LLQuaternion* value)
00839 {
00840         if( buf == NULL || buf[0] == '\0' || value == NULL)
00841         {
00842                 return FALSE;
00843         }
00844 
00845         LLQuaternion quat;
00846         S32 count = sscanf( buf, "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 );
00847         if( 4 == count )
00848         {
00849                 value->setQuat( quat );
00850                 return TRUE;
00851         }
00852 
00853         return FALSE;
00854 }
00855 
00856 
00857