Browse Source

Easing Functions

Adds the function mEase() that can be used to ease progressive values from starting point to an ending point.
greenfire27 4 years ago
parent
commit
52a5e4b0a1

+ 78 - 0
engine/source/math/mMathFn.cc

@@ -67,4 +67,82 @@ U32 getBinLog2(U32 io_num)
    return U32(shiftCount - 1);
    return U32(shiftCount - 1);
 }
 }
 
 
+F32 mEase(const EasingFunction &ease, const F32 &progress)
+{
+	//Animation progress should be between 0 and 1. Result may go past 0 or 1 depending on the animation.
+	F32 r = mClampF(progress, 0.0f, 1.0f);
+	switch (ease)
+	{
+		case EasingFunction::EaseIn:
+			r = 1 - mCos((r * M_PI_F) / 2);
+			break;
+		case EasingFunction::EaseOut:
+			r = mSin((r * M_PI_F) / 2);
+			break;
+		case EasingFunction::EaseInOut:
+			r = -(mCos(M_PI_F * r) - 1) / 2;
+			break;
+		case EasingFunction::EaseInBack:
+			r = r * r * ((2.70158 * r) - 1.70158);
+			break;
+		case EasingFunction::EaseOutBack:
+			r = 1 + (--r) * r * ((2.70158 * r) + 1.70158);
+			break;
+		case EasingFunction::EaseInOutBack:
+			if (r < 0.5f)
+			{
+				r = r * r * ((7 * r) - 2.5) * 2;
+			}
+			else
+			{
+				r = 1 + (--r) * r * 2 * ((7 * r) + 2.5);
+			}
+			break;
+		case EasingFunction::EaseInElastic:
+			if (r < 1 || r > 0)
+			{
+				const F32 c = (2 * M_PI_F) / 3;
+				r = -mPow(2.0f, (10 * r) - 10) * mSin(((r * 10) - 10.75) * c);
+			}
+			break;
+		case EasingFunction::EaseOutElastic:
+			if (r < 1 || r > 0)
+			{
+				const F32 c = (2 * M_PI_F) / 3;
+				r = (mPow(2.0f, -10 * r) * mSin(((r * 10) - 0.75) * c)) + 1;
+			}
+			break;
+		case EasingFunction::EaseInOutElastic:
+			if (r < 1 || r > 0)
+			{
+				const F32 c = (2 * M_PI_F) / 4.5;
+				if (r < 0.5f)
+				{
+					r = -(mPow(2.0f, (20 * r) - 10) * mSin(((r * 20) - 11.125) * c)) / 2;
+				}
+				else
+				{
+					r = ((mPow(2.0f, (-20 * r) + 10) * mSin(((r * 20) - 11.125) * c)) / 2) + 1;
+				}
+			}
+			break;
+		case EasingFunction::EaseInBounce:
+			r = mPow(2, 6 * (r - 1)) * mFabs(mSin(r * M_PI_F * 3.5f));
+			break;
+		case EasingFunction::EaseOutBounce:
+			r = 1 - mPow(2, -6 * r) * mFabs(mCos(r * M_PI_F * 3.5f));
+			break;
+		case EasingFunction::EaseInOutBounce:
+			if (r < 0.5f)
+			{
+				r = 8 * mPow(2, 8 * (r - 1)) * mFabs(mSin(r * M_PI_F * 7.0f));
+			}
+			else
+			{
+				r = 1 - (8 * mPow(2, -8 * r) * mFabs(mSin(r * M_PI_F * 7.0f)));
+			}
+			break;
+	}
+	return r;
+}
 
 

+ 44 - 0
engine/source/math/mMathFn.h

@@ -31,6 +31,10 @@
 #include "math/mConstants.h"
 #include "math/mConstants.h"
 #endif
 #endif
 
 
