00001
00002
00003
00004
00005
00006
00007
00008 #ifndef _Quaternion_H_
00009 #define _Quaternion_H_
00010
00011 #include <algorithm>
00012 #include <cassert>
00013 #include <cmath>
00014 #include <cstdlib>
00015 #include <iomanip>
00016 #include <iostream>
00017 #include <limits>
00018
00019 #include <vmmlib/vector3.h>
00020 #include <vmmlib/vector4.h>
00021 #include <vmmlib/matrix3.h>
00022
00023
00024
00025 #define QUATERNION_DEBUG 1
00026
00027 #define QUATERNION_TRACE_EPSILON 1e-5
00028
00029 namespace vmml
00030 {
00031
00032 template < typename T >
00033 class Quaternion
00034 {
00035 public:
00036 union
00037 {
00038 struct
00039 {
00040 T w, x, y, z;
00041 };
00042 struct
00043 {
00044 T s, t, u, v;
00045 };
00046 T wxyz [4];
00047 T stuv [4];
00048 };
00049
00050
00051 Quaternion();
00052 Quaternion( const T a );
00053 Quaternion( const T r, const T i, const T j, const T k );
00054 Quaternion( const T& real, const Vector3< T >& imag );
00055 Quaternion( const Vector3< T >& v );
00056
00057 Quaternion( const Matrix3< T >& m);
00058
00059
00060
00061
00062 Quaternion( const float* values );
00063 Quaternion( const double* values );
00064
00065 ~Quaternion();
00066
00067 void set( T ww, T xx, T yy, T zz);
00068
00069
00070
00071 void set( const float* values );
00072 void set( const double* values );
00073
00074 const Quaternion& operator=( T a );
00075 const Quaternion& operator=(const Quaternion& a);
00076
00077 bool operator==( const T& a ) const;
00078 bool operator!=( const T& a ) const;
00079
00080 bool operator==( const Quaternion& a ) const;
00081 bool operator!=( const Quaternion& a ) const;
00082 bool isAkin( const Quaternion& a,
00083 const T& delta = std::numeric_limits<T>::epsilon() );
00084
00085 T& operator[](size_t position);
00086 const T& operator[](size_t position) const;
00087
00088
00089
00090 Quaternion conjug() const;
00091 T abs() const;
00092 T absSquared() const;
00093
00094 T normalize();
00095 static T normalize( float* source );
00096
00097 T normalise();
00098 static T normalise( float* source );
00099
00100 void scale( T scale_factor );
00101
00102
00103
00104 Quaternion operator+( const T a ) const;
00105 Quaternion operator-( const T a ) const;
00106 Quaternion operator*( const T a ) const;
00107 Quaternion operator/( T a ) const;
00108
00109 const Quaternion& operator+=( T a );
00110 const Quaternion& operator-=( T a );
00111 const Quaternion& operator*=( T a );
00112 const Quaternion& operator/=( T a );
00113
00114
00115 Quaternion operator+( const Vector3< T >& a ) const;
00116 Quaternion operator-( const Vector3< T >& a ) const;
00117
00118 Quaternion operator*( const Vector3< T >& a ) const;
00119
00120
00121 const Quaternion& operator+=( const Vector3< T >& a );
00122 const Quaternion& operator-=( const Vector3< T >& a );
00123
00124 const Quaternion& operator*=( const Vector3< T >& a );
00125
00126
00127 Quaternion operator+( const Quaternion< T >& a ) const;
00128 Quaternion operator-( const Quaternion< T >& a ) const;
00129
00130 Quaternion operator*( const Quaternion< T >& a ) const;
00131 Quaternion operator-() const;
00132
00133 const Quaternion& operator+=( const Quaternion< T >& a );
00134 const Quaternion& operator-=( const Quaternion< T >& a );
00135
00136 const Quaternion& operator*=( const Quaternion< T >& a );
00137
00138 Vector3< T > cross( const Quaternion< T >& a ) const;
00139 Quaternion cross( const Quaternion< T >& a, const Quaternion< T >& b ) const;
00140 void cross( const Quaternion< T >& a, const Quaternion< T >& b );
00141 T dot( const Quaternion< T >& a ) const;
00142 static T dot( const Quaternion< T >& a, const Quaternion< T >& b );
00143
00144
00145 Quaternion invert();
00146
00147 void normal( const Quaternion& aa, const Quaternion& bb, const Quaternion& cc, const Quaternion& dd );
00148 Quaternion normal( const Quaternion& aa, const Quaternion& bb, const Quaternion& cc );
00149
00150
00151
00152 void rotate( T theta, const Vector3< T >& a );
00153 void rotatex( T theta );
00154 void rotatey( T theta );
00155 void rotatez( T theta );
00156 Quaternion rotate( T theta, Vector3< T >& axis, const Vector3< T >& a );
00157 Quaternion rotatex( T theta, const Vector3< T >& a );
00158 Quaternion rotatey( T theta, const Vector3< T >& a );
00159 Quaternion rotatez( T theta, const Vector3< T >& a );
00160
00161 Quaternion slerp( T a, Quaternion< T >& p, Quaternion& q );
00162
00163 T getMinComponent();
00164 T getMaxComponent();
00165
00166 Matrix3< T > getRotationMatrix() const;
00167
00168 friend std::ostream& operator << ( std::ostream& os, const Quaternion& q )
00169 {
00170 const std::ios::fmtflags flags = os.flags();
00171 const int prec =os.precision();
00172
00173 os. setf( std::ios::right, std::ios::adjustfield );
00174 os.precision( 5 );
00175 os << "[" << std::setw(10) << q.w << " " << std::setw(10) << q.x
00176 << " " << std::setw(10) << q.y << " " << std::setw(10) << q.z << " ]";
00177 os.precision( prec );
00178 os.setf( flags );
00179 return os;
00180 };
00181
00182 static const Quaternion ZERO;
00183 static const Quaternion IDENTITY;
00184 static const Quaternion QUATERI;
00185 static const Quaternion QUATERJ;
00186 static const Quaternion QUATERK;
00187
00188 };
00189
00190 typedef Quaternion<float> Quaternionf;
00191 typedef Quaternion<double> Quaterniond;
00192
00193
00194
00195 template < typename T >
00196 const Quaternion< T > Quaternion< T >::ZERO( 0, 0, 0, 0 );
00197
00198 template < typename T >
00199 const Quaternion< T > Quaternion< T >::IDENTITY( 1, 0, 0, 0 );
00200
00201 template < typename T >
00202 const Quaternion< T > Quaternion< T >::QUATERI( 0, 1, 0, 0 );
00203
00204 template < typename T >
00205 const Quaternion< T > Quaternion< T >::QUATERJ( 0, 0, 1, 0 );
00206
00207 template < typename T >
00208 const Quaternion< T > Quaternion< T >::QUATERK( 0, 0, 0, 1 );
00209
00210 template < typename T >
00211 Quaternion< T >::Quaternion()
00212 {}
00213
00214 template < typename T >
00215 Quaternion< T >::Quaternion( const T a )
00216 : w(a)
00217 , x(a)
00218 , y(a)
00219 , z(a)
00220 {}
00221
00222 template < typename T >
00223 Quaternion< T >::Quaternion( const T r, const T i, const T j, const T k )
00224 : w(r)
00225 , x(i)
00226 , y(j)
00227 , z(k)
00228 {}
00229
00230 template < typename T >
00231 Quaternion< T >::Quaternion( const T& real, const Vector3< T >& imag )
00232 {
00233 w = real;
00234 x = imag.x;
00235 y = imag.y;
00236 z = imag.z;
00237 }
00238
00239 template < typename T >
00240 Quaternion< T >::Quaternion( const Vector3< T >& v3 )
00241 {
00242 w = 0;
00243 x = v3.x;
00244 y = v3.y;
00245 z = v3.z;
00246 }
00247
00248
00249 template < typename T >
00250 Quaternion< T >::Quaternion( const Matrix3< T >& matrix )
00251 {
00252 T trace = matrix.m00 + matrix.m11 + matrix.m22 + 1.;
00253
00254 if( trace > QUATERNION_TRACE_EPSILON )
00255 {
00256 T s1 = 0.5 / sqrt(trace);
00257 w = 0.25 / s1;
00258 x = ( matrix.m21 - matrix.m12 ) * s1;
00259 y = ( matrix.m02 - matrix.m20 ) * s1;
00260 z = ( matrix.m10 - matrix.m01 ) * s1;
00261 }
00262 else
00263
00264 if ( matrix.m00 > matrix.m11 && matrix.m00 > matrix.m22 )
00265 {
00266 T s1 = 0.5 / sqrt( 1. + matrix.m00 - matrix.m11 - matrix.m22);
00267 w = ( matrix.m12 - matrix.m21 ) * s1;
00268 x = 0.25 / s;
00269 y = ( matrix.m01 + matrix.m10 ) * s1;
00270 z = ( matrix.m02 + matrix.m20 ) * s1;
00271 }
00272 else
00273
00274 if (matrix.m11 > matrix.m22)
00275 {
00276 T s1 = 0.5 / sqrt( 1. + matrix.m11 - matrix.m00 - matrix.m22);
00277 w = ( matrix.m02 - matrix.m20 ) * s1;
00278 x = ( matrix.m01 + matrix.m10 ) * s1;
00279 y = 0.25 / s1;
00280 z = ( matrix.m12 + matrix.m21 ) * s1;
00281 }
00282
00283 else
00284 {
00285 T s1 = 0.5 / sqrt( 1. + matrix.m22 - matrix.m00 - matrix.m11 );
00286 w = ( matrix.m01 - matrix.m10 ) * s1;
00287 x = ( matrix.m02 + matrix.m20 ) * s1;
00288 y = ( matrix.m12 + matrix.m21 ) * s1;
00289 z = 0.25 / s1;
00290 }
00291 }
00292
00293
00294
00295 template < typename T >
00296 Quaternion< T >::Quaternion( const float* values )
00297 {
00298 assert( values && "Quaternion: Nullpointer argument as Source for initialisation!" );
00299 w = static_cast< T > ( values[0] );
00300 x = static_cast< T > ( values[1] );
00301 y = static_cast< T > ( values[2] );
00302 z = static_cast< T > ( values[3] );
00303 }
00304
00305 template < typename T >
00306 Quaternion< T >::Quaternion( const double* values )
00307 {
00308 assert( values && "Quaternion: Nullpointer argument as Source for initialisation!" );
00309 w = static_cast< T > ( values[0] );
00310 x = static_cast< T > ( values[1] );
00311 y = static_cast< T > ( values[2] );
00312 z = static_cast< T > ( values[3] );
00313 }
00314
00315 template < typename T >
00316 Quaternion< T >::~Quaternion()
00317 {}
00318
00319 template < typename T >
00320 void Quaternion< T >::set( T ww, T xx, T yy, T zz )
00321 {
00322 w = ww;
00323 x = xx;
00324 y = yy;
00325 z = zz;
00326 }
00327
00328 template < typename T >
00329 void Quaternion< T >::set( const float* values )
00330 {
00331 assert( values && "Quaternion: Nullpointer argument as source for initialisation!" );
00332 w = static_cast< T > ( values[0] );
00333 x = static_cast< T > ( values[1] );
00334 y = static_cast< T > ( values[2] );
00335 z = static_cast< T > ( values[3] );
00336 }
00337
00338 template < typename T >
00339 void Quaternion< T >::set( const double* values )
00340 {
00341 assert( values && "Quaternion: Nullpointer argument as source for initialisation!" );
00342 w = static_cast< T > ( values[0] );
00343 x = static_cast< T > ( values[1] );
00344 y = static_cast< T > ( values[2] );
00345 z = static_cast< T > ( values[3] );
00346 }
00347
00348 template < typename T >
00349 const Quaternion< T >& Quaternion< T >::operator=( T a )
00350 {
00351 w = a;
00352 x = 0;
00353 y = 0;
00354 z = 0;
00355 return *this;
00356 }
00357
00358 template < typename T >
00359 const Quaternion< T >& Quaternion < T >::operator=( const Quaternion& a )
00360 {
00361 w = a.w;
00362 x = a.x;
00363 y = a.y;
00364 z = a.z;
00365 return *this;
00366 }
00367
00368 template < typename T >
00369 bool Quaternion< T >::operator==( const T& a ) const
00370 {
00371 return ( w == a && x == 0 && y == 0 && z == 0 );
00372 }
00373
00374 template < typename T >
00375 bool Quaternion< T >::operator!=( const T& a ) const
00376 {
00377 return ( w != a ||x != 0 || y != 0 || z != 0 );
00378 }
00379
00380 template < typename T >
00381 bool Quaternion< T >::operator==( const Quaternion& a ) const
00382 {
00383 return ( w == a.w && x == a.x && y == a.y && z == a.z );
00384 }
00385
00386 template < typename T >
00387 bool Quaternion< T >::operator!=( const Quaternion& a ) const
00388 {
00389 return ( w != a.w || x != a.x || y != a.y || z != a.z );
00390 }
00391
00392 template < typename T >
00393 bool Quaternion< T >::isAkin( const Quaternion& a, const T& delta )
00394 {
00395 if( fabsf( w - a.w ) > delta || fabsf( x - a.x ) > delta ||
00396 fabsf( y - a.y ) > delta || fabsf ( z - a.z ) > delta )
00397 return false;
00398 return true;
00399 }
00400
00401 template < typename T >
00402 T& Quaternion< T >::operator[]( size_t index )
00403 {
00404 assert( index < 4 && "Quaternion::operator[] Invalid component index!" );
00405 return wxyz[ index ];
00406 }
00407
00408 template < typename T >
00409 const T& Quaternion< T >::operator[]( size_t index ) const
00410 {
00411 assert( index < 4 && "Quaternion::operator[] Invalid component index!" );
00412 return wxyz[ index ];
00413 }
00414
00415 template < typename T >
00416 Quaternion< T > Quaternion< T >::conjug() const
00417 {
00418 return Quaternion< T > ( w, -x, -y, -z );
00419 }
00420
00421 template < typename T >
00422 T Quaternion< T >::abs() const
00423 {
00424 T sq = w * w + x * x + y * y + z * z;
00425 return sqrt( sq );
00426 }
00427
00428 template < typename T >
00429 T Quaternion< T >::absSquared() const
00430 {
00431 T sum = w * w + x * x + y * y + z * z;
00432 return sum;
00433 }
00434
00435
00436
00437 template < typename T >
00438 Quaternion< T > Quaternion< T >::invert()
00439 {
00440 Quaternion< T > q = conjug();
00441 T square = absSquared();
00442 square = 1.0f / square;
00443 return q * square;
00444 }
00445
00446 template < typename T >
00447 T Quaternion< T >::normalise()
00448 {
00449 T l = abs();
00450 if( l == 0 )
00451 return 0;
00452 l = 1.0f / l;
00453 w *= l;
00454 x *= l;
00455 y *= l;
00456 z *= l;
00457 return l;
00458 }
00459
00460
00461 template < typename T >
00462 T Quaternion< T >::normalise( float* source )
00463 {
00464 Quaternion< float >* a = ( Quaternion< float >* ) source;
00465 T l = a->abs();
00466 if ( l == 0 )
00467 return 0;
00468
00469 l = 1.0f / l;
00470 source[0] *= l;
00471 source[1] *= l;
00472 source[2] *= l;
00473 source[3] *= l;
00474 return l;
00475 }
00476
00477
00478
00479
00480 template < typename T >
00481 T Quaternion< T >::normalize()
00482 {
00483 T l = abs();
00484 if( l == 0 )
00485 return 0;
00486 l = 1.0f / l;
00487 w *= l;
00488 x *= l;
00489 y *= l;
00490 z *= l;
00491 return l;
00492 }
00493
00494
00495
00496
00497 template < typename T >
00498 T Quaternion< T >::normalize( float* source )
00499 {
00500 Quaternion< float >* a = ( Quaternion< float >* ) source;
00501 T l = a->abs();
00502 if ( l == 0 )
00503 return 0;
00504
00505 l = 1.0f / l;
00506 source[0] *= l;
00507 source[1] *= l;
00508 source[2] *= l;
00509 source[3] *= l;
00510 return l;
00511 }
00512
00513
00514 template < typename T >
00515 Quaternion< T > Quaternion< T >::operator+( const T a ) const
00516 {
00517 return Quaternion( w + a, x, y, z );
00518 }
00519
00520 template < typename T >
00521 Quaternion< T > Quaternion< T >::operator-( const T a ) const
00522 {
00523 return Quaternion( w - a, x, y, z );
00524 }
00525
00526 template < typename T >
00527 Quaternion< T > Quaternion< T >::operator*( const T a ) const
00528 {
00529 return Quaternion( w * a, x * a, y * a, z * a );
00530 }
00531
00532 template < typename T >
00533 Quaternion< T > Quaternion< T >::operator/( T a ) const
00534 {
00535 assert( a != 0.0f );
00536 a = 1.0f / a;
00537 return Quaternion( w * a, x * a, y * a, z * a );
00538 }
00539
00540 template < typename T >
00541 const Quaternion< T >& Quaternion< T >::operator+=( T a )
00542 {
00543 w += a;
00544 return Quaternion( w, x, y, z );
00545 }
00546
00547 template < typename T >
00548 const Quaternion< T >& Quaternion< T >::operator-=( T a )
00549 {
00550 w -= a;
00551 return *this;
00552 }
00553
00554 template < typename T >
00555 const Quaternion< T >& Quaternion< T >::operator*=( T a )
00556 {
00557 w *= a;
00558 x *= a;
00559 y *= a;
00560 z *= a;
00561 return *this;
00562 }
00563
00564 template < typename T >
00565 const Quaternion< T >& Quaternion< T >::operator/=( T a )
00566 {
00567 assert( a != 0.0f );
00568 a = 1.0f / a;
00569 w *= a;
00570 x *= a;
00571 y *= a;
00572 z *= a;
00573 return *this;
00574 }
00575
00576
00577 template < typename T >
00578 Quaternion< T > Quaternion< T >::operator+( const Vector3< T >& a ) const
00579 {
00580 return Quaternion( w, x + a.x, y + a.y, z + a.z );
00581 }
00582
00583 template < typename T >
00584 Quaternion< T > Quaternion< T >::operator-( const Vector3< T >& a ) const
00585 {
00586 return Quaternion( w, x - a.x, y - a.y, z - a.z );
00587 }
00588
00589 template < typename T >
00590 Quaternion< T > Quaternion< T >::operator*( const Vector3< T >& a ) const
00591 {
00592 return Quaternion( -x * a.x - y * a.y - z * a.z,
00593 w * a.x + y * a.z - z * a.y,
00594 w * a.y + z * a.x - x * a.z,
00595 w * a.z + x * a.y - y * a.x );
00596 }
00597
00598 template < typename T >
00599 const Quaternion< T >& Quaternion< T >::operator+=( const Vector3< T >& a )
00600 {
00601 x += a.x;
00602 y += a.y;
00603 z += a.z;
00604 return *this;
00605 }
00606
00607 template < typename T >
00608 const Quaternion< T >& Quaternion< T >::operator-=( const Vector3< T >& a )
00609 {
00610 x -= a.x;
00611 y -= a.y;
00612 z -= a.z;
00613 return *this;
00614 }
00615
00616 template < typename T >
00617 const Quaternion< T >& Quaternion< T >::operator*=(const Vector3< T >& a )
00618 {
00619 T ww = -x * a.x - y * a.y - z * a.z;
00620 T xx = w * a.x + y * a.z - z * a.y;
00621 T yy = w * a.y + z * a.x - x * a.z;
00622 T zz = w * a.z + x * a.y - y * a.x;
00623 w = ww;
00624 x = xx;
00625 y = yy;
00626 z = zz;
00627 return *this;
00628 }
00629
00630
00631 template < typename T >
00632 Quaternion< T > Quaternion< T >::operator+( const Quaternion< T >& a ) const
00633 {
00634 return Quaternion( w + a.w, x + a.x, y + a.y, z + a.z );
00635 }
00636
00637 template < typename T >
00638 Quaternion< T > Quaternion< T >::operator-( const Quaternion< T >& a ) const
00639 {
00640 return Quaternion( w - a.w, x - a.x, y - a.y, z - a.z );
00641 }
00642
00643
00644 template < typename T >
00645 Quaternion< T > Quaternion< T >::operator*( const Quaternion< T >& a ) const
00646 {
00647 return Quaternion( w * a.w - x * a.x - y * a.y - z * a.z,
00648 w * a.x + x * a.w + y * a.z - z * a.y,
00649 w * a.y + y * a.w + z * a.x - x * a.z,
00650 w * a.z + z * a.w + x * a.y - y * a.x );
00651 }
00652
00653 template < typename T >
00654 Quaternion< T > Quaternion< T >::operator-() const
00655 {
00656 return Quaternion( -w, -x, -y, -z );
00657 }
00658
00659
00660 template < typename T >
00661 const Quaternion< T >& Quaternion< T >::operator+=( const Quaternion< T >& a )
00662 {
00663 w += a.w;
00664 x += a.x;
00665 y += a.y;
00666 z += a.z;
00667 return *this;
00668 }
00669
00670 template < typename T >
00671 const Quaternion< T >& Quaternion< T >::operator-=( const Quaternion< T >& a )
00672 {
00673 w -= a.w;
00674 x -= a.x;
00675 y -= a.y;
00676 z -= a.z;
00677 return *this;
00678 }
00679
00680
00681 template < typename T >
00682 const Quaternion< T >& Quaternion< T >::operator*=( const Quaternion< T >& a )
00683 {
00684 T ww = w * a.w + x * a.x + y * a.y + z * a.z;
00685 T xx = w * a.x + x * a.w + y * a.z - z * a.y;
00686 T yy = w * a.y + y * a.w + z * a.x - x * a.z;
00687 T zz = w * a.z + z * a.w + x * a.y - y * a.x;
00688 w = ww;
00689 x = xx;
00690 y = yy;
00691 z = zz;
00692 return *this;
00693 }
00694
00695
00696 template < typename T >
00697 Vector3< T > Quaternion< T >::cross( const Quaternion< T >& a ) const
00698 {
00699 return Vector3< T >( 2 * ( y * a.z - z * a.y ), 2 * ( z * a.x - x * a.z ), 2 * ( x * a.y - y * a.x ) );
00700
00701 }
00702
00703
00704 template < typename T >
00705 Quaternion< T > Quaternion< T >::cross( const Quaternion< T >& a, const Quaternion< T >& b ) const
00706 {
00707 return Quaternion( x * a.y * b.z + y * a.z * b.x + z * a.x * b.y - z * a.y * b.x - y * a.x * b.z - x * a.z * b.y,
00708 w * a.y * b.z + y * a.z * b.w + z * a.w * b.y - z * a.y * b.w - y * a.w * b.z - w * a.z * b.y,
00709 w * a.x * b.z + x * a.z * b.w + z * a.w * b.x - z * a.x * b.w - x * a.w * b.z - w * a.z * b.x,
00710 w * a.x * b.y + x * a.y * b.w + y * a.w * b.x - y * a.x * b.w - x * a.w * b.y - w * a.y * b.x );
00711 }
00712
00713
00714 template < typename T >
00715 void Quaternion< T >:: cross( const Quaternion< T >& a, const Quaternion< T >& b )
00716 {
00717 T ww = x * a.y * b.z + y * a.z * b.x + z * a.x * b.y - z * a.y * b.x - y * a.x * b.z - x * a.z * b.y;
00718 T xx = w * a.y * b.z + y * a.z * b.w + z * a.w * b.y - z * a.y * b.w - y * a.w * b.z - w * a.z * b.y;
00719 T yy = w * a.x * b.z + x * a.z * b.w + z * a.w * b.x - z * a.x * b.w - x * a.w * b.z - w * a.z * b.x;
00720 T zz = w * a.x * b.y + x * a.y * b.w + y * a.w * b.x - y * a.x * b.w - x * a.w * b.y - w * a.y * b.x;
00721 w = ww;
00722 x = xx;
00723 y = yy;
00724 z = zz;
00725 }
00726
00727 template < typename T >
00728 T Quaternion< T >::dot( const Quaternion< T >& a ) const
00729 {
00730 return w * a.w + x * a.x + y * a.y + z * a.z;
00731 }
00732
00733 template < typename T >
00734 T Quaternion< T >::dot( const Quaternion< T >& a, const Quaternion< T >& b )
00735 {
00736 return a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
00737 }
00738
00739 template < typename T >
00740 void Quaternion< T >::normal( const Quaternion< T >& aa,
00741 const Quaternion< T >& bb,
00742 const Quaternion< T >& cc,
00743 const Quaternion< T >& dd )
00744 {
00745
00746 const Quaternion< T > quat_t = bb - aa;
00747 const Quaternion< T > quat_u = cc - aa;
00748 const Quaternion< T > quat_v = dd - aa;
00749 cross( quat_t, quat_u, quat_v );
00750 normalize();
00751 }
00752
00753 template < typename T >
00754 Quaternion< T > Quaternion< T >::normal( const Quaternion< T >& aa,
00755 const Quaternion< T >& bb,
00756 const Quaternion< T >& cc )
00757 {
00758 Quaternion< T > tmp;
00759 tmp.normal( *this, aa, bb, cc );
00760 return tmp;
00761 }
00762
00763
00764
00765
00766 template< typename T >
00767 Quaternion< T > Quaternion< T >::rotate( T theta, Vector3< T >& axis, const Vector3 < T >& a )
00768 {
00769 Quaternion< T > p = a;
00770 T alpha = theta / 2;
00771 Quaternion< T > q = cos( alpha ) + ( sin( alpha ) * axis.normalize() );
00772 return q * p * q.invert();
00773 }
00774
00775
00776 template< typename T >
00777 Quaternion< T > Quaternion< T >::rotatex( T theta, const Vector3< T >& a )
00778 {
00779 Quaternion< T > p = a;
00780 T alpha = theta / 2;
00781 Quaternion< T > q = cos( alpha ) + ( sin( alpha ) * QUATERI );
00782 return q * p * q.invert();
00783 }
00784
00785 template< typename T >
00786 Quaternion< T > Quaternion< T >::rotatey( T theta, const Vector3< T >& a )
00787 {
00788 Quaternion< T > p = a;
00789 T alpha = theta / 2;
00790 Quaternion< T > q = cos( alpha ) + ( sin( alpha ) * QUATERJ );
00791 return q * p * q.invert();
00792 }
00793
00794 template< typename T >
00795 Quaternion< T > Quaternion< T >::rotatez( T theta, const Vector3< T >& a )
00796 {
00797 Quaternion< T > p = a;
00798 T alpha = theta / 2;
00799 Quaternion< T > q = cos( alpha ) + ( sin( alpha ) * QUATERK );
00800 return q * p * q.invert();
00801 }
00802
00803 template < typename T >
00804 T Quaternion< T >::getMinComponent()
00805 {
00806 T m = std::min( w, x );
00807 m = std::min( m, y );
00808 m = std::min( m, z );
00809 return m;
00810 }
00811
00812 template < typename T >
00813 T Quaternion< T >::getMaxComponent()
00814 {
00815 T m = std::max( w, x );
00816 m = std::max( m, y );
00817 m = std::max( m, z );
00818 return m;
00819 }
00820
00821 template < typename T >
00822 Matrix3< T > Quaternion< T >::getRotationMatrix() const
00823 {
00824 T w2 = w * w;
00825 T x2 = x * x;
00826 T y2 = y * y;
00827 T z2 = z * z;
00828 T wx = w * x;
00829 T wy = w * y;
00830 T wz = w * z;
00831 T xy = x * y;
00832 T xz = x * z;
00833 T yz = y * z;
00834
00835 Matrix3< T > m( w2 + x2 - y2 - z2, 2. * (xy - wz), 2. * (xz + wy),
00836 2. * (xy + wz), w2 - x2 + y2 - z2, 2. * (yz - wx),
00837 2. * (xz - wy), 2. * (yz + wx), w2 - x2 - y2 + z2);
00838
00839 return m;
00840 }
00841
00842 template < typename T >
00843 Quaternion< T > Quaternion< T >::slerp ( T a, Quaternion< T >& p, Quaternion< T >& q )
00844 {
00845 p = p.normalize();
00846 q = q.normalize();
00847 T cosine = p.dot(q);
00848 Quaternion< T > quat_t;
00849
00850
00851 if ( cosine < 0.0 )
00852 {
00853 cosine = -cosine;
00854 quat_t = -q;
00855 }
00856 else
00857 {
00858 quat_t = q;
00859 }
00860
00861 if( cosine.abs() < 1 - 1e-13 )
00862 {
00863
00864 T sine = sqrt( 1. - ( cosine * cosine ) );
00865 T angle = atan2( sine, cosine );
00866 T coeff1 = sin( 1.0 - a ) * angle / sine;
00867 T coeff2 = sin( a * angle ) / sine;
00868 return coeff1 * p + coeff2 * quat_t;
00869 }
00870 else
00871 {
00872
00873 Quaternion< T > quat_u = ( 1. - a ) * p + a * quat_t;
00874 quat_u.normalize();
00875 return quat_u;
00876 }
00877 }
00878
00879 }
00880 #endif