Added bezier curves
This commit is contained in:
parent
306d163613
commit
3ebe7d7972
14 changed files with 255 additions and 67 deletions
|
|
@ -5,19 +5,20 @@ CAnimatedVariable::CAnimatedVariable() {
|
|||
; // dummy var
|
||||
}
|
||||
|
||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, float* speed, int64_t* enabled, void* pWindow) {
|
||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow) {
|
||||
m_eVarType = type;
|
||||
m_pSpeed = speed;
|
||||
m_pEnabled = enabled;
|
||||
m_pWindow = pWindow;
|
||||
m_pBezier = pBezier;
|
||||
|
||||
g_pAnimationManager->m_lAnimatedVariables.push_back(this);
|
||||
|
||||
m_bDummy = false;
|
||||
}
|
||||
|
||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, float* speed, int64_t* enabled, void* pWindow) {
|
||||
create(type, speed, enabled, pWindow);
|
||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow) {
|
||||
create(type, speed, enabled, pBezier, pWindow);
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ class CAnimatedVariable {
|
|||
public:
|
||||
CAnimatedVariable(); // dummy var
|
||||
|
||||
void create(ANIMATEDVARTYPE, float* speed, int64_t* enabled, void* pWindow);
|
||||
void create(ANIMATEDVARTYPE, std::any val, float* speed, int64_t* enabled, void* pWindow);
|
||||
void create(ANIMATEDVARTYPE, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow);
|
||||
void create(ANIMATEDVARTYPE, std::any val, float* speed, int64_t* enabled, std::string* pBezier, void* pWindow);
|
||||
|
||||
~CAnimatedVariable();
|
||||
|
||||
|
|
@ -60,34 +60,46 @@ public:
|
|||
void operator=(const Vector2D& v) {
|
||||
ASSERT(m_eVarType == AVARTYPE_VECTOR);
|
||||
m_vGoal = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
}
|
||||
|
||||
void operator=(const float& v) {
|
||||
ASSERT(m_eVarType == AVARTYPE_FLOAT);
|
||||
m_fGoal = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_fBegun = m_fValue;
|
||||
}
|
||||
|
||||
void operator=(const CColor& v) {
|
||||
ASSERT(m_eVarType == AVARTYPE_COLOR);
|
||||
m_cGoal = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_cBegun = m_cValue;
|
||||
}
|
||||
|
||||
// Sets the actual stored value, without affecting the goal
|
||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||
void setValue(const Vector2D& v) {
|
||||
ASSERT(m_eVarType == AVARTYPE_VECTOR);
|
||||
m_vValue = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
}
|
||||
|
||||
// Sets the actual stored value, without affecting the goal
|
||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||
void setValue(const float& v) {
|
||||
ASSERT(m_eVarType == AVARTYPE_FLOAT);
|
||||
m_fValue = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
}
|
||||
|
||||
// Sets the actual stored value, without affecting the goal
|
||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||
void setValue(const CColor& v) {
|
||||
ASSERT(m_eVarType == AVARTYPE_COLOR);
|
||||
m_cValue = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
}
|
||||
|
||||
// Sets the actual value and goal
|
||||
|
|
@ -140,12 +152,19 @@ private:
|
|||
float m_fGoal = 0;
|
||||
CColor m_cGoal;
|
||||
|
||||
Vector2D m_vBegun = Vector2D(0,0);
|
||||
float m_fBegun = 0;
|
||||
CColor m_cBegun;
|
||||
|
||||
float* m_pSpeed = nullptr;
|
||||
int64_t* m_pEnabled = nullptr;
|
||||
void* m_pWindow = nullptr;
|
||||
std::string* m_pBezier = nullptr;
|
||||
|
||||
bool m_bDummy = true;
|
||||
|
||||
std::chrono::system_clock::time_point animationBegin;
|
||||
|
||||
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
|
||||
|
||||
friend class CAnimationManager;
|
||||
|
|
|
|||
55
src/helpers/BezierCurve.cpp
Normal file
55
src/helpers/BezierCurve.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include "BezierCurve.hpp"
|
||||
|
||||
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
||||
m_dPoints.clear();
|
||||
|
||||
m_dPoints.emplace_back(Vector2D(0,0));
|
||||
|
||||
for (auto& p : *pVec) {
|
||||
m_dPoints.push_back(p);
|
||||
}
|
||||
|
||||
m_dPoints.emplace_back(Vector2D(1,1));
|
||||
|
||||
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: %i)", m_dPoints.size());
|
||||
|
||||
// bake 100 points for faster lookups
|
||||
// T -> X ( / 100 )
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
m_aPointsBaked[i] = getXForT((i + 1) / 100.f);
|
||||
}
|
||||
}
|
||||
|
||||
float CBezierCurve::getYForT(float t) {
|
||||
return 3 * t * pow(1 - t, 2) * m_dPoints[1].y + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].y + pow(t, 3);
|
||||
}
|
||||
|
||||
float CBezierCurve::getXForT(float t) {
|
||||
return 3 * t * pow(1 - t, 2) * m_dPoints[1].x + 3 * pow(t, 2) * (1 - t) * m_dPoints[2].x + pow(t, 3);
|
||||
}
|
||||
|
||||
// Todo: this probably can be done better and faster
|
||||
float CBezierCurve::getYForPoint(float x) {
|
||||
// binary search for the range UPDOWN X
|
||||
float upperX = 1;
|
||||
float lowerX = 0;
|
||||
float mid = 0.5;
|
||||
|
||||
while(std::abs(upperX - lowerX) > 0.01f) {
|
||||
if (m_aPointsBaked[((int)(mid * 100.f))] > x) {
|
||||
upperX = mid;
|
||||
} else {
|
||||
lowerX = mid;
|
||||
}
|
||||
|
||||
mid = (upperX + lowerX) / 2.f;
|
||||
}
|
||||
|
||||
// in the name of performance i shall make a hack
|
||||
const auto PERCINDELTA = (x - m_aPointsBaked[(int)(100.f * lowerX)]) / (m_aPointsBaked[(int)(100.f * upperX)] - m_aPointsBaked[(int)(100.f * lowerX)]);
|
||||
|
||||
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
|
||||
return 0.f;
|
||||
|
||||
return getYForT(mid + PERCINDELTA * 0.01f);
|
||||
}
|
||||
24
src/helpers/BezierCurve.hpp
Normal file
24
src/helpers/BezierCurve.hpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include <deque>
|
||||
|
||||
// an implementation of a cubic bezier curve
|
||||
// might do better later
|
||||
// TODO: n-point curves
|
||||
class CBezierCurve {
|
||||
public:
|
||||
// sets up the bezier curve.
|
||||
// this EXCLUDES the 0,0 and 1,1 points,
|
||||
void setup(std::vector<Vector2D>* points);
|
||||
|
||||
float getYForT(float t);
|
||||
float getXForT(float t);
|
||||
float getYForPoint(float x);
|
||||
|
||||
private:
|
||||
// this INCLUDES the 0,0 and 1,1 points.
|
||||
std::deque<Vector2D> m_dPoints;
|
||||
|
||||
std::array<float, 100> m_aPointsBaked;
|
||||
};
|
||||
|
|
@ -11,5 +11,17 @@ public:
|
|||
float r = 0, g = 0, b = 0, a = 255;
|
||||
|
||||
uint64_t getAsHex();
|
||||
|
||||
CColor operator- (const CColor& c2) const {
|
||||
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
|
||||
}
|
||||
|
||||
CColor operator+ (const CColor& c2) const {
|
||||
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
|
||||
}
|
||||
|
||||
CColor operator* (const float& v) const {
|
||||
return CColor(r * v, g * v, b * v, a * v);
|
||||
}
|
||||
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue