00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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 = 1.f-m_floats[3]*m_floats[3];
00216
00217 if (s_squared < btScalar(10.) * SIMD_EPSILON)
00218 return btVector3(1.0, 0.0, 0.0);
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)
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)
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);
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