openlearner

06-13-2013, 08:23 AM

I'm looking at two different source for the Slerp method of interpolation between two quaternions. They are pretty similar except for one notable difference: one clamps the dot product between 0 and 1, and the other between -1 and 1. Here is one of them:

glm::fquat Slerp(const glm::fquat &v0, const glm::fquat &v1, float alpha)

{

float dot = glm::dot(v0, v1);

const float DOT_THRESHOLD = 0.9995f;

if (dot > DOT_THRESHOLD)

return Lerp(v0, v1, alpha);

glm::clamp(dot, -1.0f, 1.0f); //<-- The line in question

float theta_0 = acosf(dot);

float theta = theta_0*alpha;

glm::fquat v2 = v1 - v0*dot;

v2 = glm::normalize(v2);

return v0*cos(theta) + v2*sin(theta);

}

Here is the other:

template <typename T>

inline QuaternionT<T> QuaternionT<T>::Slerp(T t, const QuaternionT<T>& v1) const

{

const T epsilon = 0.0005f;

T dot = Dot(v1);

if (dot > 1 - epsilon) {

QuaternionT<T> result = v1 + (*this - v1).Scaled(t);

result.Normalize();

return result;

}

if (dot < 0) //<-The lower clamp

dot = 0;

if (dot > 1)

dot = 1;

T theta0 = std::acos(dot);

T theta = theta0 * t;

QuaternionT<T> v2 = (v1 - Scaled(dot));

v2.Normalize();

QuaternionT<T> q = Scaled(std::cos(theta)) + v2.Scaled(std::sin(theta));

q.Normalize();

return q;

}

I think it is worth noting also the the Lerp algorithm in the second one doesn't seem right for all cases?

I just want some feedback on these differences and if they really matter at all.

glm::fquat Slerp(const glm::fquat &v0, const glm::fquat &v1, float alpha)

{

float dot = glm::dot(v0, v1);

const float DOT_THRESHOLD = 0.9995f;

if (dot > DOT_THRESHOLD)

return Lerp(v0, v1, alpha);

glm::clamp(dot, -1.0f, 1.0f); //<-- The line in question

float theta_0 = acosf(dot);

float theta = theta_0*alpha;

glm::fquat v2 = v1 - v0*dot;

v2 = glm::normalize(v2);

return v0*cos(theta) + v2*sin(theta);

}

Here is the other:

template <typename T>

inline QuaternionT<T> QuaternionT<T>::Slerp(T t, const QuaternionT<T>& v1) const

{

const T epsilon = 0.0005f;

T dot = Dot(v1);

if (dot > 1 - epsilon) {

QuaternionT<T> result = v1 + (*this - v1).Scaled(t);

result.Normalize();

return result;

}

if (dot < 0) //<-The lower clamp

dot = 0;

if (dot > 1)

dot = 1;

T theta0 = std::acos(dot);

T theta = theta0 * t;

QuaternionT<T> v2 = (v1 - Scaled(dot));

v2.Normalize();

QuaternionT<T> q = Scaled(std::cos(theta)) + v2.Scaled(std::sin(theta));

q.Normalize();

return q;

}

I think it is worth noting also the the Lerp algorithm in the second one doesn't seem right for all cases?

I just want some feedback on these differences and if they really matter at all.