diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 119b55877..cb0232d05 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -112,7 +112,13 @@ Expects that both quaternions are normalized. @f[ template inline Quaternion slerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t) { CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), "Math::slerp(): quaternions must be normalized", {}); - const T a = Implementation::angle(normalizedA, normalizedB); + const T cosHalfAngle = dot(normalizedA, normalizedB); + if(std::abs(cosHalfAngle) >= T(1)) { + /* The angle `a` between the quaternions `A` and `B` is 0 and we cannot + divide by sin(a). This is the case for `A == B` or `A == -B`. */ + return Quaternion{normalizedA}; + } + const T a = std::acos(cosHalfAngle); return (std::sin((T(1) - t)*a)*normalizedA + std::sin(t*a)*normalizedB)/std::sin(a); } diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index c7aabe50d..33cf20b0b 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -438,6 +438,9 @@ void QuaternionTest::slerp() { Quaternion slerp = Math::slerp(a, b, 0.35f); CORRADE_COMPARE(slerp, Quaternion({0.1191653f, 0.0491109f, 0.0491109f}, 0.9904423f)); + + CORRADE_COMPARE(Math::slerp(Quaternion(), Quaternion(), 0.25f), Quaternion()); + CORRADE_COMPARE(Math::slerp(Quaternion(), -Quaternion(), 0.42f), Quaternion()); } void QuaternionTest::transformVector() {