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)
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,
00102 cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
00103 cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
00104 cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
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)
00217 return btVector3(1.0, 0.0, 0.0);
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)
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)
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);
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