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 BT_SIMD__QUATERNION_H_
00018 #define BT_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 = 1.f-m_floats[3]*m_floats[3];
00216                 
00217                 if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
00218                         return btVector3(1.0, 0.0, 0.0);  // Arbitrary
00219                 btScalar s = 1.f/btSqrt(s_squared);
00220                 return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
00221         }
00222 
00224         btQuaternion inverse() const
00225         {
00226                 return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
00227         }
00228 
00231         SIMD_FORCE_INLINE btQuaternion
00232         operator+(const btQuaternion& q2) const
00233         {
00234                 const btQuaternion& q1 = *this;
00235                 return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
00236         }
00237 
00240         SIMD_FORCE_INLINE btQuaternion
00241         operator-(const btQuaternion& q2) const
00242         {
00243                 const btQuaternion& q1 = *this;
00244                 return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
00245         }
00246 
00249         SIMD_FORCE_INLINE btQuaternion operator-() const
00250         {
00251                 const btQuaternion& q2 = *this;
00252                 return btQuaternion( - q2.x(), - q2.y(),  - q2.z(),  - q2.m_floats[3]);
00253         }
00255         SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const 
00256         {
00257                 btQuaternion diff,sum;
00258                 diff = *this - qd;
00259                 sum = *this + qd;
00260                 if( diff.dot(diff) > sum.dot(sum) )
00261                         return qd;
00262                 return (-qd);
00263         }
00264 
00266         SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const 
00267         {
00268                 btQuaternion diff,sum;
00269                 diff = *this - qd;
00270                 sum = *this + qd;
00271                 if( diff.dot(diff) < sum.dot(sum) )
00272                         return qd;
00273                 return (-qd);
00274         }
00275 
00276 
00281         btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
00282         {
00283                 btScalar theta = angle(q);
00284                 if (theta != btScalar(0.0))
00285                 {
00286                         btScalar d = btScalar(1.0) / btSin(theta);
00287                         btScalar s0 = btSin((btScalar(1.0) - t) * theta);
00288                         btScalar s1 = btSin(t * theta);   
00289                         if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
00290                           return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d,
00291                                               (m_floats[1] * s0 + -q.y() * s1) * d,
00292                                               (m_floats[2] * s0 + -q.z() * s1) * d,
00293                                               (m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
00294                         else
00295                           return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d,
00296                                               (m_floats[1] * s0 + q.y() * s1) * d,
00297                                               (m_floats[2] * s0 + q.z() * s1) * d,
00298                                               (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
00299                         
00300                 }
00301                 else
00302                 {
00303                         return *this;
00304                 }
00305         }
00306 
00307         static const btQuaternion&      getIdentity()
00308         {
00309                 static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
00310                 return identityQuat;
00311         }
00312 
00313         SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
00314 
00315         
00316 };
00317 
00318 
00319 
00320 
00321 
00323 SIMD_FORCE_INLINE btQuaternion
00324 operator*(const btQuaternion& q1, const btQuaternion& q2) {
00325         return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
00326                 q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
00327                 q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
00328                 q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); 
00329 }
00330 
00331 SIMD_FORCE_INLINE btQuaternion
00332 operator*(const btQuaternion& q, const btVector3& w)
00333 {
00334         return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
00335                 q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
00336                 q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
00337                 -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); 
00338 }
00339 
00340 SIMD_FORCE_INLINE btQuaternion
00341 operator*(const btVector3& w, const btQuaternion& q)
00342 {
00343         return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
00344                 w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
00345                 w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
00346                 -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); 
00347 }
00348 
00350 SIMD_FORCE_INLINE btScalar 
00351 dot(const btQuaternion& q1, const btQuaternion& q2) 
00352 { 
00353         return q1.dot(q2); 
00354 }
00355 
00356 
00358 SIMD_FORCE_INLINE btScalar
00359 length(const btQuaternion& q) 
00360 { 
00361         return q.length(); 
00362 }
00363 
00365 SIMD_FORCE_INLINE btScalar
00366 angle(const btQuaternion& q1, const btQuaternion& q2) 
00367 { 
00368         return q1.angle(q2); 
00369 }
00370 
00372 SIMD_FORCE_INLINE btQuaternion
00373 inverse(const btQuaternion& q) 
00374 {
00375         return q.inverse();
00376 }
00377 
00383 SIMD_FORCE_INLINE btQuaternion
00384 slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) 
00385 {
00386         return q1.slerp(q2, t);
00387 }
00388 
00389 SIMD_FORCE_INLINE btVector3 
00390 quatRotate(const btQuaternion& rotation, const btVector3& v) 
00391 {
00392         btQuaternion q = rotation * v;
00393         q *= rotation.inverse();
00394         return btVector3(q.getX(),q.getY(),q.getZ());
00395 }
00396 
00397 SIMD_FORCE_INLINE btQuaternion 
00398 shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
00399 {
00400         btVector3 c = v0.cross(v1);
00401         btScalar  d = v0.dot(v1);
00402 
00403         if (d < -1.0 + SIMD_EPSILON)
00404         {
00405                 btVector3 n,unused;
00406                 btPlaneSpace1(v0,n,unused);
00407                 return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
00408         }
00409 
00410         btScalar  s = btSqrt((1.0f + d) * 2.0f);
00411         btScalar rs = 1.0f / s;
00412 
00413         return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
00414 }
00415 
00416 SIMD_FORCE_INLINE btQuaternion 
00417 shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
00418 {
00419         v0.normalize();
00420         v1.normalize();
00421         return shortestArcQuat(v0,v1);
00422 }
00423 
00424 #endif //BT_SIMD__QUATERNION_H_
00425 
00426 
00427 
00428 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


bullet
Author(s): Erwin Coumans, ROS package maintained by Tully Foote
autogenerated on Wed Oct 31 2012 07:54:31