Przeglądaj źródła

Added fast* trig methods to Math

Marko Pintera 12 lat temu
rodzic
commit
0f7bd6ed50

+ 233 - 1
CamelotUtility/Include/CmMath.h

@@ -39,7 +39,7 @@ namespace CamelotFramework
 		static Radian acos(float val);
 		static Radian asin(float val);
 		static Radian atan(float val) { return Radian(std::atan(val)); }
-		static Radian tan2(float y, float x) { return Radian(std::atan2(y,x)); }
+		static Radian atan2(float y, float x) { return Radian(std::atan2(y,x)); }
 
         static float cos(const Radian& val) { return (float)std::cos(val.valueRadians()); }
         static float cos(float val) { return (float)std::cos(val); }
@@ -116,6 +116,238 @@ namespace CamelotFramework
         static Vector3 calculateTriTangent(const Vector3& position1, const Vector3& position2, 
 			const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3);
 
+		/************************************************************************/
+		/* 							TRIG APPROXIMATIONS                      	*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastSin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
+
+		/**
+		 * @brief	Sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastSin0(float val);
+
+		/**
+		 * @brief	Sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastSin0".
+		 */
+		static float fastSin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
+
+		/**
+		 * @brief	Sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastSin0".
+		 */
+		static float fastSin1(float val);
+
+		/**
+		 * @brief	Cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastCos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
+
+		/**
+		 * @brief	Cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastCos0(float val);
+
+		/**
+		 * @brief	Cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastCos0".
+		 */
+		static float fastCos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
+
+		/**
+		 * @brief	Cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastCos0".
+		 */
+		static float fastCos1(float val);
+
+		/**
+		 * @brief	Tangent function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastTan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
+
+		/**
+		 * @brief	Tangent function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastTan0(float val);
+
+		/**
+		 * @brief	Tangent function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastTan0".
+		 */
+		static float fastTan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
+
+		/**
+		 * @brief	Tangent function approximation.
+		 *
+		 * @param	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastTan0".
+		 */
+		static float fastTan1(float val);
+
+		/**
+		 * @brief	Inverse sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastASin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
+
+		/**
+		 * @brief	Inverse sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastASin0(float val);
+
+		/**
+		 * @brief	Inverse sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastASin0".
+		 */
+		static float fastASin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
+
+		/**
+		 * @brief	Inverse sine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastASin0".
+		 */
+		static float fastASin1(float val);
+
+		/**
+		 * @brief	Inverse cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastACos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
+
+		/**
+		 * @brief	Inverse cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastACos0(float val);
+
+		/**
+		 * @brief	Inverse cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastACos0".
+		 */
+		static float fastACos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
+
+		/**
+		 * @brief	Inverse cosine function approximation.
+		 *
+		 * @param	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastACos0".
+		 */
+		static float fastACos1(float val);
+
+		/**
+		 * @brief	Inverse tangent function approximation.
+		 *
+		 * @param	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastATan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
+
+		/**
+		 * @brief	Inverse tangent function approximation.
+		 *
+		 * @param	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastATan0(float val);
+
+		/**
+		 * @brief	Inverse tangent function approximation.
+		 *
+		 * @param	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastATan0".
+		 */
+		static float fastATan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
+
+		/**
+		 * @brief	Inverse tangent function approximation.
+		 *
+		 * @param	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 * 			Slightly better (and slower) than "fastATan0".
+		 */
+		static float fastATan1(float val);
+
         static const float POS_INFINITY;
         static const float NEG_INFINITY;
         static const float PI;

+ 205 - 0
CamelotUtility/Source/CmMath.cpp

@@ -91,6 +91,211 @@ namespace CamelotFramework
 		return 1.0f/sqrt(val);
 	}
 
