diff --git a/doc/changelog.dox b/doc/changelog.dox index 410c51cfe..e67f6c82f 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -307,6 +307,8 @@ See also: - @ref Platform::GlfwApplication::exec() now asserts instead of crashing if the constructor fails to create a window (see [mosra/magnum#192](https://github.com/mosra/magnum/issues/192), [mosra/magnum#272](https://github.com/mosra/magnum/pull/272)) +- @ref Math::sclerp() was not properly interpolating the translation if + rotation was the same on both sides @subsection changelog-latest-docs Documentation diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index 81c4a95ae..d8f45269b 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -66,15 +66,15 @@ Expects that both dual quaternions are normalized. @f[ template inline DualQuaternion sclerp(const DualQuaternion& normalizedA, const DualQuaternion& normalizedB, const T t) { CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), "Math::sclerp(): dual quaternions must be normalized", {}); - const T dotResult = dot(normalizedA.real().vector(), normalizedB.real().vector()); + const T cosHalfAngle = dot(normalizedA.real(), normalizedB.real()); - /* Avoid division by zero */ - const T cosHalfAngle = dotResult + normalizedA.real().scalar()*normalizedB.real().scalar(); + /* Avoid division by zero: interpolate just the translation part */ + /** @todo could this be optimized somehow? */ if(std::abs(cosHalfAngle) >= T(1)) - return {normalizedA.real(), {Implementation::lerp(normalizedA.dual().vector(), normalizedB.dual().vector(), t), T(0)}}; + 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 */ - const DualQuaternion diff = normalizedA.quaternionConjugated()*(dotResult < T(0) ? -normalizedB : normalizedB); + const DualQuaternion diff = normalizedA.quaternionConjugated()*(cosHalfAngle < T(0) ? -normalizedB : normalizedB); const Quaternion& l = diff.real(); const Quaternion& m = diff.dual();