1#include "hostio/seadHostIOCurve.h"
2#include <cmath>
3#include "math/seadMathCalcCommon.h"
4#include "math/seadMathNumbers.h"
5
6namespace sead::hostio
7{
8template <typename T>
9constexpr CurveFunctionTable<T> makeTable_()
10{
11 return {{
12 curveLinear_,
13 curveHermit_,
14 curveStep_,
15 curveSin_,
16 curveCos_,
17 curveSinPow2_,
18 curveLinear2D_,
19 curveHermit2D_,
20 curveStep2D_,
21 curveNonuniformSpline_,
22 curveHermit2DSmooth_,
23 }};
24}
25
26template <typename T>
27constexpr CurveFunctionTableVec2<T> makeTableVec2_()
28{
29 return {{
30 curveLinearVec2_,
31 curveHermitVec2_,
32 curveStepVec2_,
33 curveSinVec2_,
34 curveCosVec2_,
35 curveSinPow2Vec2_,
36 curveLinear2DVec2_,
37 curveHermit2DVec2_,
38 curveStep2DVec2_,
39 curveNonuniformSplineVec2_,
40 curveHermit2DSmoothVec2_,
41 }};
42}
43
44CurveFunctionTable<f32> sCurveFunctionTbl_f32 = makeTable_<f32>();
45CurveFunctionTable<f64> sCurveFunctionTbl_f64 = makeTable_<f64>();
46
47CurveFunctionTableVec2<f32> sCurveFunctionTbl_Vec2f = makeTableVec2_<f32>();
48CurveFunctionTableVec2<f64> sCurveFunctionTbl_Vec2d = makeTableVec2_<f64>();
49
50template <typename T>
51static T fracPart(T x)
52{
53 return x - T(int(x));
54}
55
56template <typename T>
57T curveLinear_(f32 t, const CurveDataInfo* info, const T* f)
58{
59 if (t < 0)
60 return f[0];
61
62 const auto n = info->numUse - 1;
63 const int i = n * t;
64 if (i >= n)
65 return f[n];
66 return f[i] + (fracPart(x: n * t) * (f[i + 1] - f[i]));
67}
68
69// NON_MATCHING: instruction ordering
70template <typename T>
71T curveHermit_(f32 t, const CurveDataInfo* info, const T* f)
72{
73 if (info->numUse % 2 == 1)
74 return 0;
75 if (t < 0)
76 return f[0];
77
78 const auto n = (info->numUse / 2) - 1;
79 const int i = n * t;
80 const int j = 2 * i;
81 if (i >= n)
82 return f[j];
83
84 const auto x = fracPart(x: n * t);
85 const auto coeff = &f[j];
86
87 return ((2 * x * x * x) - (3 * x * x) + 1) * coeff[0] // (2t^3 - 3t^2 + 1)p0
88 + ((-2 * x * x * x) + (3 * x * x)) * coeff[2] // (-2t^3 + 2t^2)p1
89 + ((x * x * x) - (x * x)) * coeff[3] // (t^3 - t^2)m1
90 + ((x * x * x) - (2 * x * x) + x) * f[j | 1] // (t^3 - 2t^2 + t)m0
91 ;
92}
93
94template <typename T>
95T curveStep_(f32 t, const CurveDataInfo* info, const T* f)
96{
97 const f32 x = Mathf::clamp(value: t, low: 0.0, high: 1.0);
98 return f[int(x * (info->numUse - 1))];
99}
100
101template <typename T>
102T curveSin_(f32 t_, const CurveDataInfo*, const T* f)
103{
104 const T t = t_;
105 return std::sin(f[0] * t * (2 * numbers::pi_v<T>)) * f[1];
106}
107
108template <typename T>
109T curveCos_(f32 t_, const CurveDataInfo*, const T* f)
110{
111 const T t = t_;
112 return std::cos(f[0] * T(t) * (2 * numbers::pi_v<T>)) * f[1];
113}
114
115template <typename T>
116T curveSinPow2_(f32 t_, const CurveDataInfo*, const T* f)
117{
118 const T t = t_;
119 const auto y = std::sin(f[0] * t * (2 * numbers::pi_v<T>));
120 return y * y * f[1];
121}
122
123// NON_MATCHING: instruction reordering (which results in localized regalloc differences)
124template <typename T>
125T curveLinear2D_(f32 t_, const CurveDataInfo* info, const T* f)
126{
127 const T t = t_;
128 if (f[0] >= t)
129 return f[1];
130
131 const auto n = info->numUse / 2;
132 if (f[2 * (n - 1)] <= t)
133 return f[2 * (n - 1) + 1];
134
135 for (s32 i = 0; i < n; ++i)
136 {
137 const auto j = 2 * i;
138 if (f[j + 2] > t)
139 return f[j + 1] + ((t - f[j]) / (f[j + 2] - f[j])) * (f[j + 3] - f[j + 1]);
140 }
141 return 0;
142}
143
144// NON_MATCHING: same as curveHermit_<T>
145template <typename T>
146T curveHermit2D_(f32 t_, const CurveDataInfo* info, const T* f)
147{
148 const T t = t_;
149 const s8 n = info->numUse / 3;
150 if (f[0] >= t)
151 return f[1];
152
153 if (f[3 * (n - 1)] <= t)
154 return f[3 * (n - 1) + 1];
155
156 for (s32 i = 0; i < n; ++i)
157 {
158 const auto j = 3 * i;
159 if (f[j + 3] > t)
160 {
161 const auto x = (t - f[j]) / (f[j + 3] - f[j]);
162 return ((2 * x * x * x) - (3 * x * x) + 1) * f[j + 1] // (2t^3 - 3t^2 + 1)p0
163 + ((-2 * x * x * x) + (3 * x * x)) * f[j + 4] // (-2t^3 + 2t^2)p1
164 + ((x * x * x) - (x * x)) * f[j + 5] // (t^3 - t^2)m1
165 + ((x * x * x) - (2 * x * x) + x) * f[j + 2] // (t^3 - 2t^2 + t)m0
166 ;
167 }
168 }
169
170 return 0;
171}
172
173template <typename T>
174T curveStep2D_(f32 t_, const CurveDataInfo* info, const T* f)
175{
176 const T t = t_;
177 const s8 n = info->numUse / 2;
178 if (t <= f[0])
179 return f[1];
180
181 if (t >= f[2 * (n - 1)])
182 return f[2 * (n - 1) + 1];
183
184 for (s32 i = 0; i < n; ++i)
185 {
186 if (t < f[2 * i + 2])
187 return f[2 * i + 1];
188 }
189 return 0;
190}
191
192template <typename T>
193T curveNonuniformSpline_(f32, const CurveDataInfo*, const T*)
194{
195 SEAD_ASSERT_MSG(false, "You must call ICurve::interpolateToVec2 at this curve type.");
196 return 0;
197}
198
199template <typename T>
200Vector2<T> curveLinearVec2_(f32 t, const CurveDataInfo* info, const T* f)
201{
202 return {t, curveLinear_(t, info, f)};
203}
204
205template <typename T>
206Vector2<T> curveHermitVec2_(f32 t, const CurveDataInfo* info, const T* f)
207{
208 return {t, curveHermit_(t, info, f)};
209}
210
211template <typename T>
212Vector2<T> curveStepVec2_(f32 t, const CurveDataInfo* info, const T* f)
213{
214 return {t, curveStep_(t, info, f)};
215}
216
217template <typename T>
218Vector2<T> curveSinVec2_(f32 t, const CurveDataInfo* info, const T* f)
219{
220 return {t, curveSin_(t, info, f)};
221}
222
223template <typename T>
224Vector2<T> curveCosVec2_(f32 t, const CurveDataInfo* info, const T* f)
225{
226 return {t, curveCos_(t, info, f)};
227}
228
229template <typename T>
230Vector2<T> curveSinPow2Vec2_(f32 t, const CurveDataInfo* info, const T* f)
231{
232 return {t, curveSinPow2_(t, info, f)};
233}
234
235template <typename T>
236Vector2<T> curveLinear2DVec2_(f32 t, const CurveDataInfo* info, const T* f)
237{
238 return {t, curveLinear2D_(t, info, f)};
239}
240
241template <typename T>
242Vector2<T> curveHermit2DVec2_(f32 t, const CurveDataInfo* info, const T* f)
243{
244 return {t, curveHermit2D_(t, info, f)};
245}
246
247template <typename T>
248Vector2<T> curveStep2DVec2_(f32 t, const CurveDataInfo* info, const T* f)
249{
250 return {t, curveStep2D_(t, info, f)};
251}
252
253// curveNonuniformSplineVec2_ has an assertion
254
255template <typename T>
256Vector2<T> curveHermit2DSmoothVec2_(f32 t, const CurveDataInfo* info, const T* f)
257{
258 return {t, curveHermit2DSmooth_(t, info, f)};
259}
260} // namespace sead::hostio
261