mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-07-23 21:34:30 +08:00
backport quaternion slerp precision fix
This commit is contained in:
parent
f36650b00a
commit
72fc81dd9d
@ -450,22 +450,31 @@ inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
|
|||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const
|
Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const
|
||||||
{
|
{
|
||||||
static const Scalar one = Scalar(1) - precision<Scalar>();
|
static const Scalar one = Scalar(1) - machine_epsilon<Scalar>();
|
||||||
Scalar d = this->dot(other);
|
Scalar d = this->dot(other);
|
||||||
Scalar absD = ei_abs(d);
|
Scalar absD = ei_abs(d);
|
||||||
|
|
||||||
|
Scalar scale0;
|
||||||
|
Scalar scale1;
|
||||||
|
|
||||||
if (absD>=one)
|
if (absD>=one)
|
||||||
return *this;
|
{
|
||||||
|
scale0 = Scalar(1) - t;
|
||||||
|
scale1 = t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// theta is the angle between the 2 quaternions
|
||||||
|
Scalar theta = std::acos(absD);
|
||||||
|
Scalar sinTheta = ei_sin(theta);
|
||||||
|
|
||||||
// theta is the angle between the 2 quaternions
|
scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
||||||
Scalar theta = std::acos(absD);
|
scale1 = ei_sin( ( t * theta) ) / sinTheta;
|
||||||
Scalar sinTheta = ei_sin(theta);
|
if (d<0)
|
||||||
|
scale1 = -scale1;
|
||||||
|
}
|
||||||
|
|
||||||
Scalar scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
|
||||||
Scalar scale1 = ei_sin( ( t * theta) ) / sinTheta;
|
|
||||||
if (d<0)
|
|
||||||
scale1 = -scale1;
|
|
||||||
|
|
||||||
return Quaternion(scale0 * m_coeffs + scale1 * other.m_coeffs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set from a rotation matrix
|
// set from a rotation matrix
|
||||||
|
Loading…
x
Reference in New Issue
Block a user