Add SLERP test and euler2quat.

This commit is contained in:
2019-08-06 00:46:02 -07:00
parent be75f67ab8
commit be0d5f9b71
6 changed files with 137 additions and 27 deletions

View File

@@ -7,6 +7,7 @@
#include <cassert>
#include <cmath>
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <wrmath/geom/vector.h>
#include <wrmath/math.h>
@@ -123,8 +124,25 @@ public:
}
/// Compute the dot product of two quaternions.
///
/// \param other Another quaternion.
/// \return The dot product between the two quaternions.
T
dot(const Quaternion<T> &other) const
{
double innerProduct = this->v[0] * other.v[0];
innerProduct += (this->v[1] * other.v[1]);
innerProduct += (this->v[2] * other.v[2]);
innerProduct += (this->w * other.w);
return innerProduct;
}
/// Compute the norm of a quaternion. Treating the Quaternion as a
/// Vector<T, 4>, it's the same as computing the magnitude.
///
/// @return A non-negative real number.
T
norm() const
@@ -140,6 +158,15 @@ public:
}
/// Return the unit quaternion.
///
/// \return The unit quaternion.
Quaternion
unitQuaternion()
{
return *this / this->norm();
}
/// Compute the conjugate of a quaternion.
/// @return The conjugate of this quaternion.
Quaternion
@@ -393,7 +420,11 @@ Quaterniond quaterniond_from_euler(Vector3d euler);
/// \return A Quaternion representing the linear interpolation of the
/// two quaternions.
template <typename T>
Quaternion<T> LERP(Quaternion<T> p, Quaternion<T> q, T t);
Quaternion<T>
LERP(Quaternion<T> p, Quaternion<T> q, T t)
{
return (p + (q - p) * t).unitQuaternion();
}
/// ShortestSLERP computes the shortest distance spherical linear
@@ -402,13 +433,30 @@ Quaternion<T> LERP(Quaternion<T> p, Quaternion<T> q, T t);
///
/// \tparam T
/// \param p The starting quaternion.
/// \param q The ending quaternion.
/// \param q The ending quaternion.Short
/// \param t The fraction of the distance between the two quaternions
/// to interpolate.
/// \return A Quaternion representing the shortest path between two
/// quaternions.
template <typename T>
Quaternion<T> ShortestSLERP(Quaternion<T> p, Quaternion<T> q, T t);
Quaternion<T>
ShortestSLERP(Quaternion<T> p, Quaternion<T> q, T t)
{
assert(p.isUnitQuaternion());
assert(q.isUnitQuaternion());
T dp = p.dot(q);
T sign = dp < 0.0 ? -1.0 : 1.0;
T omega = std::acos(dp * sign);
T sin_omega = std::sin(omega); // Compute once.
if (dp > 0.99999) {
return LERP(p, q * sign, t);
}
return (p * std::sin((1.0 - t) * omega) / sin_omega) +
(q * sign * std::sin(omega*t) / sin_omega);
}
/// Run a quick self test to exercise basic functionality of the Quaternion