#pragma once
#include "gstl.h"
#include <vector>
#include "SmoothSampling.h"
using namespace gstl;
/*
n阶 bezier 曲线通用公式
*/
class GachaBazier
{
public:
GachaBazier(const Vector2<f32>& start,const Vector2<f32>& dest);
void addCtrlPoint(const Vector2<f32>& ctrlPoint);
Vector2<f32> getInterpolatePos(float t);
private:
float getKanbudong(float n, float i);
float getJieCheng(int n);
private:
Vector2<f32> m_start;
Vector2<f32> m_dest;
std::vector<Vector2<f32>> m_ctrl;
};
class GachaBezierSmooth : public BoloScriptFastLib,public GachaBazier
{
generatedBoloObject(GachaBezierSmooth,"GachaBezierSmooth");
GachaBezierSmooth();
virtual ~GachaBezierSmooth();
public:
void sampling(int fSamplingNum = 100);
float getSmoothY(float fx);
vec2 getMinSampling();
vec2 getMaxSampling();
void setStart(vec2 tStart);
void setEnd(vec2 tEnd);
private:
SmoothSampling m_tSmoothSampling;
// 网页上 看到的 起始点和目标点都是 写死的 0,0 1,1 两个点, 对应返回的百分比需要按比例变大变小
vec2 m_tStart;
vec2 m_tEnd;
};
/*
3次贝塞尔曲线差值器
http://cubic-bezier.com
css3 3次贝塞尔曲线 cubic-bezier
https://blog.csdn.net/zhaozjc112/article/details/52909172/
起点永远算作 (0,0) 终点永远算作 (1,1)
控制点有且只有2个
(m_x1,m_y1) (m_x2,m_y2)
*/
class GachaCubicBezierInter
{
public:
GachaCubicBezierInter();
~GachaCubicBezierInter();
void setPt1(float x,float y);
void setPt2(float x,float y);
void prepare();
f32 getY(float x);
private:
Vector2<f32> m_pt1;
Vector2<f32> m_pt2;
GachaBazier* m_bezier = nullptr;
};
#include "GachaBezierInter.h"
#include <math.h>
#include <cassert>
extern float clampf(float& v, float min, float max);
GachaBazier::GachaBazier(const Vector2<f32>& start, const Vector2<f32>& dest)
{
m_start = start;
m_dest = dest;
m_ctrl.push_back(m_start);
m_ctrl.push_back(m_dest);
}
void GachaBazier::addCtrlPoint(const Vector2<f32>& point) {
Vector2<f32> pt = point;
size_t len = m_ctrl.size();
m_ctrl.insert(m_ctrl.begin() + len - 1, pt);
}
Vector2<f32> GachaBazier::getInterpolatePos(float t)
{
//t = clampf(t, -1.f, 1.f);
if (t < -1.f)
{
printf("dddaaa\n");
}
if (t < 0.f)
{
printf("fsfdsa\n");
}
if (t > 1.f)
{
printf("ddd\n");
}
Vector2<f32> pt;
assert(m_ctrl.size() >= 2);
int n = m_ctrl.size() - 1;
for (int i = 0; i <= n; i++) {
pt.x += getKanbudong(n, i) * pow((1 - t), n - i) * pow(t, i) * m_ctrl[i].x;
pt.y += getKanbudong(n, i) * pow((1 - t), n - i) * pow(t, i) * m_ctrl[i].y;
}
return pt;
}
float GachaBazier::getKanbudong(float n, float i) {
return getJieCheng(n) / (getJieCheng(i) * getJieCheng(n - i));
}
float GachaBazier::getJieCheng(int n) {
float result = 1.0f;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
//////////////////////////////////////////////////////////////////////////
GachaBezierSmooth::~GachaBezierSmooth()
{
}
GachaBezierSmooth::GachaBezierSmooth() : GachaBazier(vec2::zero, vec2(1.f, 1.f))
{
}
void GachaBezierSmooth::setStart(vec2 tStart)
{
m_tStart = tStart;
}
void GachaBezierSmooth::setEnd(vec2 tEnd)
{
m_tEnd = tEnd;
}
void GachaBezierSmooth::sampling(int fSamplingNum)
{
// 需要添加对应的采样点
float fDelay = 1.f / fSamplingNum;
for (float i = 0.f; i < 1.f; i += fDelay)
{
vec2 tVec2 = getInterpolatePos(i);
tVec2 = (m_tEnd - m_tStart) * tVec2 + m_tStart;
m_tSmoothSampling.insertPoint(tVec2.x, tVec2.y);
}
}
float GachaBezierSmooth::getSmoothY(float fx)
{
return m_tSmoothSampling.getSmooth(fx);
}
vec2 GachaBezierSmooth::getMinSampling()
{
auto it = m_tSmoothSampling.m_sortMpSampling.begin();
if (it == m_tSmoothSampling.m_sortMpSampling.end())
{
return vec2::zero;
}
return vec2(it->first, it->second);
}
vec2 GachaBezierSmooth::getMaxSampling()
{
if (m_tSmoothSampling.m_sortMpSampling.size() <= 0)
{
return vec2::zero;
}
auto it = m_tSmoothSampling.m_sortMpSampling.end();
it--;
return vec2(it->first, it->second);
}
SC_Entry GachaBezierSmooth_setStart(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
float fx = bolo_float(stack);
float fy = bolo_float(stack);
pGachaBezierSmooth->setStart(vec2(fx, fy));
return SC_Entry();
}
SC_Entry GachaBezierSmooth_setEnd(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
float fx = bolo_float(stack);
float fy = bolo_float(stack);
pGachaBezierSmooth->setEnd(vec2(fx, fy));
return SC_Entry();
}
SC_Entry GachaBezierSmooth_addCtrlPoint(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
float fx = bolo_float(stack);
float fy = bolo_float(stack);
pGachaBezierSmooth->addCtrlPoint(vec2(fx, fy));
return SC_Entry();
}
SC_Entry GachaBezierSmooth_sampling(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
int nSamplingNum = bolo_int(stack);
pGachaBezierSmooth->sampling(nSamplingNum);
return SC_Entry();
}
SC_Entry GachaBezierSmooth_getSmoothY(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
float fx = bolo_float(stack);
return pGachaBezierSmooth->getSmoothY(fx);
}
SC_Entry GachaBezierSmooth_getMinSampling(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
vec2 tPos = pGachaBezierSmooth->getMinSampling();
SC_Entry* pVec = new SC_Entry[2]
{
tPos.x, tPos.y
};
return SC_Entry(pVec, 2);
}
SC_Entry GachaBezierSmooth_getMaxSampling(BoloScriptFast* stack, BoloScriptFastLib* ptr)
{
GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
vec2 tPos = pGachaBezierSmooth->getMaxSampling();
SC_Entry* pVec = new SC_Entry[2]
{
tPos.x, tPos.y
};
return SC_Entry(pVec, 2);
}
void GachaBezierSmooth::registerReflection(s32 id)
{
registerFunc(id, "setStart", GachaBezierSmooth_setStart);
registerFunc(id, "setEnd", GachaBezierSmooth_setEnd);
registerFunc(id, "addCtrlPoint", GachaBezierSmooth_addCtrlPoint);
registerFunc(id, "sampling", GachaBezierSmooth_sampling);
registerFunc(id, "getSmoothY", GachaBezierSmooth_getSmoothY);
registerFunc(id, "getMinSampling", GachaBezierSmooth_getMinSampling);
registerFunc(id, "getMaxSampling", GachaBezierSmooth_getMaxSampling);
}
///////////////////////////////
GachaCubicBezierInter::GachaCubicBezierInter()
{
m_pt1.x = 0.f;
m_pt1.y = 0.f;
m_pt2.x = 1.f;
m_pt2.y = 1.f;
Vector2<f32> start(0.f, 0.f);
Vector2<f32> dest(1.f,1.f);
m_bezier = new GachaBazier(start,dest);
}
GachaCubicBezierInter::~GachaCubicBezierInter()
{
delete m_bezier;
m_bezier = nullptr;
}
f32 GachaCubicBezierInter::getY(float x)
{
Vector2<f32> pos = m_bezier->getInterpolatePos(x);
return pos.y;
}
void GachaCubicBezierInter::setPt1(float x, float y)
{
m_pt1.x = x;
m_pt1.y = y;
}
void GachaCubicBezierInter::setPt2(float x, float y)
{
m_pt2.x = x;
m_pt2.y = y;
}
void GachaCubicBezierInter::prepare()
{
m_bezier->addCtrlPoint(m_pt1);
m_bezier->addCtrlPoint(m_pt2);
}