+	float Math::fastSin0(float val)
+	{
+		float angleSqr = val*val;
+		float result = 7.61e-03f;
+		result *= angleSqr;
+		result -= 1.6605e-01f;
+		result *= angleSqr;
+		result += 1.0f;
+		result *= val;
+		return result;
+	}
+
+	float Math::fastSin1(float val)
+	{
+		float angleSqr = val*val;
+		float result = -2.39e-08f;
+		result *= angleSqr;
+		result += 2.7526e-06f;
+		result *= angleSqr;
+		result -= 1.98409e-04f;
+		result *= angleSqr;
+		result += 8.3333315e-03f;
+		result *= angleSqr;
+		result -= 1.666666664e-01f;
+		result *= angleSqr;
+		result += 1.0f;
+		result *= val;
+
+		return result;
+	}
+
+	float Math::fastCos0(float val)
+	{
+		float angleSqr = val*val;
+		float result = 3.705e-02f;
+		result *= angleSqr;
+		result -= 4.967e-01f;
+		result *= angleSqr;
+		result += 1.0f;
+
+		return result;
+	}
+
+	float Math::fastCos1(float val)
+	{
+		float angleSqr = val*val;
+		float result = -2.605e-07f;
+		result *= angleSqr;
+		result += 2.47609e-05f;
+		result *= angleSqr;
+		result -= 1.3888397e-03f;
+		result *= angleSqr;
+		result += 4.16666418e-02f;
+		result *= angleSqr;
+		result -= 4.999999963e-01f;
+		result *= angleSqr;
+		result += 1.0f;
+
+		return result;
+	}
+
+	float Math::fastTan0(float val)
+	{
+		float angleSqr = val*val;
+		float result = 2.033e-01f;
+		result *= angleSqr;
+		result += 3.1755e-01f;
+		result *= angleSqr;
+		result += 1.0f;
+		result *= val;
+		return result;
+	}
+
+	float Math::fastTan1(float val)
+	{
+		float angleSqr = val*val;
+		float result = 9.5168091e-03f;
+		result *= angleSqr;
+		result += 2.900525e-03f;
+		result *= angleSqr;
+		result += 2.45650893e-02f;
+		result *= angleSqr;
+		result += 5.33740603e-02f;
+		result *= angleSqr;
+		result += 1.333923995e-01f;
+		result *= angleSqr;
+		result += 3.333314036e-01f;
+		result *= angleSqr;
+		result += 1.0f;
+		result *= val;
+		return result;
+	}
+
+	float Math::fastASin0(float val)
+	{
+		float root = sqrt(abs(1.0f - val));
+		float result = -0.0187293f;
+		result *= val;
+		result += 0.0742610f;
+		result *= val;
+		result -= 0.2121144f;
+		result *= val;
+		result += 1.5707288f;
+		result = HALF_PI - root*result;
+		return result;
+	}
+
+	float Math::fastASin1(float val)
+	{
+		float root = sqrt(abs(1.0f - val));
+		float result = -0.0012624911f;
+		result *= val;
+		result += 0.0066700901f;
+		result *= val;
+		result -= 0.0170881256f;
+		result *= val;
+		result += 0.0308918810f;
+		result *= val;
+		result -= 0.0501743046f;
+		result *= val;
+		result += 0.0889789874f;
+		result *= val;
+		result -= 0.2145988016f;
+		result *= val;
+		result += 1.5707963050f;
+		result = HALF_PI - root*result;
+		return result;
+	}
+
+	float Math::fastACos0(float val)
+	{
+		float root = sqrt(abs(1.0f - val));
+		float result = -0.0187293f;
+		result *= val;
+		result += 0.0742610f;
+		result *= val;
+		result -= 0.2121144f;
+		result *= val;
+		result += 1.5707288f;
+		result *= root;
+		return result;
+	}
+
+	float Math::fastACos1(float val)
+	{
+		float root = sqrt(abs(1.0f - val));
+		float result = -0.0012624911f;
+		result *= val;
+		result += 0.0066700901f;
+		result *= val;
+		result -= 0.0170881256f;
+		result *= val;
+		result += 0.0308918810f;
+		result *= val;
+		result -= 0.0501743046f;
+		result *= val;
+		result += 0.0889789874f;
+		result *= val;
+		result -= 0.2145988016f;
+		result *= val;
+		result += 1.5707963050f;
+		result *= root;
+		return result;
+	}
+
+	float Math::fastATan0(float val)
+	{
+		float valueSqr = val*val;
+		float result = 0.0208351f;
+		result *= valueSqr;
+		result -= 0.085133f;
+		result *= valueSqr;
+		result += 0.180141f;
+		result *= valueSqr;
+		result -= 0.3302995f;
+		result *= valueSqr;
+		result += 0.999866f;
+		result *= val;
+		return result;
+	}
+
+	float Math::fastATan1(float val)
+	{
+		float valueSqr = val*val;
+		float result = 0.0028662257f;
+		result *= valueSqr;
+		result -= 0.0161657367f;
+		result *= valueSqr;
+		result += 0.0429096138f;
+		result *= valueSqr;
+		result -= 0.0752896400f;
+		result *= valueSqr;
+		result += 0.1065626393f;
+		result *= valueSqr;
+		result -= 0.1420889944f;
+		result *= valueSqr;
+		result += 0.1999355085f;
+		result *= valueSqr;
+		result -= 0.3333314528f;
+		result *= valueSqr;
+		result += 1.0f;
+		result *= val;
+		return result;
+	}
+
     bool Math::approxEquals(float a, float b, float tolerance)
     {
         if (fabs(b-a) <= tolerance)

+ 8 - 8
CamelotUtility/Source/CmMatrix3.cpp

@@ -788,15 +788,15 @@ namespace CamelotFramework
         {
             if (xAngle > Radian(-Math::HALF_PI))
             {
-                yAngle = Math::tan2(-m[1][2], m[2][2]);
-                zAngle = Math::tan2(-m[0][1], m[0][0]);
+                yAngle = Math::atan2(-m[1][2], m[2][2]);
+                zAngle = Math::atan2(-m[0][1], m[0][0]);
 
                 return true;
             }
             else
             {
                 // WARNING.  Not a unique solution.
-                Radian angle = Math::tan2(m[1][0],m[1][1]);
+                Radian angle = Math::atan2(m[1][0],m[1][1]);
                 zAngle = Radian(0.0f);  // Any angle works
                 yAngle = zAngle - angle;
 
@@ -806,7 +806,7 @@ namespace CamelotFramework
         else
         {
             // WARNING.  Not a unique solution.
-            Radian angle = Math::tan2(m[1][0],m[1][1]);
+            Radian angle = Math::atan2(m[1][0],m[1][1]);
             zAngle = Radian(0.0f);  // Any angle works
             yAngle = angle - zAngle;
 
@@ -823,15 +823,15 @@ namespace CamelotFramework
 		{
 			if (xAngle > Radian(-Math::HALF_PI))
 			{
-				yAngle = Math::tan2(-l.sign * m[l.b][l.c], m[l.c][l.c]);
-				zAngle = Math::tan2(-l.sign * m[l.a][l.b], m[l.a][l.a]);
+				yAngle = Math::atan2(-l.sign * m[l.b][l.c], m[l.c][l.c]);
+				zAngle = Math::atan2(-l.sign * m[l.a][l.b], m[l.a][l.a]);
 
 				return true;
 			}
 			else
 			{
 				// WARNING.  Not a unique solution.
-				Radian angle = Math::tan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
+				Radian angle = Math::atan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
 				zAngle = Radian(0.0f);  // Any angle works
 				yAngle = zAngle - angle;
 
@@ -841,7 +841,7 @@ namespace CamelotFramework
 		else
 		{
 			// WARNING.  Not a unique solution.
-			Radian angle = Math::tan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
+			Radian angle = Math::atan2(l.sign * m[l.b][l.a], m[l.b][l.b]);
 			zAngle = Radian(0.0f);  // Any angle works
 			yAngle = angle - zAngle;
 

+ 1 - 1
CamelotUtility/Source/CmQuaternion.cpp

@@ -348,7 +348,7 @@ namespace CamelotFramework
         {
             // Standard case (slerp)
             float sin = Math::sqrt(1 - Math::sqr(cos));
-            Radian angle = Math::tan2(sin, cos);
+            Radian angle = Math::atan2(sin, cos);
             float invSin = 1.0f / sin;
             float coeff0 = Math::sin((1.0f - t) * angle) * invSin;
             float coeff1 = Math::sin(t * angle) * invSin;