From eadf8986f6dd7498b9f32078dbb71a26355b528e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 3 Sep 2018 22:18:12 +0200 Subject: [PATCH] Math: fuzzy compare for division-by-zero in quaternion s(c)lerp. Also remove a totally unneeded conversion. --- src/Magnum/Math/DualQuaternion.h | 4 ++-- src/Magnum/Math/Quaternion.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index ab806d3a6a..b268c9a267 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -84,7 +84,7 @@ template inline DualQuaternion sclerp(const DualQuaternion& 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::epsilon()) return DualQuaternion::translation(Implementation::lerp(normalizedA.translation(), normalizedB.translation(), t))*DualQuaternion{normalizedA.real()}; /* l + εm = q_A^**q_B */ @@ -151,7 +151,7 @@ template inline DualQuaternion 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::epsilon()) return DualQuaternion::translation(Implementation::lerp(normalizedA.translation(), normalizedB.translation(), t))*DualQuaternion{normalizedA.real()}; /* l + εm = q_A^**q_B, multiplying with -1 ensures shortest path when dot < 0 */ diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 4f1b600a10..325b68ce78 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -163,7 +163,8 @@ template inline Quaternion slerp(const Quaternion& normalizedA, c const T cosHalfAngle = dot(normalizedA, normalizedB); /* Avoid division by zero */ - if(std::abs(cosHalfAngle) >= T(1)) return Quaternion{normalizedA}; + if(std::abs(cosHalfAngle) >= T(1) - TypeTraits::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 inline Quaternion slerpShortestPath(const Quaternion& no const T cosHalfAngle = dot(normalizedA, normalizedB); /* Avoid division by zero */ - if(std::abs(cosHalfAngle) >= T(1)) return Quaternion{normalizedA}; + if(std::abs(cosHalfAngle) >= T(1) - TypeTraits::epsilon()) + return normalizedA; const Quaternion shortestNormalizedA = cosHalfAngle < 0 ? -normalizedA : normalizedA;