Correct CVector3f::slerp implementation

This commit is contained in:
Jack Andersen 2018-12-12 21:36:29 -10:00
parent 9799353b35
commit 7df9f9b7ec
2 changed files with 5 additions and 26 deletions

View File

@ -10,6 +10,7 @@
namespace zeus {
class CVector3d;
class CRelAngle;
class CVector3f {
public:
@ -145,7 +146,7 @@ public:
static CVector3f nlerp(const CVector3f& a, const CVector3f& b, float t) { return lerp(a, b, t).normalized(); }
static CVector3f slerp(const CVector3f& a, const CVector3f& b, float t);
static CVector3f slerp(const CVector3f& a, const CVector3f& b, CRelAngle clampAngle);
bool isNormalized() const { return std::fabs(1.f - magSquared()) < 0.01f; }

View File

@ -4,6 +4,7 @@
#include <cmath>
#include <cassert>
#include "zeus/Math.hpp"
#include "zeus/CRelAngle.hpp"
namespace zeus {
const CVector3f CVector3f::skOne(1.f);
@ -33,30 +34,7 @@ float CVector3f::getAngleDiff(const CVector3f& a, const CVector3f& b) {
return theta;
}
CVector3f CVector3f::slerp(const CVector3f& a, const CVector3f& b, float t) {
if (t <= 0.0f)
return a;
if (t >= 1.0f)
return b;
CVector3f ret;
float mag = std::sqrt(a.dot(a) * b.dot(b));
float prod = a.dot(b) / mag;
if (std::fabs(prod) < 1.0f) {
const double sign = (prod < 0.0f) ? -1.0f : 1.0f;
const double theta = acos(sign * prod);
const double s1 = sin(sign * t * theta);
const double d = 1.0 / sin(theta);
const double s0 = sin((1.0 - t) * theta);
ret = (a * s0 + b * s1) * d;
return ret;
}
return a;
CVector3f CVector3f::slerp(const CVector3f& a, const CVector3f& b, CRelAngle clampAngle) {
return a * std::cos(clampAngle) + a.cross(b).normalized().cross(a) * std::sin(clampAngle);
}
} // namespace zeus