Blender V2.61 - r43446

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