aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/helpers/BezierCurve.cpp
diff options
context:
space:
mode:
authorvaxerski <[email protected]>2022-04-23 21:47:16 +0200
committervaxerski <[email protected]>2022-04-23 21:47:16 +0200
commit3ebe7d79722c1bdc333b236960ff136ab607a02c (patch)
tree2f6c0de1534bc789ba91e7dceca155988cfa1e2c /src/helpers/BezierCurve.cpp
parent306d163613c6940e73ad58e852b42cdb236a5bc4 (diff)
downloadHyprland-3ebe7d79722c1bdc333b236960ff136ab607a02c.tar.gz
Hyprland-3ebe7d79722c1bdc333b236960ff136ab607a02c.zip
Added bezier curves
Diffstat (limited to 'src/helpers/BezierCurve.cpp')
-rw-r--r--src/helpers/BezierCurve.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/helpers/BezierCurve.cpp b/src/helpers/BezierCurve.cpp
new file mode 100644
index 00000000..845992bd
--- /dev/null
+++ b/src/helpers/BezierCurve.cpp
@@ -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);
+} \ No newline at end of file