$search
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) __attribute__((deprecated)) 00048 { 00049 #ifndef BT_EULER_DEFAULT_ZYX 00050 setEuler(yaw, pitch, roll); 00051 #else 00052 setRPY(roll, pitch, yaw); 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 setRPY(const btScalar& roll, const btScalar& pitch, const btScalar& yaw) 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 } 00110 void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) __attribute__((deprecated)) 00111 { 00112 setRPY(roll, pitch, yaw); 00113 } 00116 SIMD_FORCE_INLINE 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 btQuaternion& q) 00125 { 00126 m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3]; 00127 return *this; 00128 } 00129 00132 btQuaternion& operator*=(const btScalar& s) 00133 { 00134 m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s; 00135 return *this; 00136 } 00137 00141 btQuaternion& operator*=(const btQuaternion& q) 00142 { 00143 setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(), 00144 m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(), 00145 m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(), 00146 m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z()); 00147 return *this; 00148 } 00151 btScalar dot(const btQuaternion& q) const 00152 { 00153 return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3]; 00154 } 00155 00157 btScalar length2() const 00158 { 00159 return dot(*this); 00160 } 00161 00163 btScalar length() const 00164 { 00165 return btSqrt(length2()); 00166 } 00167 00170 btQuaternion& normalize() 00171 { 00172 return *this /= length(); 00173 } 00174 00177 SIMD_FORCE_INLINE btQuaternion 00178 operator*(const btScalar& s) const 00179 { 00180 return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s); 00181 } 00182 00183 00186 btQuaternion operator/(const btScalar& s) const 00187 { 00188 btAssert(s != btScalar(0.0)); 00189 return *this * (btScalar(1.0) / s); 00190 } 00191 00194 btQuaternion& operator/=(const btScalar& s) 00195 { 00196 btAssert(s != btScalar(0.0)); 00197 return *this *= btScalar(1.0) / s; 00198 } 00199 00201 btQuaternion normalized() const 00202 { 00203 return *this / length(); 00204 } 00207 btScalar angle(const btQuaternion& q) const 00208 { 00209 btScalar s = btSqrt(length2() * q.length2()); 00210 btAssert(s != btScalar(0.0)); 00211 return btAcos(dot(q) / s); 00212 } 00215 btScalar angleShortestPath(const btQuaternion& q) const 00216 { 00217 btScalar s = btSqrt(length2() * q.length2()); 00218 btAssert(s != btScalar(0.0)); 00219 if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp 00220 return btAcos(dot(-q) / s) * btScalar(2.0); 00221 else 00222 return btAcos(dot(q) / s) * btScalar(2.0); 00223 } 00225 btScalar getAngle() const 00226 { 00227 btScalar s = btScalar(2.) * btAcos(m_floats[3]); 00228 return s; 00229 } 00230 00232 btScalar getAngleShortestPath() const 00233 { 00234 btScalar s; 00235 if (dot(*this) < 0) 00236 s = btScalar(2.) * btAcos(m_floats[3]); 00237 else 00238 s = btScalar(2.) * btAcos(-m_floats[3]); 00239 00240 return s; 00241 } 00242 00244 btVector3 getAxis() const 00245 { 00246 btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.)); 00247 if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero 00248 return btVector3(1.0, 0.0, 0.0); // Arbitrary 00249 btScalar s = btSqrt(s_squared); 00250 return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s); 00251 } 00252 00254 btQuaternion inverse() const 00255 { 00256 return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]); 00257 } 00258 00261 SIMD_FORCE_INLINE btQuaternion 00262 operator+(const btQuaternion& q2) const 00263 { 00264 const btQuaternion& q1 = *this; 00265 return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]); 00266 } 00267 00270 SIMD_FORCE_INLINE btQuaternion 00271 operator-(const btQuaternion& q2) const 00272 { 00273 const btQuaternion& q1 = *this; 00274 return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]); 00275 } 00276 00279 SIMD_FORCE_INLINE btQuaternion operator-() const 00280 { 00281 const btQuaternion& q2 = *this; 00282 return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]); 00283 } 00285 SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const 00286 { 00287 btQuaternion diff,sum; 00288 diff = *this - qd; 00289 sum = *this + qd; 00290 if( diff.dot(diff) > sum.dot(sum) ) 00291 return qd; 00292 return (-qd); 00293 } 00294 00296 SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const 00297 { 00298 btQuaternion diff,sum; 00299 diff = *this - qd; 00300 sum = *this + qd; 00301 if( diff.dot(diff) < sum.dot(sum) ) 00302 return qd; 00303 return (-qd); 00304 } 00305 00306 00311 btQuaternion slerp(const btQuaternion& q, const btScalar& t) const 00312 { 00313 btScalar theta = angleShortestPath(q) / btScalar(2.0); 00314 if (theta != btScalar(0.0)) 00315 { 00316 btScalar d = btScalar(1.0) / btSin(theta); 00317 btScalar s0 = btSin((btScalar(1.0) - t) * theta); 00318 btScalar s1 = btSin(t * theta); 00319 if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp 00320 return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d, 00321 (m_floats[1] * s0 + -q.y() * s1) * d, 00322 (m_floats[2] * s0 + -q.z() * s1) * d, 00323 (m_floats[3] * s0 + -q.m_floats[3] * s1) * d); 00324 else 00325 return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d, 00326 (m_floats[1] * s0 + q.y() * s1) * d, 00327 (m_floats[2] * s0 + q.z() * s1) * d, 00328 (m_floats[3] * s0 + q.m_floats[3] * s1) * d); 00329 00330 } 00331 else 00332 { 00333 return *this; 00334 } 00335 } 00336 00337 static const btQuaternion& getIdentity() 00338 { 00339 static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.)); 00340 return identityQuat; 00341 } 00342 00343 SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; } 00344 00345 00346 }; 00347 00348 00350 SIMD_FORCE_INLINE btQuaternion 00351 operator-(const btQuaternion& q) 00352 { 00353 return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w()); 00354 } 00355 00356 00357 00359 SIMD_FORCE_INLINE btQuaternion 00360 operator*(const btQuaternion& q1, const btQuaternion& q2) { 00361 return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(), 00362 q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(), 00363 q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(), 00364 q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); 00365 } 00366 00367 SIMD_FORCE_INLINE btQuaternion 00368 operator*(const btQuaternion& q, const btVector3& w) 00369 { 00370 return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(), 00371 q.w() * w.y() + q.z() * w.x() - q.x() * w.z(), 00372 q.w() * w.z() + q.x() * w.y() - q.y() * w.x(), 00373 -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); 00374 } 00375 00376 SIMD_FORCE_INLINE btQuaternion 00377 operator*(const btVector3& w, const btQuaternion& q) 00378 { 00379 return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(), 00380 w.y() * q.w() + w.z() * q.x() - w.x() * q.z(), 00381 w.z() * q.w() + w.x() * q.y() - w.y() * q.x(), 00382 -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); 00383 } 00384 00386 SIMD_FORCE_INLINE btScalar 00387 dot(const btQuaternion& q1, const btQuaternion& q2) 00388 { 00389 return q1.dot(q2); 00390 } 00391 00392 00394 SIMD_FORCE_INLINE btScalar 00395 length(const btQuaternion& q) 00396 { 00397 return q.length(); 00398 } 00399 00401 SIMD_FORCE_INLINE btScalar 00402 angle(const btQuaternion& q1, const btQuaternion& q2) 00403 { 00404 return q1.angle(q2); 00405 } 00406 00408 SIMD_FORCE_INLINE btScalar 00409 angleShortestPath(const btQuaternion& q1, const btQuaternion& q2) 00410 { 00411 return q1.angleShortestPath(q2); 00412 } 00413 00415 SIMD_FORCE_INLINE btQuaternion 00416 inverse(const btQuaternion& q) 00417 { 00418 return q.inverse(); 00419 } 00420 00426 SIMD_FORCE_INLINE btQuaternion 00427 slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) 00428 { 00429 return q1.slerp(q2, t); 00430 } 00431 00432 SIMD_FORCE_INLINE btVector3 00433 quatRotate(const btQuaternion& rotation, const btVector3& v) 00434 { 00435 btQuaternion q = rotation * v; 00436 q *= rotation.inverse(); 00437 return btVector3(q.getX(),q.getY(),q.getZ()); 00438 } 00439 00440 SIMD_FORCE_INLINE btQuaternion 00441 shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized 00442 { 00443 btVector3 c = v0.cross(v1); 00444 btScalar d = v0.dot(v1); 00445 00446 if (d < -1.0 + SIMD_EPSILON) 00447 { 00448 btVector3 n,unused; 00449 btPlaneSpace1(v0,n,unused); 00450 return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0 00451 } 00452 00453 btScalar s = btSqrt((1.0f + d) * 2.0f); 00454 btScalar rs = 1.0f / s; 00455 00456 return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f); 00457 } 00458 00459 SIMD_FORCE_INLINE btQuaternion 00460 shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) 00461 { 00462 v0.normalize(); 00463 v1.normalize(); 00464 return shortestArcQuat(v0,v1); 00465 } 00466 00467 #endif 00468 00469 00470 00471