Browse Source

Added tests for slerp function

Christophe Riccio 13 years ago
parent
commit
29805391bd
5 changed files with 75 additions and 42 deletions
  1. 10 10
      glm/gtc/epsilon.hpp
  2. 0 30
      glm/gtc/epsilon.inl
  3. 2 2
      glm/gtc/quaternion.inl
  4. 1 0
      readme.txt
  5. 62 0
      test/gtc/gtc_quaternion.cpp

+ 10 - 10
glm/gtc/epsilon.hpp

@@ -57,11 +57,11 @@ namespace glm
 	/// Returns the component-wise compare of |x - y| < epsilon.
 	/// Returns the component-wise compare of |x - y| < epsilon.
 	/// @see gtc_epsilon
 	/// @see gtc_epsilon
 	template <typename genType>
 	template <typename genType>
-    typename genType::boolType epsilonEqual(
-        genType const & x,
-        genType const & y,
-        typename genType::value_type const & epsilon);
-    
+	typename genType::boolType epsilonEqual(
+		genType const & x,
+		genType const & y,
+		typename genType::value_type const & epsilon);
+
 	/// Returns the component-wise compare of |x - y| < epsilon.
 	/// Returns the component-wise compare of |x - y| < epsilon.
 	/// @see gtc_epsilon
 	/// @see gtc_epsilon
 	template <typename genType> 
 	template <typename genType> 
@@ -73,11 +73,11 @@ namespace glm
 	/// Returns the component-wise compare of |x - y| < epsilon.
 	/// Returns the component-wise compare of |x - y| < epsilon.
 	/// @see gtc_epsilon
 	/// @see gtc_epsilon
 	template <typename genType>
 	template <typename genType>
-    typename genType::boolType epsilonNotEqual(
-        genType const & x,
-        genType const & y,
-        typename genType::value_type const & epsilon);
-    
+	typename genType::boolType epsilonNotEqual(
+		genType const & x,
+		genType const & y,
+		typename genType::value_type const & epsilon);
+
 	/// Returns the component-wise compare of |x - y| >= epsilon.
 	/// Returns the component-wise compare of |x - y| >= epsilon.
 	/// @see gtc_epsilon
 	/// @see gtc_epsilon
 	template <typename genType>
 	template <typename genType>

+ 0 - 30
glm/gtc/epsilon.inl

@@ -269,21 +269,6 @@ namespace glm
 			abs(x.w - y.w) < epsilon);
 			abs(x.w - y.w) < epsilon);
 	}
 	}
 
 
-	template <typename valType>
-	GLM_FUNC_QUALIFIER detail::tvec4<bool> epsilonEqual
-	(
-		detail::tquat<valType> const & x, 
-		detail::tquat<valType> const & y, 
-		detail::tquat<valType> const & epsilon
-	)
-	{
-		return detail::tvec4<bool>(
-			abs(x.x - y.x) < epsilon.x,
-			abs(x.y - y.y) < epsilon.y,
-			abs(x.z - y.z) < epsilon.z,
-			abs(x.w - y.w) < epsilon.w);
-	}
-
 	template <typename valType>
 	template <typename valType>
 	GLM_FUNC_QUALIFIER detail::tvec4<bool> epsilonNotEqual
 	GLM_FUNC_QUALIFIER detail::tvec4<bool> epsilonNotEqual
 	(
 	(
@@ -298,19 +283,4 @@ namespace glm
 			abs(x.z - y.z) >= epsilon,
 			abs(x.z - y.z) >= epsilon,
 			abs(x.w - y.w) >= epsilon);
 			abs(x.w - y.w) >= epsilon);
 	}
 	}
-
-	template <typename valType>
-	GLM_FUNC_QUALIFIER detail::tvec4<bool> epsilonNotEqual
-	(
-		detail::tquat<valType> const & x, 
-		detail::tquat<valType> const & y, 
-		detail::tquat<valType> const & epsilon
-	)
-	{
-		return detail::tvec4<bool>(
-			abs(x.x - y.x) >= epsilon.x,
-			abs(x.y - y.y) >= epsilon.y,
-			abs(x.z - y.z) >= epsilon.z,
-			abs(x.w - y.w) >= epsilon.w);
-	}
 }//namespace glm
 }//namespace glm

+ 2 - 2
glm/gtc/quaternion.inl

@@ -468,7 +468,7 @@ namespace detail
 		{
 		{
 			// Essential Mathematics, page 467
 			// Essential Mathematics, page 467
 			T angle = acos(cosTheta);
 			T angle = acos(cosTheta);
-			return (sin((T(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle);
+			return (sin((T(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle);
 		}
 		}
 	}
 	}
 
 
@@ -658,7 +658,7 @@ namespace detail
 		typename detail::tquat<T>::value_type fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2];
 		typename detail::tquat<T>::value_type fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2];
 		typename detail::tquat<T>::value_type fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1];
 		typename detail::tquat<T>::value_type fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1];
 		typename detail::tquat<T>::value_type fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2];
 		typename detail::tquat<T>::value_type fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2];
