bezier 通用函数

/*
    缓动插值

    全套缓动函数的 js 实现
    https://www.jianshu.com/p/ddff577138bf
    缓动函数图形说明
    http://www.xuanfengge.com/easeing/easeing/
*/
#pragma once
#include "gstl.h"

class GachaEase
{
public:
    static float getEasePercent(float pct,const string& strEaseFunc);

    static float linear(float pct);

    static float easeInSine(float pct);
    static float easeOutSine(float pct);
    static float easeInOutSine(float pct);
    
    static float easeInQuad(float pct);
    static float easeOutQuad(float pct);
    static float easeInOutQuad(float pct);
    
    static float easeInCubic(float pct);
    static float easeOutCubic(float pct);
    static float easeInOutCubic(float pct);

    static float easeInQuart(float pct);
    static float easeOutQuart(float pct);
    static float easeInOutQuart(float pct);

    static float easeInOutBack(float pct);
    static float easeInElastic(float pct);

    static float easeInBack(float pct);
    static float easeOutBack(float pct);

    static float easeOutBounce(float pct);


    static float easeInCirc(float pct);
    static float easeOutCirc(float pct);
    static float easeInOutCirc(float pct);
    


private:
    static float bounceOut(float pct);
public:
    const static float PI;
    const static float c1;
    const static float c2;
    const static float c3;
    const static float c4;
    const static float c5;
};
#include "GachaEase.h"
#include <map>
#include <functional>

#define REGIST_EASE_FUNC(ease_name)    funcmap.insert(std::make_pair(#ease_name, std::bind(GachaEase::ease_name, std::placeholders::_1)))

const float GachaEase::PI = 3.1415926;
const float GachaEase::c1 = 1.70158;
const float GachaEase::c2 = c1 * 1.525;
const float GachaEase::c3 = c1 + 1;
const float GachaEase::c4 = (2 * PI) / 3;
const float GachaEase::c5 = (2 * PI) / 4.5;

static std::map<string, std::function<float(float)>>    funcmap;

/*static*/ float clampf(float& v, float min, float max)
{
    if (v < min) v = min;
    if (v > max) v = max;
    return v;
}

static void initFuncMap()
{
    //funcmap.insert(std::make_pair("linear", std::bind(GachaEase::linear, std::placeholders::_1)));
    REGIST_EASE_FUNC(linear);

    REGIST_EASE_FUNC(easeInSine);
    REGIST_EASE_FUNC(easeOutSine);
    REGIST_EASE_FUNC(easeInOutSine);

    REGIST_EASE_FUNC(easeInQuad);
    REGIST_EASE_FUNC(easeOutQuad);
    REGIST_EASE_FUNC(easeInOutQuad);

    REGIST_EASE_FUNC(easeInCubic);
    REGIST_EASE_FUNC(easeOutCubic);
    REGIST_EASE_FUNC(easeInOutCubic);

    REGIST_EASE_FUNC(easeInQuart);
    REGIST_EASE_FUNC(easeOutQuart);
    REGIST_EASE_FUNC(easeInOutQuart);

    REGIST_EASE_FUNC(easeInOutBack);
    REGIST_EASE_FUNC(easeInElastic);

    REGIST_EASE_FUNC(easeInBack);
    REGIST_EASE_FUNC(easeOutBack);

    REGIST_EASE_FUNC(easeOutBounce);
}

float GachaEase::getEasePercent(float pct, const string& strEaseFunc)
{
    if (funcmap.empty())
    {
        initFuncMap();
    }

    auto it = funcmap.find(strEaseFunc);
    if (it != funcmap.end())
    {
        float fEasePct = it->second(pct);
        return fEasePct;
    }
    return linear(pct);
}

float GachaEase::linear(float pct)
{
    return clampf(pct, 0.f, 1.f);
}

float GachaEase::easeInCubic(float pct)
{
    clampf(pct, 0.f, 1.f);
    pct = pct * pct * pct;
    return pct;
}

