Oxygen Engine
Modern C++ 3D Engine using OpenGL
Loading...
Searching...
No Matches
curve.h
1#ifndef OE_UTIL_CURVE_H
2#define OE_UTIL_CURVE_H
3
4#include <algorithm>
5#include <glm/gtx/easing.hpp>
6
7namespace oe::util
8{
12 template <typename T>
13 concept CurveValueConcept = requires(T t)
14 {
15 {0.5f * t} -> std::convertible_to<T>;
16 {t + t} -> std::convertible_to<T>;
17 };
18
22 template <typename T>
23 concept CurvePositionConcept = requires(T t)
24 {
25 {t} -> std::convertible_to<float>;
26 };
27
31 template <typename T, typename V, typename P>
32 concept CurvePointConcept = requires(T t)
33 {
34 {t.value} -> std::convertible_to<V>;
35 {t.position} -> std::convertible_to<P>;
36 };
37
42 {
43 DIRECT,
44 HOLD_LAST,
45 LINEAR,
46 CUBIC
47 };
48
52 template <CurveValueConcept V, CurvePositionConcept P = float>
54 {
58
67 constexpr auto operator<=>(const CurvePoint& other) const
68 {
69 return position <=> other.position;
70 }
71
81 [[nodiscard]] constexpr static V interpolate(const CurvePoint& begin_point, const CurvePoint& end_point, const P ratio) noexcept
82 {
83 if (end_point.interpolation == CurveInterpolation::HOLD_LAST)
84 {
85 return begin_point.value;
86 }
87 else if (end_point.interpolation == CurveInterpolation::DIRECT)
88 {
89 return end_point.value;
90 }
91
92 P factor = (end_point.position != begin_point.position)
93 ? (ratio - begin_point.position) / (end_point.position - begin_point.position)
94 : 1.0f
95 ;
96
97 if (end_point.interpolation == CurveInterpolation::CUBIC)
98 {
99 factor = glm::cubicEaseInOut(factor);
100 }
101
102 return glm::mix(begin_point.value, end_point.value, factor);
103 };
104 };
105
112 {
118 template<CurveValueConcept V, CurvePositionConcept T>
120
129 template <typename Type>
130 using PointStorageType = std::vector<Type>;
131 };
132
156 template <CurveValueConcept V, CurvePositionConcept T = float, typename CurveSettingsType = CurveSettings>
157 struct Curve
158 {
159 using PointType = typename CurveSettingsType::template PointType<V, T>;
160 using ContainerType = typename CurveSettingsType::template PointStorageType<PointType>;
161
162 // We expect to have PointType.position and PointType.value
164
176 [[nodiscard]] constexpr V eval(const T x) const noexcept
177 {
178 assert(std::is_sorted(control_points.cbegin(), control_points.cend()));
179
180 if (control_points.size() == 0)
181 {
182 return {};
183 }
184
185 if (control_points.size() == 1)
186 {
187 return control_points.at(0).value;
188 }
189
190 const auto pos_final = std::find_if(control_points.cbegin(), control_points.cend(), [&x](const PointType& point)
191 {
192 return point.position > x;
193 });
194
195 // Position is before the first element, return first element
196 if (pos_final == control_points.cbegin())
197 {
198 return pos_final->value;
199 }
200
201 // Position not found (considered after last element), return last element
202 if (pos_final == control_points.cend())
203 {
204 return (pos_final-1)->value;
205 }
206
207 const auto pos_begin = pos_final-1;
208
209 return PointType::interpolate(*pos_begin, *pos_final, x);
210 }
211
213 };
214}
215
216#endif
Curve point (= keyframe) must have value and position members.
Definition curve.h:32
Curve point position (= abscissa) must be convertible to a floating point value.
Definition curve.h:23
Various utilities.
Definition node.h:15
CurveInterpolation
Interpolation mode between points.
Definition curve.h:42
@ HOLD_LAST
Hold last value.
@ DIRECT
No interpolation, directly switch to this value.
@ LINEAR
Do a linear interpolation between last value and this one.
@ CUBIC
Do a cubic interpolation between last value and this one.
Point on a curve, also called a keyframe in some contexts.
Definition curve.h:54
CurveInterpolation interpolation
How to interpolate between last point and this point.
Definition curve.h:57
static constexpr V interpolate(const CurvePoint &begin_point, const CurvePoint &end_point, const P ratio) noexcept
Interpolate Value between two points.
Definition curve.h:81
V value
Value of this point.
Definition curve.h:56
P position
Position of this point on the curve.
Definition curve.h:55
constexpr auto operator<=>(const CurvePoint &other) const
Three-way comparison operator.
Definition curve.h:67
Curve Advanced settings.
Definition curve.h:112
std::vector< Type > PointStorageType
The container to use to store points of the curve.
Definition curve.h:130
General purpose curve (can be used for color gradients, animations, etc...)
Definition curve.h:158
ContainerType control_points
Points of the curve.
Definition curve.h:212
typename CurveSettingsType::template PointStorageType< PointType > ContainerType
Type used to store all points.
Definition curve.h:160
constexpr V eval(const T x) const noexcept
Compute a value on the curve based on its control points.
Definition curve.h:176
typename CurveSettingsType::template PointType< V, T > PointType
Type used as a point on the curve.
Definition curve.h:159