Browse Source

Added slerp, lerp and mix functions for quaternions. Added, fixed and clarified documentation.

Christophe Riccio 13 years ago
parent
commit
912d1b1e81
3 changed files with 76 additions and 3 deletions
  1. 1 1
      glm/gtc/matrix_transform.hpp
  2. 35 2
      glm/gtc/quaternion.hpp
  3. 40 0
      glm/gtc/quaternion.inl

+ 1 - 1
glm/gtc/matrix_transform.hpp

@@ -88,7 +88,7 @@ namespace glm
 	/// @param m Input matrix multiplied by this rotation matrix.
 	/// @param angle Rotation angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise.
 	/// @param axis Rotation axis, recommanded to be normalized.
-	/// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double.
+	/// @tparam T Value type used to build the matrix. Supported: half, float or double.
 	/// @see gtc_matrix_transform
 	/// @see gtx_transform
 	/// @see - rotate(T angle, T x, T y, T z) 

+ 35 - 2
glm/gtc/quaternion.hpp

@@ -171,15 +171,48 @@ namespace detail
 		detail::tquat<T> const & q1, 
 		detail::tquat<T> const & q2);
 
-	/// Returns a SLERP interpolated quaternion of x and y according a. 
+	/// Spherical linear interpolation of two quaternions.
+	/// The interpolation is oriented and the rotation is performed at constant speed.
 	/// 
+	/// @param x A quaternion
+	/// @param y A quaternion
+	/// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1].
+	/// @tparam T Value type used to build the quaternion. Supported: half, float or double.
 	/// @see gtc_quaternion
 	template <typename T> 
 	detail::tquat<T> mix(
 		detail::tquat<T> const & x, 
 		detail::tquat<T> const & y, 
 		T const & a);
-		
+
+	/// Linear interpolation of two quaternions. 
+	/// The interpolation is oriented.
+	/// 
+	/// @param x A quaternion
+	/// @param y A quaternion
+	/// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1].
+	/// @tparam T Value type used to build the quaternion. Supported: half, float or double.
+	/// @see gtc_quaternion
+	template <typename T> 
+	detail::tquat<T> lerp(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a);
+
+	/// Spherical linear interpolation of two quaternions.
+	/// The interpolation always take the short path and the rotation is performed at constant speed.
+	/// 
+	/// @param x A quaternion
+	/// @param y A quaternion
+	/// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1].
+	/// @tparam T Value type used to build the quaternion. Supported: half, float or double.
+	/// @see gtc_quaternion
+	template <typename T> 
+	detail::tquat<T> slerp(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a);
+
 	/// Returns the q conjugate. 
 	/// 
 	/// @see gtc_quaternion

+ 40 - 0
glm/gtc/quaternion.inl

@@ -443,6 +443,7 @@ namespace detail
 		return normalize(beta * x + alpha * y);
 	}
 */
+
 	template <typename T>
 	GLM_FUNC_QUALIFIER detail::tquat<T> mix
 	(
@@ -450,6 +451,45 @@ namespace detail
 		detail::tquat<T> const & y, 
 		T const & a
 	)
+	{
+		T cosTheta = dot(x, y);
+
+		// Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
+		if(cosTheta > T(1) - epsilon<T>())
+		{
+			// Linear interpolation
+			return detail::tquat<T>(
+				mix(x.w, y.w, a),
+				mix(x.x, y.x, a),
+				mix(x.y, y.y, a),
+				mix(x.z, y.z, a));
+		}
+		else
+		{
+			// Essential Mathematics, page 467
+			T angle = acos(cosTheta);
+			return (sin((T(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle);
+		}
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tquat<T> lerp
+	(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a
+	)
+	{
+		return x * (T(1) - a) + (y * a);
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tquat<T> slerp
+	(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a
+	)
 	{
 		detail::tquat<T> z = y;