fix btQuaternion::slerp

See issue 583.
Thanks to macbearchen for the report and joshua downer for the fix
This commit is contained in:
erwin.coumans
2012-02-29 04:50:39 +00:00
parent 018c526edc
commit 8f389d13e7

View File

@@ -280,23 +280,25 @@ public:
* Slerp interpolates assuming constant velocity. */ * Slerp interpolates assuming constant velocity. */
btQuaternion slerp(const btQuaternion& q, const btScalar& t) const btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
{ {
btScalar theta = angle(q); btScalar magnitude = btSqrt(length2() * q.length2());
if (theta != btScalar(0.0)) btAssert(magnitude > btScalar(0));
btScalar product = dot(q) / magnitude;
if (btFabs(product) != btScalar(1))
{ {
btScalar d = btScalar(1.0) / btSin(theta); // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
btScalar s0 = btSin((btScalar(1.0) - t) * theta); const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
btScalar s1 = btSin(t * theta);
if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp const btScalar theta = btAcos(sign * product);
return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d, const btScalar s1 = btSin(sign * t * theta);
(m_floats[1] * s0 + -q.y() * s1) * d, const btScalar d = btScalar(1.0) / btSin(theta);
(m_floats[2] * s0 + -q.z() * s1) * d, const btScalar s0 = btSin((btScalar(1.0) - t) * theta);
(m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
else return btQuaternion(
return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d, (m_floats[0] * s0 + q.x() * s1) * d,
(m_floats[1] * s0 + q.y() * s1) * d, (m_floats[1] * s0 + q.y() * s1) * d,
(m_floats[2] * s0 + q.z() * s1) * d, (m_floats[2] * s0 + q.z() * s1) * d,
(m_floats[3] * s0 + q.m_floats[3] * s1) * d); (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
} }
else else
{ {