### Use LERP interpolation for infinitesimally small angles instead of SLERP

```To avoid division by zero, perform a linear interpolation (LERP), if our
quarternions are nearly in the same direction, otherwise resort
to spherical linear interpolation. In the limiting case (for small
angles), SLERP is equivalent to LERP.```
parent c2af1618
 ... ... @@ -17,6 +17,8 @@ #include "vtkMath.h" #include #define VTKQUATERNIONINTERPOLATOR_TOLERNCE 1e-6 vtkStandardNewMacro(vtkQuaternionInterpolator); //---------------------------------------------------------------------------- ... ... @@ -111,7 +113,7 @@ struct vtkQuaternion q = vtkMath::DegreesFromRadians( q ); } // compute unit vector where q is a unit quaternion static void UnitVector(double q, double &theta, double &sinTheta, static void UnitVector(double q, double &theta, double &sinTheta, double &cosTheta, double v) { double norm = sqrt(q*q + q*q + q*q); ... ... @@ -262,7 +264,7 @@ void vtkQuaternionInterpolator::AddQuaternion(double t, double q) break; } }//for not in the right spot this->Modified(); } ... ... @@ -283,7 +285,7 @@ void vtkQuaternionInterpolator::RemoveQuaternion(double t) { this->QuaternionList->erase(iter); } this->Modified(); } ... ... @@ -291,12 +293,29 @@ void vtkQuaternionInterpolator::RemoveQuaternion(double t) //Interpolate using spherical linear interpolation between the quaternions q0 //and q1 to produce the output q. The parametric coordinate t is [0,1] and //lies between (q0,q1). void vtkQuaternionInterpolator::Slerp(double t, double q0, double q1, void vtkQuaternionInterpolator::Slerp(double t, double q0, double q1, double q) { double theta = acos( vtkMath::Dot(q0+1,q1+1) ); double t1 = sin((1.0-t)*theta)/sin(theta); double t2 = sin(t*theta)/sin(theta); const double dot = vtkMath::Dot(q0+1,q1+1); double t1, t2; // To avoid division by zero, perform a linear interpolation (LERP), if our // quarternions are nearly in the same direction, otherwise resort // to spherical linear interpolation. In the limiting case (for small // angles), SLERP is equivalent to LERP. if ((1.0 - fabs(dot)) < VTKQUATERNIONINTERPOLATOR_TOLERNCE) { t1 = 1.0-t; t2 = t; } else { const double theta = acos( dot ); t1 = sin((1.0-t)*theta)/sin(theta); t2 = sin(t*theta)/sin(theta); } q = q0*t1 + q1*t2; q = q0*t1 + q1*t2; q = q0*t1 + q1*t2; ... ... @@ -305,14 +324,14 @@ void vtkQuaternionInterpolator::Slerp(double t, double q0, double q1, //---------------------------------------------------------------------------- void vtkQuaternionInterpolator::InnerPoint(double q0, double q1, void vtkQuaternionInterpolator::InnerPoint(double q0, double q1, double q2, double q) { double qInv, qL, qR; vtkQuaternion::Inverse(q1,qInv); vtkQuaternion::Product(qInv,q2,qL); vtkQuaternion::Product(qInv,q0,qR); double qLLog, qRLog, qSum, qExp; vtkQuaternion::UnitLog(qL, qLLog); vtkQuaternion::UnitLog(qR, qRLog); ... ... @@ -354,13 +373,13 @@ void vtkQuaternionInterpolator::InterpolateQuaternion(double t, double q) { if ( iter->Time <= t && t <= nextIter->Time ) { double T = (t - iter->Time) / (nextIter->Time - iter->Time); double T = (t - iter->Time) / (nextIter->Time - iter->Time); this->Slerp(T,iter->Q,nextIter->Q,q); break; } } }//if linear quaternion interpolation else // this->InterpolationType == INTERPOLATION_TYPE_SPLINE { QuaternionListIterator iter = this->QuaternionList->begin(); ... ... @@ -374,11 +393,11 @@ void vtkQuaternionInterpolator::InterpolateQuaternion(double t, double q) { if ( iter->Time <= t && t <= nextIter->Time ) { T = (t - iter->Time) / (nextIter->Time - iter->Time); T = (t - iter->Time) / (nextIter->Time - iter->Time); break; } } double ai, bi, qc, qd; if ( i == 0 ) //initial interval { ... ... @@ -390,7 +409,7 @@ void vtkQuaternionInterpolator::InterpolateQuaternion(double t, double q) ai = iter1->QUnit; ai = iter1->QUnit; ai = iter1->QUnit; this->InnerPoint(iter1->QUnit, iter2->QUnit, iter3->QUnit, bi); } else if ( i == (numQuats-2) ) //final interval ... ... @@ -433,8 +452,8 @@ void vtkQuaternionInterpolator::PrintSelf(ostream& os, vtkIndent indent) os << indent << "There are " << this->GetNumberOfQuaternions() << " quaternions to be interpolated\n"; os << indent << "Interpolation Type: " os << indent << "Interpolation Type: " << (this->InterpolationType == INTERPOLATION_TYPE_LINEAR ? "Linear\n" : "Spline\n"); } ... ...
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!