Fix nans in math::slerp, second attempt.

My earlier fix (3b373e5) was insufficient in some cases, this new
approach is cribbed from glMatrix.
This commit is contained in:
Philip Rideout
2019-02-26 21:03:49 -08:00
parent 552b1c551f
commit c65e561c59
+7 -7
View File
@@ -245,17 +245,17 @@ public:
friend inline
QUATERNION<T> MATH_PURE slerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
// could also be computed as: pow(q * inverse(p), t) * p;
const T d = dot(p, q);
const T d = std::abs(dot(p, q));
static constexpr T value_eps = T(10) * std::numeric_limits<T>::epsilon();
// Prevent blowing up when slerping between two quaternions that are very near each other.
if ((T(1) - d) < value_eps) {
return lerp(p, q, t);
}
const T npq = sqrt(dot(p, p) * dot(q, q)); // ||p|| * ||q||
const T a = std::acos(std::abs(d) / npq);
const T a = std::acos(d / npq);
const T a0 = a * (1 - t);
const T a1 = a * t;
const T sina = sin(a);
// Prevent blowing up when slerping between two quaternions that are very near each other.
static constexpr T value_eps = T(10) * std::numeric_limits<T>::epsilon();
if (std::abs(sina) < value_eps) {
return lerp(p, q, t);
}
const T isina = 1 / sina;
const T s0 = std::sin(a0) * isina;
const T s1 = std::sin(a1) * isina;