-        
+
 		int biggestIndex = 0;
 		int biggestIndex = 0;
 		typename detail::tquat<T>::value_type fourBiggestSquaredMinus1 = fourWSquaredMinus1;
 		typename detail::tquat<T>::value_type fourBiggestSquaredMinus1 = fourWSquaredMinus1;
 		if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
 		if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)

+ 1 - 0
readme.txt

@@ -47,6 +47,7 @@ GLM 0.9.4.1: 2012-12-21
 - Fixed quat slerp using mix function when cosTheta close to 1
 - Fixed quat slerp using mix function when cosTheta close to 1
 - Improved fvec4SIMD and fmat4x4SIMD implementations
 - Improved fvec4SIMD and fmat4x4SIMD implementations
 - Fixed assert messages
 - Fixed assert messages
+- Added slerp and lerp quaternion functions and tests
 
 
 ================================================================================
 ================================================================================
 GLM 0.9.4.0: 2012-11-18
 GLM 0.9.4.0: 2012-11-18

+ 62 - 0
test/gtc/gtc_quaternion.cpp

@@ -144,6 +144,67 @@ int test_quat_euler()
 	return Error;
 	return Error;
 }
 }
 
 
+int test_quat_slerp()
+{
+	int Error(0);
+
+	float const Epsilon = 0.0001f;//glm::epsilon<float>();
+
+	float sqrt2 = sqrt(2.0f)/2.0f;
+	glm::quat id;
+	glm::quat Y90rot(sqrt2, 0.0f, sqrt2, 0.0f);
+	glm::quat Y180rot(0.0f, 0.0f, 1.0f, 0.0f);
+
+	// Testing a == 0
+	// Must be id
+	glm::quat id2 = glm::slerp(id, Y90rot, 0.0f);
+	Error += glm::all(glm::epsilonEqual(id, id2, Epsilon)) ? 0 : 1;
+
+	// Testing a == 1
+	// Must be 90° rotation on Y : 0 0.7 0 0.7
+	glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f);
+	Error += glm::all(glm::epsilonEqual(Y90rot, Y90rot2, Epsilon)) ? 0 : 1;
+
+	// Testing standard, easy case
+	// Must be 45° rotation on Y : 0 0.38 0 0.92
+	glm::quat Y45rot1 = glm::slerp(id, Y90rot, 0.5f);
+
+	// Testing reverse case
+	// Must be 45° rotation on Y : 0 0.38 0 0.92
+	glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.5f);
+
+	// Testing against full circle around the sphere instead of shortest path
+	// Must be 45° rotation on Y
+	// certainly not a 135° rotation
+	glm::quat Y45rot3 = glm::slerp(id , -Y90rot, 0.5f);
+	float Y45angle3 = glm::angle(Y45rot3);
+	Error += glm::epsilonEqual(Y45angle3, 45.f, Epsilon) ? 0 : 1;
+	Error += glm::all(glm::epsilonEqual(Ym45rot2, Y45rot3, Epsilon)) ? 0 : 1;
+
+	// Same, but inverted
+	// Must also be 45° rotation on Y :  0 0.38 0 0.92
+	// -0 -0.38 -0 -0.92 is ok too
+	glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f);
+	Error += glm::all(glm::epsilonEqual(Ym45rot2, -Y45rot4, Epsilon)) ? 0 : 1;
+
+	// Testing q1 = q2
+	// Must be 90° rotation on Y : 0 0.7 0 0.7
+	glm::quat Y90rot3 = glm::slerp(Y90rot, Y90rot, 0.5f);
+	Error += glm::all(glm::epsilonEqual(Y90rot, Y90rot3, Epsilon)) ? 0 : 1;
+
+	// Testing 180° rotation
+	// Must be 90° rotation on almost any axis that is on the XZ plane
+	glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f);
+	float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78;
+	Error += glm::epsilonEqual(XZ90angle, 45.f, Epsilon) ? 0 : 1;
+
+	// Testing almost equal quaternions (this test should pass through the linear interpolation)
+	// Must be 0 0.00X 0 0.99999
+	glm::quat almostid = glm::slerp(id, glm::angleAxis(0.1f, 0.0f, 1.0f, 0.0f), 0.5f);
+
+	return Error;
+}
+
 int test_quat_type()
 int test_quat_type()
 {
 {
 	glm::quat A;
 	glm::quat A;
@@ -163,6 +224,7 @@ int main()
 	Error += test_quat_mix();
 	Error += test_quat_mix();
 	Error += test_quat_normalize();
 	Error += test_quat_normalize();
 	Error += test_quat_euler();
 	Error += test_quat_euler();
+	Error += test_quat_slerp();
 
 
 	return Error;
 	return Error;
 }
 }