SMG-Decomp
A decompilation of Super Mario Galaxy 1
Loading...
Searching...
No Matches
MathUtil.cpp
1#include "Game/Util/MathUtil.hpp"
2#include "JSystem/JGeometry/TUtil.hpp"
3#include "JSystem/JMath/JMath.hpp"
4#include "JSystem/JMath/JMATrigonometric.hpp"
5
6#include "math_types.hpp"
7
8#include <cmath>
9
10namespace MR {
11 f32 getRandom(f32 min, f32 max) {
12 return (min + ((max - min) * getRandom()));
13 }
14
15 // getRandom(s32, s32)
16
17 f32 getRandomDegree() {
18 return minDegree + (maxDegree * getRandom());
19 }
20
21 void calcRandomVec(TVec3f *pOut, f32 a2, f32 a3) {
22 f32 v10 = (a2 + ((a3 - a2) * getRandom()));
23 f32 v11 = (a2 + ((a3 - a2) * getRandom()));
24 f32 v12 = getRandom();
25
26 f32 dist = a3 - a2;
27 pOut->set<f32>((a2 + (dist * v12)), v11, v10);
28 }
29
30 u8 isHalfProbability() {
31 return MR::getRandom() < 0.5f;
32 }
33
34 f32 getSignHalfProbability() {
35 if (isHalfProbability()) {
36 return -1.0f;
37 }
38
39 return 1.0f;
40 }
41
42 void getRandomVector(TVec3f *pOut, f32 a2) {
43 f32 z = (-a2 + ((a2 - -a2) * getRandom()));
44 f32 y = (-a2 + ((a2 - -a2) * getRandom()));
45 pOut->set((-a2 + ((a2 - -a2) * getRandom())), y, z);
46 }
47
48 #ifdef NON_MATCHING
49 // stack places randVec and otherVec wrongly
50 void addRandomVector(TVec3f *pOut, const TVec3f &rOtherVec, f32 a3) {
51
52 f32 x = -a3 + ((a3 - -a3) * getRandom());
53 f32 y = -a3 + ((a3 - -a3) * getRandom());
54 f32 z = -a3 + ((a3 - -a3) * getRandom());
55
56 TVec3f randVec;
57 randVec.x = x;
58 randVec.y = y;
59 randVec.z = z;
60
61 TVec3f otherVec(rOtherVec);
62 otherVec.add(randVec);
63 pOut->set(otherVec);
64 }
65 #endif
66
67 void turnRandomVector(TVec3f *pOut, const TVec3f &rOtherVec, f32 a3) {
68 f32 mag = PSVECMag((Vec*)(&rOtherVec));
69 addRandomVector(pOut, rOtherVec, a3);
70
71 if (isNearZero(*pOut, 0.001f)) {
72 pOut->set(rOtherVec);
73 }
74 else {
75 pOut->setLength(mag);
76 }
77 }
78
79
80 f32 getInterpolateValue(f32 a1, f32 a2, f32 a3) {
81 return (a2 + (a1 * (a3 - a2)));
82 }
83
84 f32 getLinerValue(f32 a1, f32 a2, f32 a3, f32 a4) {
85 return (a2 + (a1 / a4) * (a3 - a2));
86 }
87
88 f32 getLinerValueFromMinMax(f32 a1, f32 a2, f32 a3, f32 a4, f32 a5) {
89 f32 val = (JGeometry::TUtil<f32>::clamp(a1, a2, a3) - a2) / (a3 - a2);
90 return a4 + ((a5 - a4) * val);
91 }
92
93 #ifdef NON_MATCHING
94 // wrong register orders
95 f32 getEaseInValue(f32 a1, f32 a2, f32 a3, f32 a4) {
96 f32 val = (1.0f - JMACosRadian((((a1 / a4) * PI) * 0.5f)));
97 return a2 + ((a3 - a2) * val);
98 }
99 #endif
100
101 #ifdef NON_MATCHING
102 // wrong register orders
103 f32 getEaseOutValue(f32 a1, f32 a2, f32 a3, f32 a4) {
104 f32 val = (JMASinRadian((((a1 / a4) * PI) * 0.5f)) * (a3 - a2));
105 return a2 + val;
106 }
107 #endif
108
109 // MR::getEaseInOutValue
110 // MR::getScaleWithReactionValueZeroToOne
111 // MR::getConvergeVibrationValue
112 // MR::getReduceVibrationValue
113
114 void makeAxisFrontUp(TVec3f *a1, TVec3f *a2, const TVec3f &a3, const TVec3f &a4) {
115 PSVECCrossProduct((Vec*)&a4, (Vec*)&a3, (Vec*)a1);
116 PSVECNormalize((Vec*)a1, (Vec*)a1);
117 PSVECCrossProduct((Vec*)&a3, (Vec*)a1, (Vec*)a2);
118 }
119
120 // MR::makeAxisFrontSide
121 // MR::makeAxisUpFront
122 // MR::makeAxisUpSide
123 // MR::makeAxisVerticalZX
124 // MR::makeAxisCrossPlane
125 // MR::makeAxisAndCosignVecToVec
126 // MR::calcPerpendicFootToLine
127 // MR::calcPerpendicFootToLineInside
128
129 // etc
130
131 void clampLength(TVec3f *a1, const TVec3f &a2, f32 a3) {
132 if (a2.squared() > (a3 * a3)) {
133 f32 sqr = a2.squared();
134
135 if (sqr <= 0.0000038146973f) {
136 a1->zero();
137 }
138 else {
139 f32 inv_sqr = JGeometry::TUtil<f32>::inv_sqrt(sqr);
140 a1->scale((inv_sqr * a3), a2);
141 }
142
143 }
144 else {
145 a1->set(a2);
146 }
147 }
148
149 // MR::convergeRadian(f32, f32, f32)
150
151 bool isInRange(f32 a1, f32 a2, f32 a3) {
152 if (a2 > a3) {
153 if (a1 < a3) {
154 return false;
155 }
156 else {
157 return !(a1 > a2);
158 }
159 }
160 else {
161 if (a1 < a2) {
162 return false;
163 }
164 else {
165 return !(a1 > a3);
166 }
167 }
168 }
169
170 /*f32 calcRotateY(f32 a1, f32 a2) {
171 f32 val = JMath::sAtanTable.atan2_(-a2, a1);
172 return (minDegree + fmod((maxDegree + ((90.0f + (val * 57.295776f)) - minDegree)), maxDegree));
173 }*/
174
175
176 f32 calcDistanceXY(const TVec3f &a1, const TVec3f &a2) {
177 f32 x_diff = a1.x - a2.x;
178 f32 y_diff = a1.y - a2.y;
179 return JGeometry::TUtil<f32>::sqrt((x_diff * x_diff) + (y_diff * y_diff));
180 }
181
182 bool isNearZero(f32 a1, f32 a2) {
183 if (a1 < 0.0f) {
184 a1 = -a1;
185 }
186
187 if (a1 < a2) {
188 return true;
189 }
190
191 return false;
192 }
193
194 bool isNearZero(const TVec3f &rVec, f32 a2) {
195 f32 v2 = rVec.x;
196 if ( v2 > a2 )
197 return 0;
198
199 f32 v4 = -a2;
200 if ( v2 < -a2 )
201 return 0;
202
203 f32 v5 = rVec.y;
204 if ( v5 > a2 )
205 return 0;
206
207 if ( v5 < v4 )
208 return 0;
209
210 f32 v6 = rVec.z;
211
212 if ( v6 > a2 )
213 return 0;
214
215 return !(rVec.z < -a2);
216 }
217
218
219 f32 diffAngleAbs(f32 a1, f32 a2) {
220 f32 normalize = normalizeAngleAbs(a1 - a2);
221
222 if (normalize > PI) {
223 normalize = (TWO_PI - normalize);
224 }
225
226 return normalize;
227 }
228
229 f32 normalizeAngleAbs(f32 angle) {
230 while (1) {
231 if (angle < 0.0f) {
232 angle += TWO_PI;
233 }
234 else {
235 if (!(angle > TWO_PI)) {
236 return angle;
237 }
238 else {
239 angle -= TWO_PI;
240 }
241 }
242 }
243 }
244
245 bool isAngleBetween(f32 a1, f32 a2, f32 a3) {
246 f32 a1_n = normalizeAngleAbs(a1);
247 f32 a2_n = normalizeAngleAbs(a2);
248 f32 a3_n = normalizeAngleAbs(a3);
249
250 if (a3_n > a2_n) {
251 f32 val = a3_n;
252 a3_n = a2_n;
253 a2_n = val;
254 }
255
256 bool res = false;
257
258 if (a1_n >= a3_n && a1_n <= a2_n) {
259 res = true;
260 }
261
262 if ((a2_n - a3_n) > PI) {
263 res = !res;
264 }
265
266 return res;
267 }
268
269 #ifdef NON_MATCHING
270 // register use is wrong, and mull is in wrong order for isAngleBetween
271 f32 blendAngle(f32 a1, f32 a2, f32 a3) {
272 f32 a1_n = normalizeAngleAbs(a1);
273 f32 a2_n = normalizeAngleAbs(a2);
274
275 if (!isAngleBetween(0.5f * (a1_n + a2_n), a1_n, a2_n)) {
276 if (a1_n < a2_n) {
277 a2_n += TWO_PI;
278 }
279 else {
280 a1_n += TWO_PI;
281 }
282 }
283
284 return normalizeAngleAbs((((1.0f - a3) * a1_n) + (a3 * a2_n)));
285 }
286 #endif
287
288 u8 lerp(u8 a1, u8 a2, f32 a3) {
289 return JGeometry::TUtil<f32>::clamp(a1 + (a3 * (a2 - a1)), 0.0f, 255.0f);
290 }
291
292 /*#ifdef NON_MATCHING
293 _GXColor lerp(_GXColor a1, _GXColor a2, f32 a3) {
294 u8 v6 = lerp(a1.a, a2.a, a3);
295 u8 v7 = lerp(a1.b, a2.b, a3);
296 u8 v8 = lerp(a1.g, a2.b, a3);
297 u8 thing = lerp(a1.r, a2.r, a3);
298
299 return (v6 | ((v7 << 8) & 0xFF00 | ((v8 << 16) & 0xFF000 | thing << 24)) & 0xFFFF00FF) & 0xFFFFFF00;
300 }
301 #endif*/
302
303 f32 vecKillElement(const TVec3f &a1, const TVec3f &a2, TVec3f *a3) {
304 if (isNearZero(a2, 0.001f)) {
305 *a3 = a1;
306 return 0.0f;
307 }
308
309 return PSVECKillElement((const Vec*)&a1, (const Vec*)&a2, (const Vec*)a3);
310 }
311
312 void vecScaleAdd(const register TVec3f *a1, const register TVec3f *a2, register f32 a3) {
313 __asm {
314 psq_l f0, 0(a1), 0, 0
315 psq_l f3, 0(a2), 0, 0
316 psq_l f2, 8(a1), 1, 0
317 psq_l f4, 8(a2), 1, 0
318 ps_madds0 f0, f3, a3, f0
319 ps_madds0 f2, f4, a3, f2
320 psq_st f0, 0(a1), 0, 0
321 psq_st f2, 8(a1), 1, 0
322 }
323 }
324
325 void PSvecBlend(const register TVec3f *a1, const register TVec3f *a2, register TVec3f *a3, register f32 a4, register f32 a5) {
326 __asm {
327 psq_l f0, 0(a1), 0, 0
328 psq_l f3, 8(a1), 1, 0
329 ps_muls0 f4, f0, a4
330 psq_l f0, 0(a2), 0, 0
331 ps_muls0 f3, f3, a4
332 psq_l f1, 8(a2), 1, 0
333 ps_madds0 f4, f0, f2, f4
334 ps_madds0 f3, f1, f2, f3
335 psq_st f4, 0(a3), 0, 0
336 psq_st f3, 8(a3), 1, 0
337 }
338 }
339
340 void vecBlend(const TVec3f &a1, const TVec3f &a2, TVec3f *a3, f32 a4) {
341 PSvecBlend(&a1, &a2, a3, 1.0f - a4, a4);
342 }
343
344 // MR::vecBlendNormal
345 // MR::vecBlendSphere
346 // MR::vecRotAxis
347
348 void blendColor(_GXColor *a1, const _GXColor &a2, const _GXColor &a3, f32 a4) {
349 a1->r = getInterpolateValue(a4, a2.r, a3.r);
350 a1->g = getInterpolateValue(a4, a2.g, a3.g);
351 a1->b = getInterpolateValue(a4, a2.b, a3.b);
352 a1->a = getInterpolateValue(a4, a2.a, a3.a);
353 }
354
355 void blendVec(Vec *a1, const Vec &a2, const Vec &a3, f32 a4) {
356 a1->x = getInterpolateValue(a4, a2.x, a3.x);
357 a1->y = getInterpolateValue(a4, a2.y, a3.y);
358 a1->z = getInterpolateValue(a4, a2.z, a3.z);
359 }
360
361 // MR::turnVecToPlane
362
363 int getMinAbsElementIndex(const TVec3f &rVec) {
364 f64 abs_x = __fabs(rVec.x);
365 f64 abs_y = __fabs(rVec.y);
366 f64 abs_z = __fabs(rVec.z);
367
368 if (abs_x < abs_y && abs_x < abs_z) {
369 return 0;
370 }
371
372 if (abs_y < abs_z) {
373 return 1;
374 }
375
376 return 2;
377 }
378
379 f32 getMaxElement(const TVec3f &rVec) {
380 f32* vec_arr = (f32*)(&rVec);
381 return vec_arr[getMaxElementIndex(rVec)];
382 }
383
384 f32 getMaxAbsElement(const TVec3f &rVec) {
385 f32* vec_arr = (f32*)(&rVec);
386 return vec_arr[getMaxAbsElementIndex(rVec)];
387 }
388
389 int getMaxElementIndex(const TVec3f &rVec) {
390 if (rVec.x > rVec.y && rVec.x > rVec.z) {
391 return 0;
392 }
393
394 if (rVec.y > rVec.z) {
395 return 1;
396 }
397
398 return 2;
399 }
400
401 int getMaxAbsElementIndex(const TVec3f &rVec) {
402 f64 abs_x = __fabs(rVec.x);
403 f64 abs_y = __fabs(rVec.y);
404 f64 abs_z = __fabs(rVec.z);
405
406 if (abs_x > abs_y && abs_x > abs_z) {
407 return 0;
408 }
409
410 if (abs_y > abs_z) {
411 return 1;
412 }
413
414 return 2;
415 }
416};