float GachaEase::easeOutCubic(float pct)
{
    clampf(pct, 0.f, 1.f);
    return 1 - pow(1 - pct, 3);
}

float GachaEase::easeInOutCubic(float pct)
{
    clampf(pct, 0.f, 1.f);
    if (pct < 0.5)
    {
        return 4 * pct * pct * pct;
    }
    else
    {
        return 1 - pow(-2 * pct + 2, 3) / 2;
    }
}


float GachaEase::easeInOutBack(float pct)
{
    clampf(pct, 0.f, 1.f);
    pct = pct < 0.5 ?
        (pow(2 * pct, 2)*((c2 + 1) * 2 * pct - c2)) / 2 :
        (pow(2 * pct - 2, 2)*((c2 + 1)*(pct * 2 - 2) + c2) + 2) / 2;
    return pct;
}

float GachaEase::easeInElastic(float pct)
{

    clampf(pct, 0.f, 1.f);
    if (pct <= 0.f)
    {
        return 0;
    }
    if (pct >= 1.f)
    {
        return 1;
    }
    return -pow(2, 10 * pct - 10)* sin((pct * 10 - 10.75)* c4);
}



float GachaEase::easeInSine(float pct)
{
    clampf(pct, 0.f, 1.f);
    return 1 - cos(pct * PI / 2);
}

float GachaEase::easeOutSine(float pct)
{
    clampf(pct, 0.f, 1.f);
    return sin(pct * PI / 2);
}

float GachaEase::easeInOutSine(float pct)
{
    clampf(pct, 0.f, 1.f);
    return -(cos(PI * pct) - 1) / 2;
}

float GachaEase::easeInQuad(float pct)
{
    clampf(pct, 0.f, 1.f);
    return pct * pct;
}


float GachaEase::easeOutQuad(float pct)
{
    clampf(pct, 0.f, 1.f);
    return 1 - (1 - pct)*(1 - pct);
}


float GachaEase::easeInOutQuad(float pct)
{
    clampf(pct, 0.f, 1.f);
    if (pct < 0.5)
    {
        return 2 * pct * pct;
    }
    else
    {
        return 1 - pow(-2 * pct + 2, 2) / 2;
    }
}

float GachaEase::easeInQuart(float pct)
{
    clampf(pct, 0.f, 1.f);
    return pct * pct * pct * pct;
}

float GachaEase::easeOutQuart(float pct)
{
    clampf(pct, 0.f, 1.f);
    return 1 - pow(1 - pct, 4);
}

float GachaEase::easeInOutQuart(float pct)
{
    clampf(pct, 0.f, 1.f);
    if (pct < 0.5)
    {
        return 8 * pct * pct * pct * pct;
    }
    else
    {
        return 1 - pow(-2 * pct + 2, 4) / 2;
    }
}

float GachaEase::easeInBack(float pct)
{
    clampf(pct, 0.f, 1.f);
    return c3 * pct * pct * pct - c1 * pct * pct;
}

float GachaEase::easeOutBack(float pct)
{
    return 1 + c3 * pow(pct - 1, 3) + c1 * pow(pct - 1, 2);
}

float GachaEase::easeOutBounce(float pct)
{
    return bounceOut(pct);
}

float GachaEase::bounceOut(float pct)
{
    float n1 = 7.5625;

    float d1 = 2.75;

    if (pct < 1 / d1) {

        return n1*pct*pct;

    }
    else if (pct < 2 / d1) {

        return n1*(pct -= (1.5 / d1))*pct + .75;

    }
    else if (pct < 2.5 / d1) {

        return n1*(pct -= (2.25 / d1))*pct + .9375;
    }
    else {
        return n1*(pct -= (2.625 / d1))*pct + .984375;
    }
}
原文地址:https://www.cnblogs.com/zijian-yang/p/13273702.html