00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041
00042 #include "OSGConfig.h"
00043
00044 #include <iostream>
00045
00046 OSG_BEGIN_NAMESPACE
00047
00063
00064
00065
00067
00068 template <class ValueTypeT>
00069 QuaternionBase<ValueTypeT> QuaternionBase<ValueTypeT>::_identity;
00070
00072
00073 template <class ValueTypeT> inline
00074 const QuaternionBase<ValueTypeT> &QuaternionBase<ValueTypeT>::identity(void)
00075 {
00076 return _identity;
00077 }
00078
00080
00081 template <class ValueTypeT> inline
00082 QuaternionBase<ValueTypeT>
00083 QuaternionBase<ValueTypeT>::slerp(const QuaternionBase &rot0,
00084 const QuaternionBase &rot1,
00085 const ValueTypeT t )
00086 {
00087 QuaternionBase returnValue;
00088
00089 slerp(rot0, rot1, returnValue, t);
00090
00091 return returnValue;
00092 }
00093
00094
00095
00096
00097 template <class ValueTypeT> inline
00098 QuaternionBase<ValueTypeT>::QuaternionBase(void)
00099 {
00100 _quat[0] =
00101 _quat[1] =
00102 _quat[2] = TypeTraits<ValueTypeT>::getZeroElement();
00103
00104 _quat[3] = TypeTraits<ValueTypeT>::getOneElement();
00105 }
00106
00107
00108 template <class ValueTypeT> inline
00109 QuaternionBase<ValueTypeT>::QuaternionBase(const QuaternionBase &source)
00110 {
00111 for(UInt32 i = 0; i < 4; i++)
00112 {
00113 _quat[i] = source._quat[i];
00114 }
00115 }
00116
00117
00118 template <class ValueTypeT> inline
00119 QuaternionBase<ValueTypeT>::QuaternionBase(const MatrixType &matrix)
00120 {
00121 setValue(matrix);
00122 }
00123
00124
00125 template <class ValueTypeT> inline
00126 QuaternionBase<ValueTypeT>::QuaternionBase(const VectorType &axis,
00127 const ValueTypeT angle)
00128 {
00129 setValueAsAxisRad(axis, angle);
00130 }
00131
00133
00134 template <class ValueTypeT> inline
00135 QuaternionBase<ValueTypeT>::QuaternionBase(const VectorType &rotateFrom,
00136 const VectorType &rotateTo)
00137 {
00138 setValue(rotateFrom, rotateTo);
00139 }
00140
00141
00142
00143
00144 template <class ValueTypeT> inline
00145 QuaternionBase<ValueTypeT>::~QuaternionBase(void)
00146 {
00147 }
00148
00149
00150
00151
00153
00154 template <class ValueTypeT> inline
00155 void QuaternionBase<ValueTypeT>::setIdentity(void)
00156 {
00157 _quat[0] =
00158 _quat[1] =
00159 _quat[2] = TypeTraits<ValueTypeT>::getZeroElement();
00160
00161 _quat[3] = TypeTraits<ValueTypeT>::getOneElement();
00162 }
00163
00168 template <class ValueTypeT> inline
00169 void QuaternionBase<ValueTypeT>::setValueAsAxisRad(
00170 const ValueTypeT *valsP)
00171 {
00172 setValueAsAxisRad(valsP[0], valsP[1], valsP[2], valsP[3]);
00173 }
00174
00179 template <class ValueTypeT> inline
00180 void QuaternionBase<ValueTypeT>::setValueAsAxisDeg(
00181 const ValueTypeT *valsP)
00182 {
00183 setValueAsAxisDeg(valsP[0], valsP[1], valsP[2], valsP[3]);
00184 }
00185
00187
00188 template <class ValueTypeT> inline
00189 void QuaternionBase<ValueTypeT>::setValueAsQuat(
00190 const ValueTypeT *valsP)
00191 {
00192 UInt32 i;
00193
00194 for(i = 0; i < 4; i++)
00195 {
00196 _quat[i] = valsP[i];
00197 }
00198 }
00199
00204 template <class ValueTypeT> inline
00205 void QuaternionBase<ValueTypeT>::setValueAsAxisRad(const ValueTypeT x,
00206 const ValueTypeT y,
00207 const ValueTypeT z,
00208 const ValueTypeT w)
00209 {
00210 ValueTypeT rTmp = osgsqrt(x * x + y * y + z * z);
00211
00212 if(rTmp > Eps)
00213 {
00214 rTmp = osgsin(w / 2.0f) / rTmp;
00215
00216 _quat[0] = x * rTmp;
00217 _quat[1] = y * rTmp;
00218 _quat[2] = z * rTmp;
00219 _quat[3] = osgcos(w / 2.0f);
00220 }
00221 else
00222 {
00223 setIdentity();
00224 }
00225 }
00226
00231 template <class ValueTypeT> inline
00232 void QuaternionBase<ValueTypeT>::setValueAsAxisDeg(const ValueTypeT x,
00233 const ValueTypeT y,
00234 const ValueTypeT z,
00235 const ValueTypeT w)
00236 {
00237 setValueAsAxisRad(x,y,z,osgdegree2rad(w));
00238 }
00239
00244 template <class ValueTypeT> inline
00245 void QuaternionBase<ValueTypeT>::setValueAsQuat(const ValueTypeT x,
00246 const ValueTypeT y,
00247 const ValueTypeT z,
00248 const ValueTypeT w)
00249 {
00250 _quat[0] = x;
00251 _quat[1] = y;
00252 _quat[2] = z;
00253 _quat[3] = w;
00254 }
00255
00257
00258 template <class ValueTypeT> inline
00259 void QuaternionBase<ValueTypeT>::setValue(const MatrixType &matrix)
00260 {
00261 Real64 tr;
00262 Real64 s;
00263 Real64 qt[3];
00264
00265 UInt32 i;
00266 UInt32 j;
00267 UInt32 k;
00268
00269 UInt32 nxt[3] = { 1, 2, 0};
00270
00271 tr = matrix[0][0] + matrix[1][1] + matrix[2][2];
00272
00273 if(tr > 0.0)
00274 {
00275 s = osgsqrt(tr + 1.0);
00276
00277 _quat[3] = ValueTypeT(s * 0.5);
00278
00279 s = 0.5 / s;
00280
00281 _quat[0] = ValueTypeT((matrix[1][2] - matrix[2][1]) * s);
00282 _quat[1] = ValueTypeT((matrix[2][0] - matrix[0][2]) * s);
00283 _quat[2] = ValueTypeT((matrix[0][1] - matrix[1][0]) * s);
00284 }
00285 else
00286 {
00287 if(matrix[1][1] > matrix[0][0])
00288 i = 1;
00289 else
00290 i = 0;
00291
00292 if(matrix[2][2] > matrix[i][i])
00293 i = 2;
00294
00295 j = nxt[i];
00296 k = nxt[j];
00297
00298 s = osgsqrt(matrix[i][i] - (matrix[j][j] + matrix[k][k]) + 1.0 );
00299
00300 qt[i] = s * 0.5;
00301 s = 0.5 / s;
00302
00303 _quat[3] = ValueTypeT((matrix[j][k] - matrix[k][j]) * s);
00304
00305 qt[j] = (matrix[i][j] + matrix[j][i]) * s;
00306 qt[k] = (matrix[i][k] + matrix[k][i]) * s;
00307
00308 _quat[0] = ValueTypeT(qt[0]);
00309 _quat[1] = ValueTypeT(qt[1]);
00310 _quat[2] = ValueTypeT(qt[2]);
00311 }
00312
00313 if(_quat[3] > 1.0 || _quat[3] < -1.0)
00314 {
00315 const ValueTypeT errThreshold = 1 + (Eps * 100);
00316
00317 if(_quat[3] > errThreshold || _quat[3] < -errThreshold)
00318 {
00319 fprintf(stderr,
00320 "\nMatToQuat: BUG: |quat[4]| (%f) >> 1.0 !\n\n",
00321 _quat[3]);
00322 }
00323
00324 if(_quat[3] > 1.0)
00325 {
00326 _quat[3] = 1.0;
00327 }
00328 else
00329 {
00330 _quat[3] = -1.0;
00331 }
00332 }
00333 }
00334
00339 template <class ValueTypeT> inline
00340 void QuaternionBase<ValueTypeT>::setValueAsAxisRad(const VectorType &axis,
00341 ValueTypeT angle)
00342 {
00343 setValueAsAxisRad(axis[0], axis[1], axis[2], angle);
00344 }
00345
00350 template <class ValueTypeT> inline
00351 void QuaternionBase<ValueTypeT>::setValueAsAxisDeg(const VectorType &axis,
00352 ValueTypeT angle)
00353 {
00354 setValueAsAxisDeg(axis[0], axis[1], axis[2], angle);
00355 }
00356
00358
00359 template <class ValueTypeT> inline
00360 void QuaternionBase<ValueTypeT>::setValue(const VectorType &rotateFrom,
00361 const VectorType &rotateTo)
00362 {
00363 VectorType from = rotateFrom;
00364 VectorType to = rotateTo;
00365 VectorType axis;
00366 ValueTypeT cost;
00367
00368 from.normalize();
00369 to .normalize();
00370
00371 cost = from.dot(to);
00372
00373
00374 if(cost > 0.99999)
00375 {
00376 setIdentity();
00377 return;
00378 }
00379 else if(cost < -0.99999)
00380 {
00381
00382
00383
00384
00385
00386
00387 VectorType cAxis(1.0, 0.0, 0.0);
00388
00389 VectorType tmp = from.cross(cAxis);
00390
00391 if(tmp.length() < 0.00001)
00392 {
00393 cAxis.setValues(0.0, 1.0, 0.0);
00394
00395 tmp = from.cross(cAxis);
00396 }
00397
00398 tmp.normalize();
00399
00400 setValueAsAxisRad(tmp[0], tmp[1], tmp[2], Pi);
00401
00402 return;
00403 }
00404
00405 axis = rotateFrom.cross(rotateTo);
00406 axis.normalize();
00407
00408
00409
00410
00411 axis *= ValueTypeT(osgsqrt(0.5 * (1.0 - cost)));
00412
00413
00414
00415
00416 _quat[0] = axis[0];
00417 _quat[1] = axis[1];
00418 _quat[2] = axis[2];
00419
00420
00421
00422
00423 _quat[3] = ValueTypeT(osgsqrt(0.5 * (1.0 + cost)));
00424 }
00425
00426
00431 template <class ValueTypeT> inline
00432 void QuaternionBase<ValueTypeT>::setValueAsAxisRad(const Char8 *str)
00433 {
00434 setValueAsQuat(str);
00435
00436 if(osgfinite(_quat[0]) == 0 ||
00437 osgfinite(_quat[1]) == 0 ||
00438 osgfinite(_quat[2]) == 0 ||
00439 osgfinite(_quat[3]) == 0 )
00440 {
00441 setIdentity();
00442 }
00443 else
00444 {
00445 setValueAsAxisRad(_quat[0], _quat[1], _quat[2], _quat[3]);
00446 }
00447 }
00448
00453 template <class ValueTypeT> inline
00454 void QuaternionBase<ValueTypeT>::setValueAsAxisDeg(const Char8 *str)
00455 {
00456 setValueAsQuat(str);
00457
00458 if(osgfinite(_quat[0]) == 0 ||
00459 osgfinite(_quat[1]) == 0 ||
00460 osgfinite(_quat[2]) == 0 ||
00461 osgfinite(_quat[3]) == 0 )
00462 {
00463 setIdentity();
00464 }
00465 else
00466 {
00467 setValueAsAxisDeg(_quat[0], _quat[1], _quat[2], _quat[3]);
00468 }
00469 }
00470
00475 template <class ValueTypeT> inline
00476 void QuaternionBase<ValueTypeT>::setValueAsQuat(const Char8 *str)
00477 {
00478 UInt32 i;
00479 UInt32 numOfToken = 4;
00480
00481 Char8 *c = const_cast<Char8 *>(str);
00482
00483 Char8 *tokenC = 0;
00484 Char8 token[256];
00485
00486 ValueTypeT vec[4];
00487
00488 if( (str == NULL) ||
00489 (*str == '\0') )
00490 {
00491 setIdentity();
00492 return;
00493 }
00494
00495 for(i = 0; i < numOfToken; c++)
00496 {
00497 switch (*c)
00498 {
00499 case '\0':
00500 if (tokenC)
00501 {
00502 *tokenC = 0;
00503 vec[i++] = TypeTraits<ValueTypeT>::getFromString(token);
00504
00505 }
00506
00507 while (i < numOfToken)
00508 {
00509 vec[i++] = TypeTraits<ValueTypeT>::getZeroElement();
00510 }
00511
00512 break;
00513 case ' ' :
00514 case '\t':
00515 case '\n':
00516 if (tokenC)
00517 {
00518 *tokenC = 0;
00519 vec[i++] = TypeTraits<ValueTypeT>::getFromString(token);
00520 tokenC = 0;
00521 }
00522 break;
00523 default:
00524 if (!tokenC)
00525 {
00526 tokenC = token;
00527 }
00528 *tokenC++ = *c;
00529 break;
00530 }
00531 }
00532
00533 _quat[0] = vec[0];
00534 _quat[1] = vec[1];
00535 _quat[2] = vec[2];
00536 _quat[3] = vec[3];
00537 }
00538
00540
00541 template <class ValueTypeT> inline
00542 void QuaternionBase<ValueTypeT>::setValue(const ValueTypeT alpha,
00543 const ValueTypeT beta,
00544 const ValueTypeT gamma)
00545 {
00546 ValueTypeT sx = osgsin(alpha * 0.5f);
00547 ValueTypeT cx = osgcos(alpha * 0.5f);
00548
00549 ValueTypeT sy = osgsin(beta * 0.5f);
00550 ValueTypeT cy = osgcos(beta * 0.5f);
00551
00552 ValueTypeT sz = osgsin(gamma * 0.5f);
00553 ValueTypeT cz = osgcos(gamma * 0.5f);
00554
00555 _quat[0] = (sx * cy * cz) - (cx * sy * sz);
00556 _quat[1] = (cx * sy * cz) + (sx * cy * sz);
00557 _quat[2] = (cx * cy * sz) - (sx * sy * cz);
00558 _quat[3] = (cx * cy * cz) + (sx * sy * sz);
00559 }
00560
00561
00562
00563
00565
00566 template <class ValueTypeT> inline
00567 const ValueTypeT *QuaternionBase<ValueTypeT>::getValues(void) const
00568 {
00569 return _quat;
00570 }
00571
00576 template <class ValueTypeT> inline
00577 void QuaternionBase<ValueTypeT>::getValueAsAxisRad(ValueTypeT &x,
00578 ValueTypeT &y,
00579 ValueTypeT &z,
00580 ValueTypeT &w) const
00581 {
00582 getValueAsAxisDeg(x, y, z, w);
00583
00584 w = osgdegree2rad(w);
00585 }
00586
00591 template <class ValueTypeT> inline
00592 void QuaternionBase<ValueTypeT>::getValueAsAxisDeg(ValueTypeT &x,
00593 ValueTypeT &y,
00594 ValueTypeT &z,
00595 ValueTypeT &w) const
00596 {
00597 ValueTypeT len;
00598
00599 VectorType q(_quat[0], _quat[1], _quat[2]);
00600
00601 len = q.length();
00602
00603 if(len > Eps)
00604 {
00605 q *= (TypeTraits<ValueTypeT>::getOneElement() / len);
00606
00607 x = q[0];
00608 y = q[1];
00609 z = q[2];
00610
00611 w = osgrad2degree(2.0f * osgacos(_quat[3]));
00612 }
00613 else
00614 {
00615 x = TypeTraits<ValueTypeT>::getZeroElement();
00616 y = TypeTraits<ValueTypeT>::getZeroElement();
00617 z = TypeTraits<ValueTypeT>::getOneElement();
00618
00619 w = TypeTraits<ValueTypeT>::getZeroElement();
00620 }
00621 }
00622
00624
00625 template <class ValueTypeT> inline
00626 void QuaternionBase<ValueTypeT>::getValueAsQuat(ValueTypeT &x,
00627 ValueTypeT &y,
00628 ValueTypeT &z,
00629 ValueTypeT &w) const
00630 {
00631 x = _quat[0];
00632 y = _quat[1];
00633 z = _quat[2];
00634 w = _quat[3];
00635 }
00636
00638
00639 template <class ValueTypeT> inline
00640 void QuaternionBase<ValueTypeT>::getValueAsAxisRad(VectorType &axis,
00641 ValueTypeT &radians) const
00642 {
00643 ValueTypeT x;
00644 ValueTypeT y;
00645 ValueTypeT z;
00646 ValueTypeT w;
00647
00648 getValueAsAxisRad(x, y, z, w);
00649
00650 axis.setValues(x, y, z);
00651
00652 radians = w;
00653 }
00654
00656
00657 template <class ValueTypeT> inline
00658 void QuaternionBase<ValueTypeT>::getValueAsAxisDeg(VectorType &axis,
00659 ValueTypeT °rees) const
00660 {
00661 ValueTypeT x;
00662 ValueTypeT y;
00663 ValueTypeT z;
00664 ValueTypeT w;
00665
00666 getValueAsAxisDeg(x, y, z, w);
00667
00668 axis.setValues(x, y, z);
00669
00670 degrees = w;
00671 }
00672
00674
00675 template <class ValueTypeT> inline
00676 void QuaternionBase<ValueTypeT>::getValue(MatrixType &matrix) const
00677 {
00678 getValuesOnly(matrix);
00679
00680 matrix[0][3] = 0.0f;
00681 matrix[1][3] = 0.0f;
00682 matrix[2][3] = 0.0f;
00683
00684 matrix[3][0] = 0.0f;
00685 matrix[3][1] = 0.0f;
00686 matrix[3][2] = 0.0f;
00687 matrix[3][3] = 1.0f;
00688 }
00689
00691
00692 template <class ValueTypeT> inline
00693 void QuaternionBase<ValueTypeT>::getValuesOnly(MatrixType &matrix) const
00694 {
00695 matrix[0][0] = 1.0f - 2.0f * (_quat[Q_Y] * _quat[Q_Y] +
00696 _quat[Q_Z] * _quat[Q_Z]);
00697 matrix[0][1] = 2.0f * (_quat[Q_X] * _quat[Q_Y] +
00698 _quat[Q_Z] * _quat[Q_W]);
00699 matrix[0][2] = 2.0f * (_quat[Q_Z] * _quat[Q_X] -
00700 _quat[Q_Y] * _quat[Q_W]);
00701
00702 matrix[1][0] = 2.0f * (_quat[Q_X] * _quat[Q_Y] -
00703 _quat[Q_Z] * _quat[Q_W]);
00704 matrix[1][1] = 1.0f - 2.0f * (_quat[Q_Z] * _quat[Q_Z] +
00705 _quat[Q_X] * _quat[Q_X]);
00706 matrix[1][2] = 2.0f * (_quat[Q_Y] * _quat[Q_Z] +
00707 _quat[Q_X] * _quat[Q_W]);
00708
00709 matrix[2][0] = 2.0f * (_quat[Q_Z] * _quat[Q_X] +
00710 _quat[Q_Y] * _quat[Q_W]);
00711 matrix[2][1] = 2.0f * (_quat[Q_Y] * _quat[Q_Z] -
00712 _quat[Q_X] * _quat[Q_W]);
00713 matrix[2][2] = 1.0f - 2.0f * (_quat[Q_Y] * _quat[Q_Y] +
00714 _quat[Q_X] * _quat[Q_X]);
00715 }
00716
00717 template <class ValueTypeT> inline
00718 ValueTypeT QuaternionBase<ValueTypeT>::x(void) const
00719 {
00720 return _quat[0];
00721 }
00722
00723 template <class ValueTypeT> inline
00724 ValueTypeT QuaternionBase<ValueTypeT>::y(void) const
00725 {
00726 return _quat[1];
00727 }
00728
00729 template <class ValueTypeT> inline
00730 ValueTypeT QuaternionBase<ValueTypeT>::z(void) const
00731 {
00732 return _quat[2];
00733 }
00734
00735 template <class ValueTypeT> inline
00736 ValueTypeT QuaternionBase<ValueTypeT>::w(void) const
00737 {
00738 return _quat[3];
00739 }
00740
00741
00742
00743
00745
00746 template <class ValueTypeT> inline
00747 ValueTypeT QuaternionBase<ValueTypeT>::length(void) const
00748 {
00749 return osgsqrt(_quat[0] * _quat[0] +
00750 _quat[1] * _quat[1] +
00751 _quat[2] * _quat[2] +
00752 _quat[3] * _quat[3]);
00753 }
00754
00756
00757 template <class ValueTypeT> inline
00758 void QuaternionBase<ValueTypeT>::normalize(void)
00759 {
00760 ValueTypeT rLength = length();
00761
00762 if(osgabs(rLength) < Eps)
00763 {
00764 rLength = TypeTraits<ValueTypeT>::getOneElement();
00765 }
00766 else
00767 {
00768 rLength = TypeTraits<ValueTypeT>::getOneElement() / rLength;
00769 }
00770
00771 for(UInt32 i = 0; i < 4; i++)
00772 {
00773 _quat[i] *= rLength;
00774 }
00775 }
00776
00778
00779 template <class ValueTypeT> inline
00780 void QuaternionBase<ValueTypeT>::invert(void)
00781 {
00782 _quat[0] = -_quat[0];
00783 _quat[1] = -_quat[1];
00784 _quat[2] = -_quat[2];
00785
00786 }
00787
00789
00790 template <class ValueTypeT> inline
00791 const QuaternionBase<ValueTypeT>QuaternionBase<ValueTypeT>::inverse(void) const
00792 {
00793 QuaternionBase returnValue(*this);
00794
00795 returnValue.invert();
00796
00797 return returnValue;
00798 }
00799
00801
00802
00803
00804
00805
00806 template <class ValueTypeT> inline
00807 void QuaternionBase<ValueTypeT>::multVec(const VectorType &src,
00808 VectorType &dst) const
00809 {
00810 ValueTypeT rx,ry,rz;
00811 ValueTypeT QwQx, QwQy, QwQz, QxQy, QxQz, QyQz;
00812
00813 QwQx = _quat[3] * _quat[0];
00814 QwQy = _quat[3] * _quat[1];
00815 QwQz = _quat[3] * _quat[2];
00816 QxQy = _quat[0] * _quat[1];
00817 QxQz = _quat[0] * _quat[2];
00818 QyQz = _quat[1] * _quat[2];
00819
00820 ValueTypeT Vx = src[0], Vy = src[1], Vz = src[2];
00821
00822 rx = 2* (Vy * (-QwQz + QxQy) + Vz *( QwQy + QxQz));
00823 ry = 2* (Vx * ( QwQz + QxQy) + Vz *(-QwQx + QyQz));
00824 rz = 2* (Vx * (-QwQy + QxQz) + Vy *( QwQx + QyQz));
00825
00826 ValueTypeT QwQw, QxQx, QyQy, QzQz;
00827
00828 QwQw = _quat[3] * _quat[3];
00829 QxQx = _quat[0] * _quat[0];
00830 QyQy = _quat[1] * _quat[1];
00831 QzQz = _quat[2] * _quat[2];
00832
00833 rx+= Vx * (QwQw + QxQx - QyQy - QzQz);
00834 ry+= Vy * (QwQw - QxQx + QyQy - QzQz);
00835 rz+= Vz * (QwQw - QxQx - QyQy + QzQz);
00836
00837 dst.setValues(rx,ry,rz);
00838 }
00839
00844 template <class ValueTypeT> inline
00845 void QuaternionBase<ValueTypeT>::scaleAngle(ValueTypeT scaleFactor)
00846 {
00847 VectorType axis;
00848 ValueTypeT radians;
00849
00850 getValueAsAxisRad(axis, radians);
00851 setValueAsAxisRad(axis, radians * scaleFactor);
00852 }
00853
00854 template <class ValueTypeT> inline
00855 void QuaternionBase<ValueTypeT>::slerpThis(const QuaternionBase &rot0,
00856 const QuaternionBase &rot1,
00857 const ValueTypeT t)
00858 {
00859 slerp(rot0, rot1, *this, t);
00860 }
00861
00862 template <class ValueTypeT> inline
00863 void QuaternionBase<ValueTypeT>::mult(const QuaternionBase &other)
00864 {
00865 mult(_quat, other._quat);
00866 }
00867
00868 template <class ValueTypeT> inline
00869 void QuaternionBase<ValueTypeT>::multLeft(const QuaternionBase &other)
00870 {
00871 mult(other._quat, _quat);
00872 }
00873
00874 template <class ValueTypeT> inline
00875 bool QuaternionBase<ValueTypeT>::equals(const QuaternionBase &rot,
00876 const ValueTypeT tolerance) const
00877 {
00878 bool returnValue = true;
00879
00880 for(UInt32 i = 0; i < 4; i++)
00881 {
00882 returnValue &= ( ( _quat[i] - rot._quat[i] <= tolerance) &&
00883 (rot._quat[i] - _quat[i] <= tolerance));
00884 }
00885
00886 return returnValue;
00887 }
00888
00889
00890
00891
00892 template <class ValueTypeT> inline
00893 ValueTypeT &QuaternionBase<ValueTypeT>::operator [](const UInt32 index)
00894 {
00895 return _quat[index];
00896 }
00897
00898 template <class ValueTypeT> inline
00899 const ValueTypeT &QuaternionBase<ValueTypeT>::operator [](
00900 const UInt32 index) const
00901 {
00902 return _quat[index];
00903 }
00904
00905
00906
00907
00908 template <class ValueTypeT> inline
00909 void QuaternionBase<ValueTypeT>::operator *=(const QuaternionBase &other)
00910 {
00911 mult(_quat, other._quat);
00912 }
00913
00914
00915
00916
00917 template <class ValueTypeT> inline
00918 const QuaternionBase<ValueTypeT> &
00919 QuaternionBase<ValueTypeT>::operator =(const QuaternionBase &source)
00920 {
00921 if (this == &source)
00922 return *this;
00923
00924 for(UInt32 i = 0; i < 4; i++)
00925 {
00926 _quat[i] = source._quat[i];
00927 }
00928
00929 return *this;
00930 }
00931
00932
00933
00934
00935 template <class ValueTypeT> inline
00936 bool QuaternionBase<ValueTypeT>::operator ==(const QuaternionBase &other) const
00937 {
00938 return equals(other, Eps);
00939 }
00940
00941 template <class ValueTypeT> inline
00942 bool QuaternionBase<ValueTypeT>::operator !=(const QuaternionBase &other) const
00943 {
00944 return ! (*this == other);
00945 }
00946
00947
00948
00949
00951
00952 template <class ValueTypeT> inline
00953 void QuaternionBase<ValueTypeT>::slerp(const QuaternionBase &rot0,
00954 const QuaternionBase &rot1,
00955 QuaternionBase &result,
00956 const ValueTypeT t )
00957 {
00958 ValueTypeT rot1q[4];
00959
00960 Real64 omega;
00961 Real64 cosom;
00962 Real64 sinom;
00963 Real64 scalerot0;
00964 Real64 scalerot1;
00965
00966 UInt32 i;
00967 UInt32 j;
00968
00969
00970 cosom =
00971 rot0._quat[0] * rot1._quat[0] +
00972 rot0._quat[1] * rot1._quat[1] +
00973 rot0._quat[2] * rot1._quat[2] +
00974 rot0._quat[3] * rot1._quat[3];
00975
00976
00977 if(cosom < 0.0)
00978 {
00979 cosom = -cosom;
00980
00981 for(j = 0; j < 4; j++)
00982 {
00983 rot1q[j] = -rot1[j];
00984 }
00985 }
00986 else
00987 {
00988 for(j = 0; j < 4; j++)
00989 {
00990 rot1q[j] = rot1[j];
00991 }
00992 }
00993
00994
00995 if ((1.0 - cosom) > 0.00001)
00996 {
00997
00998 omega = osgacos(cosom);
00999 sinom = osgsin(omega);
01000 scalerot0 = osgsin((1.0 - t) * omega) / sinom;
01001 scalerot1 = osgsin(t * omega) / sinom;
01002 }
01003 else
01004 {
01005
01006 scalerot0 = 1.0 - t;
01007 scalerot1 = t;
01008 }
01009
01010
01011 for (i = 0; i < 4; i++)
01012 result[i] = (ValueTypeT) (scalerot0 * rot0._quat[i] +
01013 scalerot1 * rot1q[i]);
01014 }
01019 template <class ValueTypeT> inline
01020 void QuaternionBase<ValueTypeT>::mult(const ValueTypeT rVal1[4],
01021 const ValueTypeT rVal2[4])
01022 {
01023 ValueTypeT s1, s2, s3, s4, s5, s6, s7, s8, s9, t;
01024
01025 s1 = (rVal1[2] - rVal1[1]) * (rVal2[1] - rVal2[2]);
01026 s2 = (rVal1[3] + rVal1[0]) * (rVal2[3] + rVal2[0]);
01027 s3 = (rVal1[3] - rVal1[0]) * (rVal2[1] + rVal2[2]);
01028 s4 = (rVal1[2] + rVal1[1]) * (rVal2[3] - rVal2[0]);
01029 s5 = (rVal1[2] - rVal1[0]) * (rVal2[0] - rVal2[1]);
01030 s6 = (rVal1[2] + rVal1[0]) * (rVal2[0] + rVal2[1]);
01031 s7 = (rVal1[3] + rVal1[1]) * (rVal2[3] - rVal2[2]);
01032 s8 = (rVal1[3] - rVal1[1]) * (rVal2[3] + rVal2[2]);
01033
01034 s9 = s6 + s7 + s8;
01035
01036 t = (s5 + s9) / 2.0f;
01037
01038 _quat[3] = s1 + t - s6;
01039 _quat[0] = s2 + t - s9;
01040 _quat[1] = s3 + t - s8;
01041 _quat[2] = s4 + t - s7;
01042
01043 normalize();
01044 }
01045
01046
01047
01048
01049 template <class ValueTypeT> inline
01050 std::ostream &operator <<( std::ostream &os,
01051 const QuaternionBase<ValueTypeT> &obj)
01052 {
01053 #ifdef OSG_SGI_STL
01054 os << std::fixed
01055 << std::showpoint
01056 << std::setprecision(3)
01057 << std::setfill(' ');
01058 #else
01059 os << std::setprecision(3) << std::setfill(' ');
01060 #endif
01061
01062 return os << std::setw(8)
01063 << obj.x() << " "
01064 << obj.y() << " "
01065 << obj.z() << " "
01066 << obj.w();
01067 }
01068
01069 OSG_END_NAMESPACE
01070
01071 #define OSGQUATERNION_INLINE_CVSID "@(#)$Id: $"