1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-10-25 09:27:01 +00:00
Files
CLK/Numeric/CubicCurve.hpp
2025-10-04 22:26:09 -04:00

70 lines
1.7 KiB
C++

//
// CubicCurve.hpp
// Clock Signal
//
// Created by Thomas Harte on 04/10/2025.
// Copyright © 2025 Thomas Harte. All rights reserved.
//
#pragma once
#include <cassert>
/*!
Provides a cubic Bezier-based timing function.
*/
struct CubicCurve {
CubicCurve(const float c1x, const float c1y, const float c2x, const float c2y) :
c1(c1x, c1y), c2(c2x, c2y)
{
assert(0.0f <= c1x); assert(c1x <= 1.0f);
assert(0.0f <= c1y); assert(c1y <= 1.0f);
assert(0.0f <= c2x); assert(c2x <= 1.0f);
assert(0.0f <= c2y); assert(c2y <= 1.0f);
}
/// @returns A standard ease-in-out animation curve.
static CubicCurve easeInOut() {
return CubicCurve(0.42f, 0.0f, 0.58f, 1.0f);
}
/// @returns The value for y given x, in range [0.0, 1.0].
float value(const float x) const {
return axis(t(x), 1);
}
private:
/// @returns The value for @c t that generates the value @c x.
float t(const float x) const {
static constexpr float Precision = 0.01f;
float bounds[2] = {0.0f, 1.0f};
const auto midpoint = [&] { return (bounds[0] + bounds[1]) * 0.5f; };
while(bounds[1] > bounds[0] + Precision) {
const float mid = midpoint();
const float value = axis(mid, 0);
if(value > x) {
bounds[1] = mid;
} else {
bounds[0] = mid;
}
}
return midpoint();
}
/// @returns The value for axis @c index at time @c t.
float axis(const float t, int index) const {
const float f1 = t * c1[index];
const float f2 = t * c2[index] + (1.0f - t) * c1[index];
const float f3 = t + (1.0f - t) * c2[index];
const float c1 = t * f2 + (1.0f - t) * f1;
const float c2 = t * f3 + (1.0f - t) * f2;
return t * c2 + (1.0f - t) * c1;
}
float c1[2];
float c2[2];
};