Browse Source

Math: fuzzy compare for division-by-zero in quaternion s(c)lerp.

Also remove a totally unneeded conversion.
pull/267/head
Vladimír Vondruš 8 years ago
parent
commit
eadf8986f6
  1. 4
      src/Magnum/Math/DualQuaternion.h
  2. 6
      src/Magnum/Math/Quaternion.h

4
src/Magnum/Math/DualQuaternion.h

@ -84,7 +84,7 @@ template<class T> inline DualQuaternion<T> sclerp(const DualQuaternion<T>& norma
/* Avoid division by zero: interpolate just the translation part */
/** @todo could this be optimized somehow? */
if(std::abs(cosHalfAngle) >= T(1))
if(std::abs(cosHalfAngle) >= T(1) - TypeTraits<T>::epsilon())
return DualQuaternion<T>::translation(Implementation::lerp(normalizedA.translation(), normalizedB.translation(), t))*DualQuaternion<T>{normalizedA.real()};
/* l + εm = q_A^**q_B */
@ -151,7 +151,7 @@ template<class T> inline DualQuaternion<T> sclerpShortestPath(const DualQuaterni
/* Avoid division by zero: interpolate just the translation part */
/** @todo could this be optimized somehow? */
if(std::abs(cosHalfAngle) >= T(1))
if(std::abs(cosHalfAngle) >= T(1) - TypeTraits<T>::epsilon())
return DualQuaternion<T>::translation(Implementation::lerp(normalizedA.translation(), normalizedB.translation(), t))*DualQuaternion<T>{normalizedA.real()};
/* l + εm = q_A^**q_B, multiplying with -1 ensures shortest path when dot < 0 */

6
src/Magnum/Math/Quaternion.h

@ -163,7 +163,8 @@ template<class T> inline Quaternion<T> slerp(const Quaternion<T>& normalizedA, c
const T cosHalfAngle = dot(normalizedA, normalizedB);
/* Avoid division by zero */
if(std::abs(cosHalfAngle) >= T(1)) return Quaternion<T>{normalizedA};
if(std::abs(cosHalfAngle) >= T(1) - TypeTraits<T>::epsilon())
return normalizedA;
const T a = std::acos(cosHalfAngle);
return (std::sin((T(1) - t)*a)*normalizedA + std::sin(t*a)*normalizedB)/std::sin(a);
@ -206,7 +207,8 @@ template<class T> inline Quaternion<T> slerpShortestPath(const Quaternion<T>& no
const T cosHalfAngle = dot(normalizedA, normalizedB);
/* Avoid division by zero */
if(std::abs(cosHalfAngle) >= T(1)) return Quaternion<T>{normalizedA};
if(std::abs(cosHalfAngle) >= T(1) - TypeTraits<T>::epsilon())
return normalizedA;
const Quaternion<T> shortestNormalizedA = cosHalfAngle < 0 ? -normalizedA : normalizedA;

Loading…
Cancel
Save