Index: quaternion.h =================================================================== RCS file: /cvsroot/celestia/celestia/src/celmath/quaternion.h,v retrieving revision 1.7 diff -r1.7 quaternion.h 47c47 < static Quaternion slerp(Quaternion, Quaternion, T); --- > static Quaternion slerp(const Quaternion&, const Quaternion&, T); 533,535c533,538 < //! Spherical interpolation of two unit quaternions < template Quaternion Quaternion::slerp(Quaternion q0, < Quaternion q1, --- > /*! Spherical linear interpolation of two unit quaternions. Designed for > * interpolating rotations, so shortest path between rotations will be > * taken. > */ > template Quaternion Quaternion::slerp(const Quaternion& q0, > const Quaternion& q1, 538c541 < T c = dot(q0, q1); --- > const double Nlerp_Threshold = 0.99999; 540,544c543 < // Because of potential rounding errors, we must clamp c to the domain of acos. < if (c > (T) 1.0) < c = (T) 1.0; < else if (c < (T) -1.0) < c = (T) -1.0; --- > T cosAngle = dot(q0, q1); 546c545,557 < T angle = (T) acos(c); --- > // Assuming the quaternions representat rotations, ensure that we interpolate > // through the shortest path by inverting one of the quaternions if the > // angle between them is negative. > Quaternion qstart; > if (cosAngle < 0) > { > qstart = -q0; > cosAngle = -cosAngle; > } > else > { > qstart = q0; > } 548,549c559,583 < if (abs(angle) < (T) 1.0e-5) < return q0; --- > // Avoid precision troubles when we're near the limit of acos range and > // perform a linear interpolation followed by a normalize when interpolating > // very small angles. > if (cosAngle > (T) Nlerp_Threshold) > { > Quaternion q = (1 - t) * qstart + t * q1; > q.normalize(); > return q; > } > > // Below code unnecessary since we've already inverted cosAngle if it's negative. > // It will be necessary if we change slerp to not assume that we want the shortest > // path between two rotations. > #if 0 > // Because of potential rounding errors, we must clamp c to the domain of acos. > if (cosAngle < (T) -1.0) > cosAngle = (T) -1.0; > #endif > > T angle = (T) acos(cosAngle); > T interpolatedAngle = t * angle; > > // qstart and q2 will form an orthonormal basis in the plane of interpolation. > Quaternion q2 = q1 - qstart * cosAngle; > q2.normalize(); 550a585,586 > return qstart * (T) cos(interpolatedAngle) + q2 * (T) sin(interpolatedAngle); > #if 0 555a592 > #endif