Browse Source

Fixed ticket #48, improved SLERP interpolation

Christophe Riccio 14 years ago
parent
commit
144caa18d5
3 changed files with 83 additions and 2 deletions
  1. 13 1
      glm/gtc/quaternion.inl
  2. 17 1
      glm/gtx/quaternion.hpp
  3. 53 0
      glm/gtx/quaternion.inl

+ 13 - 1
glm/gtc/quaternion.inl

@@ -326,7 +326,7 @@ namespace quaternion{
 	        q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z,
 	        q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x);
     }
-
+/*
 	// (x * sin(1 - a) * angle / sin(angle)) + (y * sin(a) * angle / sin(angle))
     template <typename T>
     GLM_FUNC_QUALIFIER detail::tquat<T> mix
@@ -406,6 +406,18 @@ namespace quaternion{
 		
         return normalize(beta * x + alpha * y);
     }
+*/
+    template <typename T>
+    GLM_FUNC_QUALIFIER detail::tquat<T> mix
+	(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a
+	)
+    {
+		T angle = acos(dot(x, y));
+		return (sin((1 - a) * angle) * x + sin(a * angle) * y) / sin(angle);
+	}
 
     template <typename T> 
     GLM_FUNC_QUALIFIER detail::tquat<T> conjugate

+ 17 - 1
glm/gtx/quaternion.hpp

@@ -109,7 +109,7 @@ namespace glm
 			detail::tquat<valType> const & q, 
 			detail::tvec4<valType> const & v);
 		
-        //! Returns the q rotation angle. 
+        //! Returns the quaternion rotation angle. 
 		//! From GLM_GTX_quaternion extension.
 		template <typename valType> 
 		valType angle(
@@ -191,6 +191,22 @@ namespace glm
 		detail::tquat<valType> toQuat(
 			detail::tmat4x4<valType> const & x){return gtc::quaternion::quat_cast(x);}
 
+		//! Quaternion interpolation using the rotation short path. 
+		//! From GLM_GTX_quaternion extension.
+		template <typename T>
+		detail::tquat<T> shortMix(
+			detail::tquat<T> const & x, 
+			detail::tquat<T> const & y, 
+			T const & a);
+
+		//! Quaternion normalized linear interpolation. 
+		//! From GLM_GTX_quaternion extension.
+		template <typename T>
+		detail::tquat<T> fastMix(
+			detail::tquat<T> const & x, 
+			detail::tquat<T> const & y, 
+			T const & a);
+
 		///@}
 
     }//namespace quaternion

+ 53 - 0
glm/gtx/quaternion.inl

@@ -245,6 +245,59 @@ namespace quaternion
         return detail::tvec3<valType>(pitch(x), yaw(x), roll(x));
     }
 
+    template <typename T>
+    GLM_FUNC_QUALIFIER detail::tquat<T> shortMix
+	(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a
+	)
+    {
+        if(a <= typename detail::tquat<T>::value_type(0)) return x;
+        if(a >= typename detail::tquat<T>::value_type(1)) return y;
+
+        float fCos = dot(x, y);
+        detail::tquat<T> y2(y); //BUG!!! tquat<T> y2;
+        if(fCos < typename detail::tquat<T>::value_type(0))
+        {
+            y2 = -y;
+            fCos = -fCos;
+        }
+
+        //if(fCos > 1.0f) // problem
+        float k0, k1;
+        if(fCos > typename detail::tquat<T>::value_type(0.9999))
+        {
+            k0 = typename detail::tquat<T>::value_type(1) - a;
+            k1 = typename detail::tquat<T>::value_type(0) + a; //BUG!!! 1.0f + a;
+        }
+        else
+        {
+            typename detail::tquat<T>::value_type fSin = sqrt(T(1) - fCos * fCos);
+            typename detail::tquat<T>::value_type fAngle = atan(fSin, fCos);
+            typename detail::tquat<T>::value_type fOneOverSin = T(1) / fSin;
+            k0 = sin((typename detail::tquat<T>::value_type(1) - a) * fAngle) * fOneOverSin;
+            k1 = sin((typename detail::tquat<T>::value_type(0) + a) * fAngle) * fOneOverSin;
+        }
+
+        return detail::tquat<T>(
+            k0 * x.w + k1 * y2.w,
+            k0 * x.x + k1 * y2.x,
+            k0 * x.y + k1 * y2.y,
+            k0 * x.z + k1 * y2.z);
+	}
+
+    template <typename T>
+    GLM_FUNC_QUALIFIER detail::tquat<T> fastMix
+	(
+		detail::tquat<T> const & x, 
+		detail::tquat<T> const & y, 
+		T const & a
+	)
+    {
+		return glm::normalize(x * (1 - a) + (y * a));
+	}
+
 }//namespace quaternion
 }//namespace gtx
 }//namespace glm