00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00031
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,
00102 cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
00103 cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
00104 cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
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)
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)
00248 return btVector3(1.0, 0.0, 0.0);
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)
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)
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);
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