sandbox
Loading...
Searching...
No Matches
smooth_value.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_MATH_SMOOTH_VALUE_HPP_
3#define LIBSBX_MATH_SMOOTH_VALUE_HPP_
4
5#include <cmath>
6#include <concepts>
7#include <type_traits>
8
9#include <libsbx/units/time.hpp>
10
11#include <libsbx/utility/logger.hpp>
12
15#include <libsbx/math/traits.hpp>
17
18namespace sbx::math {
19
20enum class smoothing_mode : std::uint8_t {
21 linear,
22 proportional
23}; // enum class smoothing_mode
24
25template<typename Type>
26struct is_smoothable : std::false_type { };
27
28template<typename Type>
29inline constexpr auto is_smoothable_v = is_smoothable<Type>::value;
30
31template<floating_point Type>
32struct is_smoothable<Type> : std::true_type { };
33
34template<typename Type>
35concept smoothable = is_smoothable_v<Type>;
36
37template<smoothable Type, smoothing_mode Mode>
39
40public:
41
42 using value_type = Type;
43
44 inline static constexpr auto mode = Mode;
45
46 basic_smooth_value(const value_type value)
47 : _current{value},
48 _target{value} { }
49
50 static constexpr auto clamp(const basic_smooth_value& value, const value_type min, const value_type max) -> basic_smooth_value {
51 return basic_smooth_value{value._current, std::clamp(value._target, min, max)};
52 }
53
54 template<floating_point Ratio>
55 static constexpr auto lerp(const basic_smooth_value& x, const basic_smooth_value& y, const Ratio ratio) -> basic_smooth_value {
56 return basic_smooth_value{x._current, mix(x._target, y._target, ratio)};
57 }
58
59 constexpr auto operator=(const value_type value) -> basic_smooth_value& {
60 _target = value;
61
62 return *this;
63 }
64
65 constexpr auto operator+=(const value_type value) -> basic_smooth_value& {
66 _target += value;
67
68 return *this;
69 }
70
71 constexpr auto operator-=(const value_type value) -> basic_smooth_value& {
72 _target -= value;
73
74 return *this;
75 }
76
77 constexpr auto operator*=(const value_type value) -> basic_smooth_value& {
78 _target *= value;
79
80 return *this;
81 }
82
83 constexpr auto operator/=(const value_type value) -> basic_smooth_value& {
84 _target /= value;
85
86 return *this;
87 }
88
89 constexpr auto operator+(const value_type value) -> basic_smooth_value {
90 auto copy = basic_smooth_value{*this};
91 copy += value;
92 return copy;
93 }
94
95 constexpr auto operator-(const value_type value) -> basic_smooth_value {
96 auto copy = basic_smooth_value{*this};
97 copy -= value;
98 return copy;
99 }
100
101 constexpr auto operator*(const value_type value) -> basic_smooth_value {
102 auto copy = basic_smooth_value{*this};
103 copy *= value;
104 return copy;
105 }
106
107 constexpr auto operator/(const value_type value) -> basic_smooth_value {
108 auto copy = basic_smooth_value{*this};
109 copy /= value;
110 return copy;
111 }
112
113 constexpr auto value() const noexcept -> value_type {
114 return _current;
115 }
116
117 constexpr operator value_type() const noexcept {
118 return value();
119 }
120
121 constexpr void update(const units::second& delta_time, const value_type base_speed) {
122 const auto difference = _target - _current;
123
124 if (comparision_traits<value_type>::equal(difference, static_cast<value_type>(0))) {
125 _current = _target;
126 return;
127 }
128
129 const auto step = _compute_step(difference, base_speed, delta_time);
130
131 // Clamp step to not overshoot
132 if (std::abs(step) >= std::abs(difference)) {
133 _current = _target;
134 } else {
135 _current += step;
136 }
137 }
138
139
140private:
141
142 basic_smooth_value(const value_type current, const value_type target)
143 : _current{current},
144 _target{target} { }
145
146 constexpr auto _compute_step(const value_type difference, const value_type base_speed, const units::second& delta_time) const -> value_type {
147 switch (mode) {
148 case smoothing_mode::linear: {
149 return (difference > 0 ? 1 : -1) * base_speed * delta_time;
150 }
151 case smoothing_mode::proportional: {
152 return difference * base_speed * delta_time;
153 }
154 default: {
155 return {};
156 }
157 }
158 }
159
160 value_type _current;
161 value_type _target;
162
163}; // class basic_smooth_value
164
165template<smoothable Type>
167
169
171
172template<smoothable Type>
174
176
178
179} // namespace sbx::math
180
181#endif // LIBSBX_MATH_SMOOTH_VALUE_HPP_
Definition: smooth_value.hpp:38
Definition: quantity.hpp:66
Mathematical constants.
Generic math algorithms and helpers.
constexpr auto mix(const Type x, const Type y, const Type a) -> Type
Linearly interpolates between two values.
Definition: algorithm.ipp:7
Core numeric concepts and type traits.
Definition: traits.hpp:11
Definition: smooth_value.hpp:26