Newer
Older
Import / applications / HighwayDash / ports / Framework / Animation.cpp
#include "Animation.h"
#include <cmath>
#include <unordered_map>
#include <string>


typedef std::unordered_map<std::string, CurveFunction> CurveFunctionMap;
CurveFunctionMap g_curveFunctionMap;
struct CurveMapIniter {
  void map(const char* str, CurveFunction func) {
    g_curveFunctionMap.insert(std::make_pair(str, func));
  }
  CurveMapIniter() {
    printf("creating curve function mapper\n");
    map("square",           &squareCurve);
    map("linear",           &linearCurve);
    map("easeIn",           &easeInCurve);
    map("easeOut",          &easeOutCurve);
    map("easeInOut",        &easeInOutCurve);
    map("easeOutIn",        &easeOutInCurve);
    map("easeInBack",       &easeInBackCurve);
    map("easeOutBack",      &easeOutBackCurve);
    map("easeInOutBack",    &easeInOutBackCurve);
    map("easeOutInBack",    &easeOutInBackCurve);
    map("easeInBounce",     &easeInBounceCurve);
    map("easeOutBounce",    &easeOutBounceCurve);
    map("easeInOutBounce",  &easeInOutBounceCurve);
    map("easeOutInBounce",  &easeOutInBounceCurve);
    map("easeInElastic;",   &easeInElasticCurve);
    map("easeOutElastic",   &easeOutElasticCurve);
    map("easeInOutElastic", &easeInOutElasticCurve);
    map("easeOutInElastic", &easeOutInElasticCurve);
} } g_initCurveMapper;


bool LookupCurveFunction(const char* curveName, CurveFunction& curveFunction)
{
  if (g_curveFunctionMap.count(curveName)) {
    curveFunction = g_curveFunctionMap[curveName];
    return true;
  }
  return false;
}


float EvaluateCurve(const char* curveName, float ratio)
{
  if (g_curveFunctionMap.count(curveName))
    return g_curveFunctionMap[curveName](ratio);
  return 1.0f;
}


inline float square(float ratio)
{
  //return powf(ratio, 2.0f);
  return ratio * ratio;
}

inline float inOutHelper(float ratio, CurveFunction inCurve, CurveFunction outCurve)
{
  if (ratio < 0.5f)
    return 0.5f * inCurve(ratio*2.0f);
  return 0.5f * outCurve((ratio-0.5f)*2.0f) + 0.5f;
}

float squareCurve(float ratio)
{
  if (ratio < 0.5f)
    return 0.0f;
  return 1.0f;
}

float linearCurve(float ratio)
{
  return ratio;
}

float easeInCurve(float ratio)
{
  return ratio * ratio * ratio;
}

float easeOutCurve(float ratio)
{
  float invRatio = ratio - 1.0f;
  return invRatio * invRatio * invRatio + 1.0f;
}

float easeInOutCurve(float ratio)
{
  return inOutHelper(ratio, easeInCurve, easeOutCurve);
}

float easeOutInCurve(float ratio)
{
  return inOutHelper(ratio, easeOutCurve, easeInCurve);
}

float easeInBackCurve(float ratio)
{
  float s = 1.70158f;
  return square(ratio) * ((s + 1.0f)*ratio - s);    
}

float easeOutBackCurve(float ratio)
{
  float invRatio = ratio - 1.0f;
  float s = 1.70158f;
  return square(invRatio) * ((s + 1.0f)*invRatio + s) + 1.0f;    
}

float easeInOutBackCurve(float ratio)
{
  return inOutHelper(ratio, easeInBackCurve, easeOutBackCurve);
}

float easeOutInBackCurve(float ratio)
{
  return inOutHelper(ratio, easeOutBackCurve, easeInBackCurve);
}

float easeInBounceCurve(float ratio)
{
  return 1.0f - easeOutBounceCurve(1.0f - ratio);
}

float easeOutBounceCurve(float ratio)
{
  const float s = 7.5625f;
  const float p = 2.75f;
  if (ratio < (1.0f/p))
    return s * square(ratio);
  if (ratio < (2.0f/p))
    return s * square(ratio - 1.5f/p) + 0.75f;
  if (ratio < 2.5f/p)
    return s * square(ratio - 2.25f/p) + 0.9375f;
  return s * square(ratio - 2.625f/p) + 0.984375f;
}

float easeInOutBounceCurve(float ratio)
{
  return inOutHelper(ratio, easeInBounceCurve, easeOutBounceCurve);
}

float easeOutInBounceCurve(float ratio)
{
  return inOutHelper(ratio, easeOutBounceCurve, easeInBounceCurve);
}

float easeInElasticCurve(float ratio)
{
  if (ratio == 0.0f || ratio == 1.0f)
    return ratio;
  float p = 0.3f;
  float s = p / 4.0f;
  float invRatio = ratio - 1.0f;
  return -1.0f * powf(2.0f, 10.0f*invRatio) * sinf((invRatio-s)*2.0f*M_PI/p);        
}

float easeOutElasticCurve(float ratio)
{
  if (ratio == 0.0f || ratio == 1.0f)
    return ratio;
  float p = 0.3f;
  float s = p / 4.0f;
  return powf(2.0f, -10.0f*ratio) * sinf((ratio-s)*2.0f*M_PI/p) + 1.0f;
}

float easeInOutElasticCurve(float ratio)
{
  return inOutHelper(ratio, easeInElasticCurve, easeOutElasticCurve);
}

float easeOutInElasticCurve(float ratio)
{
  return inOutHelper(ratio, easeOutElasticCurve, easeInElasticCurve);
}