Blender V2.61 - r43446
|
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