btQuaternion.h

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
00003 
00004 This software is provided 'as-is', without any express or implied warranty.
00005 In no event will the authors be held liable for any damages arising from the use of this software.
00006 Permission is granted to anyone to use this software for any purpose, 
00007 including commercial applications, and to alter it and redistribute it freely, 
00008 subject to the following restrictions:
00009 
00010 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00011 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00012 3. This notice may not be removed or altered from any source distribution.
00013 */
00014 
00015 
00016 
00017 #ifndef SIMD__QUATERNION_H_
00018 #define SIMD__QUATERNION_H_
00019 
00020 
00021 #include "btVector3.h"
00022 #include "btQuadWord.h"
00023 
00025 class btQuaternion : public btQuadWord {
00026 public:
00028         btQuaternion() {}
00029 
00030         //              template <typename btScalar>
00031         //              explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
00033         btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) 
00034                 : btQuadWord(x, y, z, w) 
00035         {}
00039         btQuaternion(const btVector3& axis, const btScalar& angle) 
00040         { 
00041                 setRotation(axis, angle); 
00042         }
00047         btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
00048         { 
00049 #ifndef BT_EULER_DEFAULT_ZYX
00050                 setEuler(yaw, pitch, roll); 
00051 #else
00052                 setEulerZYX(yaw, pitch, roll); 
00053 #endif 
00054         }
00058         void setRotation(const btVector3& axis, const btScalar& angle)
00059         {
00060                 btScalar d = axis.length();
00061                 btAssert(d != btScalar(0.0));
00062                 btScalar s = btSin(angle * btScalar(0.5)) / d;
00063                 setValue(axis.x() * s, axis.y() * s, axis.z() * s, 
00064                         btCos(angle * btScalar(0.5)));
00065         }
00070         void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
00071         {
00072                 btScalar halfYaw = btScalar(yaw) * btScalar(0.5);  
00073                 btScalar halfPitch = btScalar(pitch) * btScalar(0.5);  
00074                 btScalar halfRoll = btScalar(roll) * btScalar(0.5);  
00075                 btScalar cosYaw = btCos(halfYaw);
00076                 btScalar sinYaw = btSin(halfYaw);
00077                 btScalar cosPitch = btCos(halfPitch);
00078                 btScalar sinPitch = btSin(halfPitch);
00079                 btScalar cosRoll = btCos(halfRoll);
00080                 btScalar sinRoll = btSin(halfRoll);
00081                 setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
00082                         cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
00083                         sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
00084                         cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
00085         }
00090         void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
00091         {
00092                 btScalar halfYaw = btScalar(yaw) * btScalar(0.5);  
00093                 btScalar halfPitch = btScalar(pitch) * btScalar(0.5);  
00094                 btScalar halfRoll = btScalar(roll) * btScalar(0.5);  
00095                 btScalar cosYaw = btCos(halfYaw);
00096                 btScalar sinYaw = btSin(halfYaw);
00097                 btScalar cosPitch = btCos(halfPitch);
00098                 btScalar sinPitch = btSin(halfPitch);
00099                 btScalar cosRoll = btCos(halfRoll);
00100                 btScalar sinRoll = btSin(halfRoll);
00101                 setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
00102                          cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
00103                          cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
00104                          cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
00105         }
00108         SIMD_FORCE_INLINE       btQuaternion& operator+=(const btQuaternion& q)
00109         {
00110                 m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3];
00111                 return *this;
00112         }
00113 
00116         btQuaternion& operator-=(const btQuaternion& q) 
00117         {
00118                 m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3];
00119                 return *this;
00120         }
00121 
00124         btQuaternion& operator*=(const btScalar& s)
00125         {
00126                 m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s;
00127                 return *this;
00128         }
00129 
00133         btQuaternion& operator*=(const btQuaternion& q)
00134         {
00135                 setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
00136                         m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
00137                         m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
00138                         m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
00139                 return *this;
00140         }
00143         btScalar dot(const btQuaternion& q) const
00144         {
00145                 return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3];
00146         }
00147 
00149         btScalar length2() const
00150         {
00151                 return dot(*this);
00152         }
00153 
00155         btScalar length() const
00156         {
00157                 return btSqrt(length2());
00158         }
00159 
00162         btQuaternion& normalize() 
00163         {
00164                 return *this /= length();
00165         }
00166 
00169         SIMD_FORCE_INLINE btQuaternion
00170         operator*(const btScalar& s) const
00171         {
00172                 return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
00173         }
00174 
00175 
00178         btQuaternion operator/(const btScalar& s) const
00179         {
00180                 btAssert(s != btScalar(0.0));
00181                 return *this * (btScalar(1.0) / s);
00182         }
00183 
00186         btQuaternion& operator/=(const btScalar& s) 
00187         {
00188                 btAssert(s != btScalar(0.0));
00189                 return *this *= btScalar(1.0) / s;
00190         }
00191 
00193         btQuaternion normalized() const 
00194         {
00195                 return *this / length();
00196         } 
00199         btScalar angle(const btQuaternion& q) const 
00200         {
00201                 btScalar s = btSqrt(length2() * q.length2());
00202                 btAssert(s != btScalar(0.0));
00203                 return btAcos(dot(q) / s);
00204         }
00206         btScalar getAngle() const 
00207         {
00208                 btScalar s = btScalar(2.) * btAcos(m_floats[3]);
00209                 return s;
00210         }
00211 
00213         btVector3 getAxis() const
00214         {
00215                 btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.));
00216                 if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
00217                         return btVector3(1.0, 0.0, 0.0);  // Arbitrary
00218                 btScalar s = btSqrt(s_squared);
00219                 return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s);
00220         }
00221 
00223         btQuaternion inverse() const
00224         {
00225                 return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
00226         }
00227 
00230         SIMD_FORCE_INLINE btQuaternion
00231         operator+(const btQuaternion& q2) const
00232         {
00233                 const btQuaternion& q1 = *this;
00234                 return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
00235         }
00236 
00239         SIMD_FORCE_INLINE btQuaternion
00240         operator-(const btQuaternion& q2) const
00241         {
00242                 const btQuaternion& q1 = *this;
00243                 return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
00244         }
00245 
00248         SIMD_FORCE_INLINE btQuaternion operator-() const
00249         {
00250                 const btQuaternion& q2 = *this;
00251                 return btQuaternion( - q2.x(), - q2.y(),  - q2.z(),  - q2.m_floats[3]);
00252         }
00254         SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const 
00255         {
00256                 btQuaternion diff,sum;
00257                 diff = *this - qd;
00258                 sum = *this + qd;
00259                 if( diff.dot(diff) > sum.dot(sum) )
00260                         return qd;
00261                 return (-qd);
00262         }
00263 
00265         SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const 
00266         {
00267                 btQuaternion diff,sum;
00268                 diff = *this - qd;
00269                 sum = *this + qd;
00270                 if( diff.dot(diff) < sum.dot(sum) )
00271                         return qd;
00272                 return (-qd);
00273         }
00274 
00275 
00280         btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
00281         {
00282                 btScalar theta = angle(q);
00283                 if (theta != btScalar(0.0))
00284                 {
00285                         btScalar d = btScalar(1.0) / btSin(theta);
00286                         btScalar s0 = btSin((btScalar(1.0) - t) * theta);
00287                         btScalar s1 = btSin(t * theta);   
00288                         if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
00289                           return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d,
00290                                               (m_floats[1] * s0 + -q.y() * s1) * d,
00291                                               (m_floats[2] * s0 + -q.z() * s1) * d,
00292                                               (m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
00293                         else
00294                           return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d,
00295                                               (m_floats[1] * s0 + q.y() * s1) * d,
00296                                               (m_floats[2] * s0 + q.z() * s1) * d,
00297                                               (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
00298                         
00299                 }
00300                 else
00301                 {
00302                         return *this;
00303                 }
00304         }
00305 
00306         static const btQuaternion&      getIdentity()
00307         {
00308                 static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
00309                 return identityQuat;
00310         }
00311 
00312         SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
00313 
00314         
00315 };
00316 
00317 
00319 SIMD_FORCE_INLINE btQuaternion
00320 operator-(const btQuaternion& q)
00321 {
00322         return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w());
00323 }
00324 
00325 
00326 
00328 SIMD_FORCE_INLINE btQuaternion
00329 operator*(const btQuaternion& q1, const btQuaternion& q2) {
00330         return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
00331                 q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
00332                 q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
00333                 q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); 
00334 }
00335 
00336 SIMD_FORCE_INLINE btQuaternion
00337 operator*(const btQuaternion& q, const btVector3& w)
00338 {
00339         return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
00340                 q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
00341                 q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
00342                 -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); 
00343 }
00344 
00345 SIMD_FORCE_INLINE btQuaternion
00346 operator*(const btVector3& w, const btQuaternion& q)
00347 {
00348         return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
00349                 w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
00350                 w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
00351                 -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); 
00352 }
00353 
00355 SIMD_FORCE_INLINE btScalar 
00356 dot(const btQuaternion& q1, const btQuaternion& q2) 
00357 { 
00358         return q1.dot(q2); 
00359 }
00360 
00361 
00363 SIMD_FORCE_INLINE btScalar
00364 length(const btQuaternion& q) 
00365 { 
00366         return q.length(); 
00367 }
00368 
00370 SIMD_FORCE_INLINE btScalar
00371 angle(const btQuaternion& q1, const btQuaternion& q2) 
00372 { 
00373         return q1.angle(q2); 
00374 }
00375 
00377 SIMD_FORCE_INLINE btQuaternion
00378 inverse(const btQuaternion& q) 
00379 {
00380         return q.inverse();
00381 }
00382 
00388 SIMD_FORCE_INLINE btQuaternion
00389 slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) 
00390 {
00391         return q1.slerp(q2, t);
00392 }
00393 
00394 SIMD_FORCE_INLINE btVector3 
00395 quatRotate(const btQuaternion& rotation, const btVector3& v) 
00396 {
00397         btQuaternion q = rotation * v;
00398         q *= rotation.inverse();
00399         return btVector3(q.getX(),q.getY(),q.getZ());
00400 }
00401 
00402 SIMD_FORCE_INLINE btQuaternion 
00403 shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
00404 {
00405         btVector3 c = v0.cross(v1);
00406         btScalar  d = v0.dot(v1);
00407 
00408         if (d < -1.0 + SIMD_EPSILON)
00409         {
00410                 btVector3 n,unused;
00411                 btPlaneSpace1(v0,n,unused);
00412                 return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
00413         }
00414 
00415         btScalar  s = btSqrt((1.0f + d) * 2.0f);
00416         btScalar rs = 1.0f / s;
00417 
00418         return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
00419 }
00420 
00421 SIMD_FORCE_INLINE btQuaternion 
00422 shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
00423 {
00424         v0.normalize();
00425         v1.normalize();
00426         return shortestArcQuat(v0,v1);
00427 }
00428 
00429 #endif
00430 
00431 
00432 
00433 

Generated on Mon Feb 15 22:17:05 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1