+#ifndef _CONSOLE_H_
+#include "console/console.h"
+#endif
+
 #include <math.h>
 #include <math.h>
 
 
 // Remove a couple of annoying macros, if they are present (In VC 6, they are.)
 // Remove a couple of annoying macros, if they are present (In VC 6, they are.)
@@ -658,4 +662,44 @@ inline void mGetMinMax(const F32& a, const F32& b, F32& min, F32& max) { if ( mG
 /// Swap.
 /// Swap.
 inline void mSwap(F32& a, F32& b) { F32 temp = b; b = a; a = temp; }
 inline void mSwap(F32& a, F32& b) { F32 temp = b; b = a; a = temp; }
 
 
+//list of possible ways to ease progress
+enum EasingFunction
+{
+	Linear,
+	EaseIn,
+	EaseOut,
+	EaseInOut,
+	EaseInBack,
+	EaseOutBack,
+	EaseInOutBack,
+	EaseInElastic,
+	EaseOutElastic,
+	EaseInOutElastic,
+	EaseInBounce,
+	EaseOutBounce,
+	EaseInOutBounce
+};
+
+static EnumTable::Enums easingEnums[] =
+{
+   { EasingFunction::Linear, "linear" },
+   { EasingFunction::EaseIn, "easeIn" },
+   { EasingFunction::EaseOut, "easeOut" },
+   { EasingFunction::EaseInOut, "easeInOut" },
+   { EasingFunction::EaseInBack, "easeInBack" },
+   { EasingFunction::EaseOutBack, "easeOutBack" },
+   { EasingFunction::EaseInOutBack, "easeInOutBack" },
+   { EasingFunction::EaseInElastic, "easeInElastic" },
+   { EasingFunction::EaseOutElastic, "easeOutElastic" },
+   { EasingFunction::EaseInOutElastic, "easeInOutElastic" },
+   { EasingFunction::EaseInBounce, "easeInBounce" },
+   { EasingFunction::EaseOutBounce, "easeOutBounce" },
+   { EasingFunction::EaseInOutBounce, "easeInOutBounce" }
+};
+static EnumTable gEasingTable(13, &easingEnums[0]);
+
+// Given linear time progress between 0 and 1, this returns animation progress, based on 
+// a selected easing function, between 0 and 1 (and possibly outside of 0 and 1 in some cases).
+F32 mEase(const EasingFunction &ease, const F32 &progress);
+
 #endif //_MMATHFN_H_
 #endif //_MMATHFN_H_

+ 23 - 0
engine/source/math/math_ScriptBinding.cc

@@ -382,4 +382,27 @@ ConsoleFunctionWithDocs( removeBitFromMask, ConsoleInt, 3, 3, ( mask, bit ))
 
 
 ConsoleFunctionGroupEnd(GeneralMath)
 ConsoleFunctionGroupEnd(GeneralMath)
 
 
+/*! Given a linear progress from 0 to 1, the ease function returns an "eased" version of that progress. The 
+	returned value might be outside of 0 and 1.
+	@param easeFunction The name of the easing function to use. Possible values include EaseIn, EaseOut, EaseInOut and postfix versions of Back, Elastic, and Bounce (i.e. EaseInBounce).
+	@param progress Linear progress from 0 to 1.
+	@return An eased progress from 0 to 1 (although the value might go outside of 0 and 1).
+*/
+ConsoleFunctionWithDocs(mEase, ConsoleFloat, 3, 3, (easeFunction, progress))
+{
+	F32 progress = 0.0;
+	if (argc >= 3)
+	{
+		progress = dAtof(argv[2]);
+	}
+	EasingFunction f = Linear;
+	for (U32 i = 0; i < (sizeof(easingEnums) / sizeof(EnumTable::Enums)); i++)
+	{
+		if (dStricmp(easingEnums[i].label, argv[1]) == 0)
+			f = (EasingFunction)easingEnums[i].index;
+	}
+
+	return mEase(f, progress);
+}
+
 /*! @} */ // group MathFunctions
 /*! @} */ // group MathFunctions