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