NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
math_types.h
1#ifndef NW4R_MATH_TYPES_H
2#define NW4R_MATH_TYPES_H
3#include <nw4r/types_nw4r.h>
4
5#include <nw4r/math/math_arithmetic.h>
6#include <nw4r/math/math_triangular.h>
7
8#include <revolution/MTX.h>
9
10namespace nw4r {
11namespace math {
12
13/******************************************************************************
14 *
15 * VEC2 structure
16 *
17 ******************************************************************************/
18// Provides a POD type that can be upcasted to the real structure.
19// (Has the added benefit of forcing struct copies to use lwz/stw.)
20struct _VEC2 {
21 f32 x, y;
22};
23
24struct VEC2 : _VEC2 {
25 VEC2() {}
26 VEC2(f32 fx, f32 fy) {
27 x = fx;
28 y = fy;
29 }
30
31 operator f32*() {
32 return reinterpret_cast<f32*>(this);
33 }
34 operator const f32*() const {
35 return reinterpret_cast<const f32*>(this);
36 }
37
38 VEC2 operator+(const VEC2& rRhs) const {
39 return VEC2(x + rRhs.x, y + rRhs.y);
40 }
41 VEC2 operator-(const VEC2& rRhs) const {
42 return VEC2(x - rRhs.x, y - rRhs.y);
43 }
44
45 VEC2& operator+=(const VEC2& rRhs) {
46 x += rRhs.x;
47 y += rRhs.y;
48 return *this;
49 }
50 VEC2& operator-=(const VEC2& rRhs) {
51 x -= rRhs.x;
52 y -= rRhs.y;
53 return *this;
54 }
55
56 bool operator==(const VEC2& rRhs) const {
57 return x == rRhs.x && y == rRhs.y;
58 }
59 bool operator!=(const VEC2& rRhs) const {
60 return x != rRhs.x || y != rRhs.y;
61 }
62};
63
64/******************************************************************************
65 *
66 * VEC3 structure
67 *
68 ******************************************************************************/
69// Forward declarations
70struct VEC3;
71VEC3* VEC3Add(VEC3* pOut, const VEC3* pA, const VEC3* pB);
72VEC3* VEC3Sub(VEC3* pOut, const VEC3* pA, const VEC3* pB);
73VEC3* VEC3Scale(VEC3* pOut, const VEC3* pIn, f32 scale);
74
75// Provides a POD type that can be upcasted to the real structure.
76// (Has the added benefit of forcing struct copies to use lwz/stw.)
77struct _VEC3 {
78 f32 x, y, z;
79};
80
81struct VEC3 : _VEC3 {
82 VEC3() {}
83 VEC3(f32 fx, f32 fy, f32 fz) {
84 x = fx;
85 y = fy;
86 z = fz;
87 }
88 VEC3(const _VEC3& rVec) {
89 x = rVec.x;
90 y = rVec.y;
91 z = rVec.z;
92 }
93 VEC3(const Vec& rVec) {
94 x = rVec.x;
95 y = rVec.y;
96 z = rVec.z;
97 }
98 VEC3(const f32* pData) {
99 x = pData[0];
100 y = pData[1];
101 z = pData[2];
102 }
103
104 operator Vec*() {
105 return reinterpret_cast<Vec*>(this);
106 }
107 operator const Vec*() const {
108 return reinterpret_cast<const Vec*>(this);
109 }
110
111 f32 LenSq() const {
112 return x * x + y * y + z * z;
113 }
114
115 VEC3 operator-() const {
116 return VEC3(-x, -y, -z);
117 }
118
119 VEC3 operator+(const VEC3& rRhs) const {
120 VEC3 out;
121 VEC3Add(&out, this, &rRhs);
122 return out;
123 }
124 VEC3 operator-(const VEC3& rRhs) const {
125 VEC3 out;
126 VEC3Sub(&out, this, &rRhs);
127 return out;
128 }
129 VEC3 operator*(f32 x) const {
130 VEC3 out;
131 VEC3Scale(&out, this, x);
132 return out;
133 }
134 VEC3 operator/(f32 x) const {
135 f32 r = 1 / x;
136 return *this * r;
137 }
138
139 VEC3& operator+=(const VEC3& rRhs) {
140 VEC3Add(this, this, &rRhs);
141 return *this;
142 }
143 VEC3& operator-=(const VEC3& rRhs) {
144 VEC3Sub(this, this, &rRhs);
145 return *this;
146 }
147 VEC3& operator*=(f32 x) {
148 VEC3Scale(this, this, x);
149 return *this;
150 }
151 VEC3& operator/=(f32 x) {
152 return *this *= (1 / x);
153 }
154
155 bool operator==(const VEC3& rRhs) const {
156 return x == rRhs.x && y == rRhs.y && z == rRhs.z;
157 }
158 bool operator!=(const VEC3& rRhs) const {
159 return x != rRhs.x || y != rRhs.y || z != rRhs.z;
160 }
161};
162
163/******************************************************************************
164 *
165 * MTX33 structure
166 *
167 ******************************************************************************/
168// Provides a POD type that can be upcasted to the real structure.
169// (Has the added benefit of forcing struct copies to use lwz/stw.)
170struct _MTX33 {
171 union {
172 struct {
173 f32 _00, _01, _02;
174 f32 _10, _11, _12;
175 f32 _20, _21, _22;
176 };
177
178 f32 m[3][3];
179 f32 a[3 * 3];
180 };
181};
182
183struct MTX33 : _MTX33 {
184 MTX33() {}
185};
186
187/******************************************************************************
188 *
189 * MTX34 structure
190 *
191 ******************************************************************************/
192// Provides a POD type that can be upcasted to the real structure.
193// (Has the added benefit of forcing struct copies to use lwz/stw.)
194struct _MTX34 {
195 union {
196 struct {
197 f32 _00, _01, _02, _03;
198 f32 _10, _11, _12, _13;
199 f32 _20, _21, _22, _23;
200 };
201
202 f32 m[3][4];
203 f32 a[3 * 4];
204 Mtx mtx;
205 };
206};
207
208struct MTX34 : _MTX34 {
209 typedef f32 (*MtxRef)[4];
210 typedef const f32 (*MtxRefConst)[4];
211
212 MTX34() {}
213
214 // clang-format off
215 MTX34(f32 f00, f32 f01, f32 f02, f32 f03,
216 f32 f10, f32 f11, f32 f12, f32 f13,
217 f32 f20, f32 f21, f32 f22, f32 f23) {
218 _00 = f00; _01 = f01; _02 = f02; _03 = f03;
219 _10 = f10; _11 = f11; _12 = f12; _13 = f13;
220 _20 = f20; _21 = f21; _22 = f22; _23 = f23;
221 }
222 // clang-format on
223
224 operator MtxRef() {
225 return mtx;
226 }
227 operator MtxRefConst() const {
228 return mtx;
229 }
230};
231
232/******************************************************************************
233 *
234 * MTX44 structure
235 *
236 ******************************************************************************/
237// Provides a POD type that can be upcasted to the real structure.
238// (Has the added benefit of forcing struct copies to use lwz/stw.)
239struct _MTX44 {
240 union {
241 struct {
242 f32 _00, _01, _02, _03;
243 f32 _10, _11, _12, _13;
244 f32 _20, _21, _22, _23;
245 f32 _30, _31, _32, _33;
246 };
247
248 f32 m[4][4];
249 f32 a[4 * 4];
250 Mtx44 mtx;
251 };
252};
253
254struct MTX44 : _MTX44 {
255 typedef f32 (*Mtx44Ref)[4];
256 typedef const f32 (*Mtx44RefConst)[4];
257
258 MTX44() {}
259
260 operator Mtx44Ref() {
261 return mtx;
262 }
263 operator Mtx44RefConst() const {
264 return mtx;
265 }
266};
267
268/******************************************************************************
269 *
270 * QUAT structure
271 *
272 ******************************************************************************/
273// Provides a POD type that can be upcasted to the real structure.
274// (Has the added benefit of forcing struct copies to use lwz/stw.)
275struct _QUAT {
276 f32 x, y, z, w;
277};
278
279struct QUAT : _QUAT {
280 QUAT() {}
281 QUAT(f32 fx, f32 fy, f32 fz, f32 fw) {
282 x = fx;
283 y = fy;
284 z = fz;
285 w = fw;
286 }
287
288 // TODO: These are not real AFAIK. Do they really manually cast the QUAT?
289 operator Quaternion*() {
290 return reinterpret_cast<Quaternion*>(this);
291 }
292 operator const Quaternion*() const {
293 return reinterpret_cast<const Quaternion*>(this);
294 }
295};
296
297/******************************************************************************
298 *
299 * VEC2 functions
300 *
301 ******************************************************************************/
302inline f32 VEC2Len(const VEC2* pVec) {
303 return FSqrt(pVec->x * pVec->x + pVec->y * pVec->y);
304}
305
306/******************************************************************************
307 *
308 * VEC3 functions
309 *
310 ******************************************************************************/
311VEC3* VEC3Maximize(VEC3* pOut, const VEC3* pA, const VEC3* pB);
312VEC3* VEC3Minimize(VEC3* pOut, const VEC3* pA, const VEC3* pB);
313VEC3* VEC3TransformNormal(VEC3* pOut, const MTX34* pMtx, const VEC3* pVec);
314
315inline VEC3* VEC3Add(register VEC3* pOut, register const VEC3* pA,
316 register const VEC3* pB) {
317 register f32 work0, work1, work2;
318
319 // clang-format off
320 asm {
321 // Add XY
322 psq_l work0, VEC3.x(pA), 0, 0
323 psq_l work1, VEC3.x(pB), 0, 0
324 ps_add work2, work0, work1
325 psq_st work2, VEC3.x(pOut), 0, 0
326
327 // Add Z
328 psq_l work0, VEC3.z(pA), 1, 0
329 psq_l work1, VEC3.z(pB), 1, 0
330 ps_add work2, work0, work1
331 psq_st work2, VEC3.z(pOut), 1, 0
332 }
333 // clang-format on
334
335 return pOut;
336}
337
338inline f32 VEC3Dot(register const VEC3* pA, register const VEC3* pB) {
339 register f32 dot;
340 register f32 work0, work1, work2, work3;
341
342 // clang-format off
343 asm {
344 // YZ product
345 psq_l work0, VEC3.y(pA), 0, 0
346 psq_l work1, VEC3.y(pB), 0, 0
347 ps_mul work0, work0, work1
348
349 // X product + YZ product
350 psq_l work3, VEC3.x(pA), 1, 0
351 psq_l work2, VEC3.x(pB), 1, 0
352 ps_madd work1, work3, work2, work0
353
354 // Dot product
355 ps_sum0 dot, work1, work0, work0
356 }
357 // clang-format on
358
359 return dot;
360}
361
362inline f32 VEC3LenSq(register const VEC3* pVec) {
363 register f32 work0, work1, work2;
364
365 // clang-format off
366 asm {
367 // Square XY
368 psq_l work0, VEC3.x(pVec), 0, 0
369 ps_mul work0, work0, work0
370
371 // Square Z
372 lfs work1, VEC3.z(pVec)
373 ps_madd work2, work1, work1, work0
374
375 // Sum products
376 ps_sum0 work2, work2, work0, work0
377 }
378 // clang-format on
379
380 return work2;
381}
382
383inline VEC3* VEC3Lerp(register VEC3* pOut, register const VEC3* pVec1,
384 register const VEC3* pVec2, register f32 t) {
385 register f32 work0, work1, work2;
386
387 // clang-format off
388 asm {
389 // X/Y delta
390 psq_l work0, VEC3.x(pVec1), 0, 0
391 psq_l work1, VEC3.x(pVec2), 0, 0
392 ps_sub work2, work1, work0
393 // Scale with time and add to v0
394 ps_madds0 work2, work2, t, work0
395 psq_st work2, VEC3.x(pOut), 0, 0
396
397 // Z delta
398 psq_l work0, VEC3.z(pVec1), 1, 0
399 psq_l work1, VEC3.z(pVec2), 1, 0
400 ps_sub work2, work1, work0
401 // Scale with time and add to v0
402 ps_madds0 work2, work2, t, work0
403 psq_st work2, VEC3.z(pOut), 1, 0
404 }
405 // clang-format on
406
407 return pOut;
408}
409
410inline VEC3* VEC3Scale(register VEC3* pOut, register const VEC3* pIn,
411 register f32 scale) {
412 register f32 work0, work1;
413
414 // clang-format off
415 asm {
416 // Scale XY
417 psq_l work0, VEC3.x(pIn), 0, 0
418 ps_muls0 work1, work0, scale
419 psq_st work1, VEC3.x(pOut), 0, 0
420
421 // Scale Z
422 psq_l work0, VEC3.z(pIn), 1, 0
423 ps_muls0 work1, work0, scale
424 psq_st work1, VEC3.z(pOut), 1, 0
425 }
426 // clang-format on
427
428 return pOut;
429}
430
431inline VEC3* VEC3Sub(register VEC3* pOut, register const VEC3* pA,
432 register const VEC3* pB) {
433 register f32 work0, work1, work2;
434
435 // clang-format off
436 asm {
437 // Sub XY
438 psq_l work0, VEC3.x(pA), 0, 0
439 psq_l work1, VEC3.x(pB), 0, 0
440 ps_sub work2, work0, work1
441 psq_st work2, VEC3.x(pOut), 0, 0
442
443 // Sub Z
444 psq_l work0, VEC3.z(pA), 1, 0
445 psq_l work1, VEC3.z(pB), 1, 0
446 ps_sub work2, work0, work1
447 psq_st work2, VEC3.z(pOut), 1, 0
448 }
449 // clang-format on
450
451 return pOut;
452}
453
454inline VEC3* VEC3Cross(VEC3* pOut, const VEC3* pA, const VEC3* pB) {
455 PSVECCrossProduct(*pA, *pB, *pOut);
456 return pOut;
457}
458
459inline f32 VEC3DistSq(const VEC3* pA, const VEC3* pB) {
460 return PSVECSquareDistance(*pA, *pB);
461}
462
463inline f32 VEC3Len(const VEC3* pVec) {
464 return PSVECMag(*pVec);
465}
466
467inline VEC3* VEC3Normalize(VEC3* pOut, const VEC3* pIn) {
468 PSVECNormalize(*pIn, *pOut);
469 return pOut;
470}
471
472inline VEC3* VEC3Transform(VEC3* pOut, const MTX34* pMtx, const VEC3* pVec) {
473 PSMTXMultVec(*pMtx, *pVec, *pOut);
474 return pOut;
475}
476
477inline VEC3* VEC3TransformCoord(VEC3* pOut, const MTX34* pMtx,
478 const VEC3* pVec) {
479 PSMTXMultVec(*pMtx, *pVec, *pOut);
480 return pOut;
481}
482
483/******************************************************************************
484 *
485 * MTX33 functions
486 *
487 ******************************************************************************/
488MTX33* MTX33Identity(MTX33* pMtx);
489
490/******************************************************************************
491 *
492 * MTX34 functions
493 *
494 ******************************************************************************/
495MTX33* MTX34ToMTX33(MTX33* pOut, const MTX34* pIn);
496ulong MTX34InvTranspose(MTX33* pOut, const MTX34* pIn);
497MTX34* MTX34Zero(MTX34* pMtx);
498MTX34* MTX34Scale(MTX34* pOut, const MTX34* pIn, const VEC3* pScale);
499MTX34* MTX34Trans(MTX34* pOut, const MTX34* pIn, const VEC3* pTrans);
500MTX34* MTX34RotAxisFIdx(MTX34* pMtx, const VEC3* pAxis, f32 fidx);
501MTX34* MTX34RotXYZFIdx(MTX34* pMtx, f32 fx, f32 fy, f32 fz);
502
503inline MTX34* MTX34Copy(MTX34* pOut, const MTX34* pIn) {
504 PSMTXCopy(*pIn, *pOut);
505 return pOut;
506}
507
508inline MTX34* MTX34Identity(MTX34* pMtx) {
509 PSMTXIdentity(*pMtx);
510 return pMtx;
511}
512
513inline ulong MTX34Inv(MTX34* pOut, const MTX34* pIn) {
514 return PSMTXInverse(*pIn, *pOut);
515}
516
517inline ulong MTX34InvTranspose(MTX34* pOut, const MTX34* pIn) {
518 return PSMTXInvXpose(*pIn, *pOut);
519}
520
521inline MTX34* MTX34LookAt(MTX34* pMtx, const VEC3* pPos, const VEC3* pUp,
522 const VEC3* pTarget) {
523 C_MTXLookAt(*pMtx, *pPos, *pUp, *pTarget);
524 return pMtx;
525}
526
527inline MTX34* MTX34Mult(MTX34* pOut, const MTX34* pA, const MTX34* pB) {
528 PSMTXConcat(*pA, *pB, *pOut);
529 return pOut;
530}
531
532inline MTX34* MTX34MultArray(MTX34* pOut, const MTX34* p1, const MTX34* pSrc,
533 ulong len) {
534 PSMTXConcatArray(*p1, *pSrc, *pOut, len);
535 return pOut;
536}
537
538inline MTX34* MTX34RotAxisRad(MTX34* pOut, const VEC3* pAxis, f32 frad) {
539 return MTX34RotAxisFIdx(pOut, pAxis, NW4R_MATH_RAD_TO_FIDX(frad));
540}
541
542inline MTX34* MTX34RotXYZDeg(MTX34* pMtx, f32 dx, f32 dy, f32 dz) {
543 return MTX34RotXYZFIdx(pMtx, NW4R_MATH_DEG_TO_FIDX(dx),
544 NW4R_MATH_DEG_TO_FIDX(dy),
545 NW4R_MATH_DEG_TO_FIDX(dz));
546}
547
548inline MTX34* MTX34RotXYZRad(MTX34* pMtx, f32 rx, f32 ry, f32 rz) {
549 return MTX34RotXYZFIdx(pMtx, NW4R_MATH_RAD_TO_FIDX(rx),
550 NW4R_MATH_RAD_TO_FIDX(ry),
551 NW4R_MATH_RAD_TO_FIDX(rz));
552}
553
554inline MTX34* MTX34Scale(MTX34* pOut, const VEC3* pScale, const MTX34* pIn) {
555 PSMTXScaleApply(*pIn, *pOut, pScale->x, pScale->y, pScale->z);
556 return pOut;
557}
558
559inline QUAT* MTX34ToQUAT(QUAT* pQuat, const MTX34* pMtx) {
560 C_QUATMtx(*pQuat, *pMtx);
561 return pQuat;
562}
563
564inline MTX34* MTX34Trans(MTX34* pOut, const VEC3* pTrans, const MTX34* pIn) {
565 PSMTXTransApply(*pIn, *pOut, pTrans->x, pTrans->y, pTrans->z);
566 return pOut;
567}
568
569/******************************************************************************
570 *
571 * MTX44 functions
572 *
573 ******************************************************************************/
574MTX44* MTX44Identity(MTX44* pMtx);
575MTX44* MTX44Copy(MTX44* pDst, const MTX44* pSrc);
576
577/******************************************************************************
578 *
579 * QUAT functions
580 *
581 ******************************************************************************/
582inline MTX34* QUATToMTX34(MTX34* pMtx, const QUAT* pQuat) {
583 PSMTXQuat(*pMtx, *pQuat);
584 return pMtx;
585}
586
587// @bug QUATSlerp macro changes this function name!
588inline QUAT* C_QUATSlerp(QUAT* pOut, const QUAT* p1, const QUAT* p2, f32 t) {
589 ::C_QUATSlerp(*p1, *p2, *pOut, t);
590 return pOut;
591}
592
593} // namespace math
594} // namespace nw4r
595
596#endif
Math library.
Definition mtxtypes.h:11