1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| template <typename T>
struct EaseInEaseOutInterpolation;
template <typename T>
struct EaseInEaseOutInterpolationDispatch
{
// http://math.stackexchange.com/questions/121720/ease-in-out-function
static T get(const T& begin, const T& end, float interp)
{
float interp2 = interp*interp;
return (interp2 / (interp2 + (1 - interp)*(1 - interp))) * (end-begin)+begin;
}
protected:
template<class U>
using impl = typename std::conditional<
std::is_same<T, U>::value
, EaseInEaseOutInterpolationDispatch
, EaseInEaseOutInterpolation<T>
>::type;
};
template <typename T>
struct EaseInEaseOutInterpolation
{
protected:
static T get(const T& begin, const T& end, float interp)
{
return EaseInEaseOutInterpolationDispatch<T>::template impl<T>::get(begin, end, interp);
}
};
template <>
struct EaseInEaseOutInterpolation<Angle>
: protected EaseInEaseOutInterpolationDispatch<Angle>
{
protected:
static Angle get(const Angle& begin, const Angle& end, float interp)
{
// http://stackoverflow.com/questions/2708476/rotation-interpolation
Angle diff = end-begin;
Angle fixedBegin = begin;
Angle fixedEnd = end;
if ( diff > 180 ) // Here, normal interpolation will take the longest path
{
fixedBegin += 360;
}
else if ( diff < -180 )
{
fixedEnd += 360;
}
Angle result = EaseInEaseOutInterpolationDispatch<Angle>::impl<float>::get(begin,end,interp);
// Wrap angle
while ( result > 360 )
{
result -= 360.f;
}
while ( result < -360 )
{
result += 360.f;
}
return result;
}
}; |
Partager