citro3d
Loading...
Searching...
No Matches
maths.h
Go to the documentation of this file.
1/**
2 * @file maths.h
3 * @brief Basic math library for matrix, vector, and quaternion operations
4 */
5#pragma once
6#include "types.h"
7#include <math.h>
8#include <string.h>
9
10/**
11 * @addtogroup math_support
12 * @brief Implementations of matrix, vector, and quaternion operations.
13 * @{
14 */
15
16/**
17 * The one true circumference-to-radius ratio.
18 * See http://tauday.com/tau-manifesto
19 */
20#define M_TAU (6.28318530717958647692528676655900576)
21
22// Define the legacy circle constant as well
23#ifndef M_PI
24#define M_PI (M_TAU/2)
25#endif
26
27/**
28 * @brief Convert an angle from revolutions to radians
29 * @param[in] _angle Proportion of a full revolution
30 * @return Angle in radians
31 */
32#define C3D_Angle(_angle) ((_angle)*M_TAU)
33
34/**
35 * @brief Convert an angle from degrees to radians
36 * @param[in] _angle Angle in degrees
37 * @return Angle in radians
38 */
39#define C3D_AngleFromDegrees(_angle) ((_angle)*M_TAU/360.0f)
40
41#define C3D_AspectRatioTop (400.0f / 240.0f) ///< Aspect ratio for 3DS top screen
42#define C3D_AspectRatioBot (320.0f / 240.0f) ///< Aspect ratio for 3DS bottom screen
43
44/**
45 * @name Vector Math
46 * @{
47 */
48
49/**
50 * @brief Create a new FVec4
51 * @param[in] x X-component
52 * @param[in] y Y-component
53 * @param[in] z Z-component
54 * @param[in] w W-component
55 * @return New FVec4
56 */
57static inline C3D_FVec FVec4_New(float x, float y, float z, float w)
58{
59 return (C3D_FVec){{ w, z, y, x }};
60}
61
62/**
63 * @brief Add two FVec4s
64 * @param[in] lhs Augend
65 * @param[in] rhs Addend
66 * @return lhs+rhs (sum)
67 */
68static inline C3D_FVec FVec4_Add(C3D_FVec lhs, C3D_FVec rhs)
69{
70 // component-wise addition
71 return FVec4_New(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w);
72}
73
74/**
75 * @brief Subtract two FVec4s
76 * @param[in] lhs Minuend
77 * @param[in] rhs Subtrahend
78 * @return lhs-rhs (difference)
79 */
81{
82 // component-wise subtraction
83 return FVec4_New(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w);
84}
85
86/**
87 * @brief Negate a FVec4
88 * @note This is equivalent to `FVec4_Scale(v, -1)`
89 * @param[in] v Vector to negate
90 * @return -v
91 */
93{
94 // component-wise negation
95 return FVec4_New(-v.x, -v.y, -v.z, -v.w);
96}
97
98/**
99 * @brief Scale a FVec4
100 * @param[in] v Vector to scale
101 * @param[in] s Scale factor
102 * @return v*s
103 */
104static inline C3D_FVec FVec4_Scale(C3D_FVec v, float s)
105{
106 // component-wise scaling
107 return FVec4_New(v.x*s, v.y*s, v.z*s, v.w*s);
108}
109
110/**
111 * @brief Perspective divide
112 * @param[in] v Vector to divide
113 * @return v/v.w
114 */
116{
117 // divide by w
118 return FVec4_New(v.x/v.w, v.y/v.w, v.z/v.w, 1.0f);
119}
120
121/**
122 * @brief Dot product of two FVec4s
123 * @param[in] lhs Left-side FVec4
124 * @param[in] rhs Right-side FVec4
125 * @return lhs∙rhs
126 */
127static inline float FVec4_Dot(C3D_FVec lhs, C3D_FVec rhs)
128{
129 // A∙B = sum of component-wise products
130 return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z + lhs.w*rhs.w;
131}
132
133/**
134 * @brief Magnitude of a FVec4
135 * @param[in] v Vector
136 * @return ‖v‖
137 */
138static inline float FVec4_Magnitude(C3D_FVec v)
139{
140 // ‖v‖ = √(v∙v)
141 return sqrtf(FVec4_Dot(v,v));
142}
143
144/**
145 * @brief Normalize a FVec4
146 * @param[in] v FVec4 to normalize
147 * @return v/‖v‖
148 */
150{
151 // get vector magnitude
152 float m = FVec4_Magnitude(v);
153
154 // scale by inverse magnitude to get a unit vector
155 return FVec4_New(v.x/m, v.y/m, v.z/m, v.w/m);
156}
157
158/**
159 * @brief Create a new FVec3
160 * @param[in] x X-component
161 * @param[in] y Y-component
162 * @param[in] z Z-component
163 * @return New FVec3
164 */
165static inline C3D_FVec FVec3_New(float x, float y, float z)
166{
167 return FVec4_New(x, y, z, 0.0f);
168}
169
170/**
171 * @brief Dot product of two FVec3s
172 * @param[in] lhs Left-side FVec3
173 * @param[in] rhs Right-side FVec3
174 * @return lhs∙rhs
175 */
176static inline float FVec3_Dot(C3D_FVec lhs, C3D_FVec rhs)
177{
178 // A∙B = sum of component-wise products
179 return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
180}
181
182/**
183 * @brief Magnitude of a FVec3
184 * @param[in] v Vector
185 * @return ‖v‖
186 */
187static inline float FVec3_Magnitude(C3D_FVec v)
188{
189 // ‖v‖ = √(v∙v)
190 return sqrtf(FVec3_Dot(v,v));
191}
192
193/**
194 * @brief Normalize a FVec3
195 * @param[in] v FVec3 to normalize
196 * @return v/‖v‖
197 */
199{
200 // get vector magnitude
201 float m = FVec3_Magnitude(v);
202
203 // scale by inverse magnitude to get a unit vector
204 return FVec3_New(v.x/m, v.y/m, v.z/m);
205}
206
207/**
208 * @brief Add two FVec3s
209 * @param[in] lhs Augend
210 * @param[in] rhs Addend
211 * @return lhs+rhs (sum)
212 */
213static inline C3D_FVec FVec3_Add(C3D_FVec lhs, C3D_FVec rhs)
214{
215 // component-wise addition
216 return FVec3_New(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z);
217}
218
219/**
220 * @brief Subtract two FVec3s
221 * @param[in] lhs Minuend
222 * @param[in] rhs Subtrahend
223 * @return lhs-rhs (difference)
224 */
226{
227 // component-wise subtraction
228 return FVec3_New(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z);
229}
230
231/**
232 * @brief Distance between two 3D points
233 * @param[in] lhs Relative origin
234 * @param[in] rhs Relative point of interest
235 * @return ‖lhs-rhs‖
236 */
237static inline float FVec3_Distance(C3D_FVec lhs, C3D_FVec rhs)
238{
239 // distance = ‖lhs-rhs‖
240 return FVec3_Magnitude(FVec3_Subtract(lhs, rhs));
241}
242
243/**
244 * @brief Scale a FVec3
245 * @param[in] v Vector to scale
246 * @param[in] s Scale factor
247 * @return v*s
248 */
249static inline C3D_FVec FVec3_Scale(C3D_FVec v, float s)
250{
251 // component-wise scaling
252 return FVec3_New(v.x*s, v.y*s, v.z*s);
253}
254
255/**
256 * @brief Negate a FVec3
257 * @note This is equivalent to `FVec3_Scale(v, -1)`
258 * @param[in] v Vector to negate
259 * @return -v
260 */
262{
263 // component-wise negation
264 return FVec3_New(-v.x, -v.y, -v.z);
265}
266
267/**
268 * @brief Cross product of two FVec3s
269 * @note This returns a pseudo-vector which is perpendicular to the plane
270 * spanned by the two input vectors.
271 * @param[in] lhs Left-side FVec3
272 * @param[in] rhs Right-side FVec3
273 * @return lhs×rhs
274 */
275static inline C3D_FVec FVec3_Cross(C3D_FVec lhs, C3D_FVec rhs)
276{
277 // A×B = (AyBz - AzBy, AzBx - AxBz, AxBy - AyBx)
278 return FVec3_New(lhs.y*rhs.z - lhs.z*rhs.y, lhs.z*rhs.x - lhs.x*rhs.z, lhs.x*rhs.y - lhs.y*rhs.x);
279}
280/** @} */
281
282/**
283 * @name Matrix Math
284 * @note All matrices are 4x4 unless otherwise noted.
285 * @{
286 */
287
288/**
289 * @brief Zero matrix
290 * @param[out] out Matrix to zero
291 */
292static inline void Mtx_Zeros(C3D_Mtx* out)
293{
294 memset(out, 0, sizeof(*out));
295}
296
297/**
298 * @brief Copy a matrix
299 * @param[out] out Output matrix
300 * @param[in] in Input matrix
301 */
302static inline void Mtx_Copy(C3D_Mtx* out, const C3D_Mtx* in)
303{
304 *out = *in;
305}
306
307/**
308 * @brief Creates a matrix with the diagonal using the given parameters.
309 * @param[out] out Output matrix.
310 * @param[in] x The X component.
311 * @param[in] y The Y component.
312 * @param[in] z The Z component.
313 * @param[in] w The W component.
314 */
315static inline void Mtx_Diagonal(C3D_Mtx* out, float x, float y, float z, float w)
316{
317 Mtx_Zeros(out);
318 out->r[0].x = x;
319 out->r[1].y = y;
320 out->r[2].z = z;
321 out->r[3].w = w;
322}
323
324/**
325 * @brief Identity matrix
326 * @param[out] out Matrix to fill
327 */
328static inline void Mtx_Identity(C3D_Mtx* out)
329{
330 Mtx_Diagonal(out, 1.0f, 1.0f, 1.0f, 1.0f);
331}
332
333/**
334 *@brief Transposes the matrix. Row => Column, and vice versa.
335 *@param[in,out] out Output matrix.
336 */
338
339/**
340 * @brief Matrix addition
341 * @param[out] out Output matrix.
342 * @param[in] lhs Left matrix.
343 * @param[in] rhs Right matrix.
344 * @return lhs+rhs (sum)
345 */
346static inline void Mtx_Add(C3D_Mtx* out, const C3D_Mtx* lhs, const C3D_Mtx* rhs)
347{
348 for (int i = 0; i < 16; i++)
349 out->m[i] = lhs->m[i] + rhs->m[i];
350}
351
352/**
353 * @brief Matrix subtraction
354 * @param[out] out Output matrix.
355 * @param[in] lhs Left matrix.
356 * @param[in] rhs Right matrix.
357 * @return lhs-rhs (difference)
358 */
359static inline void Mtx_Subtract(C3D_Mtx* out, const C3D_Mtx* lhs, const C3D_Mtx* rhs)
360{
361 for (int i = 0; i < 16; i++)
362 out->m[i] = lhs->m[i] - rhs->m[i];
363}
364
365/**
366 * @brief Multiply two matrices
367 * @param[out] out Output matrix
368 * @param[in] a Multiplicand
369 * @param[in] b Multiplier
370 */
371void Mtx_Multiply(C3D_Mtx* out, const C3D_Mtx* a, const C3D_Mtx* b);
372
373/**
374 * @brief Inverse a matrix
375 * @param[in,out] out Matrix to inverse
376 * @retval 0.0f Degenerate matrix (no inverse)
377 * @return determinant
378 */
380
381/**
382 * @brief Multiply 3x3 matrix by a FVec3
383 * @param[in] mtx Matrix
384 * @param[in] v Vector
385 * @return mtx*v (product)
386 */
388
389/**
390 * @brief Multiply 4x4 matrix by a FVec4
391 * @param[in] mtx Matrix
392 * @param[in] v Vector
393 * @return mtx*v (product)
394 */
396
397/**
398 * @brief Multiply 4x3 matrix by a FVec3
399 * @param[in] mtx Matrix
400 * @param[in] v Vector
401 * @return mtx*v (product)
402 */
403static inline C3D_FVec Mtx_MultiplyFVecH(const C3D_Mtx* mtx, C3D_FVec v)
404{
405 v.w = 1.0f;
406
407 return Mtx_MultiplyFVec4(mtx, v);
408}
409
410/**
411 * @brief Get 4x4 matrix equivalent to Quaternion
412 * @param[out] m Output matrix
413 * @param[in] q Input Quaternion
414 */
416/** @} */
417
418/**
419 * @name 3D Transformation Matrix Math
420 * @note bRightSide is used to determine which side to perform the transformation.
421 * With an input matrix A and a transformation matrix B, bRightSide being
422 * true yields AB, while being false yield BA.
423 * @{
424 */
425
426/**
427 * @brief 3D translation
428 * @param[in,out] mtx Matrix to translate
429 * @param[in] x X component to translate
430 * @param[in] y Y component to translate
431 * @param[in] z Z component to translate
432 * @param[in] bRightSide Whether to transform from the right side
433 */
434void Mtx_Translate(C3D_Mtx* mtx, float x, float y, float z, bool bRightSide);
435
436/**
437 * @brief 3D Scale
438 * @param[in,out] mtx Matrix to scale
439 * @param[in] x X component to scale
440 * @param[in] y Y component to scale
441 * @param[in] z Z component to scale
442 */
443void Mtx_Scale(C3D_Mtx* mtx, float x, float y, float z);
444
445/**
446 * @brief 3D Rotation
447 * @param[in,out] mtx Matrix to rotate
448 * @param[in] axis Axis about which to rotate
449 * @param[in] angle Radians to rotate
450 * @param[in] bRightSide Whether to transform from the right side
451 */
452void Mtx_Rotate(C3D_Mtx* mtx, C3D_FVec axis, float angle, bool bRightSide);
453
454/**
455 * @brief 3D Rotation about the X axis
456 * @param[in,out] mtx Matrix to rotate
457 * @param[in] angle Radians to rotate
458 * @param[in] bRightSide Whether to transform from the right side
459 */
460void Mtx_RotateX(C3D_Mtx* mtx, float angle, bool bRightSide);
461
462/**
463 * @brief 3D Rotation about the Y axis
464 * @param[in,out] mtx Matrix to rotate
465 * @param[in] angle Radians to rotate
466 * @param[in] bRightSide Whether to transform from the right side
467 */
468void Mtx_RotateY(C3D_Mtx* mtx, float angle, bool bRightSide);
469
470/**
471 * @brief 3D Rotation about the Z axis
472 * @param[in,out] mtx Matrix to rotate
473 * @param[in] angle Radians to rotate
474 * @param[in] bRightSide Whether to transform from the right side
475 */
476void Mtx_RotateZ(C3D_Mtx* mtx, float angle, bool bRightSide);
477/** @} */
478
479/**
480 * @name 3D Projection Matrix Math
481 * @{
482 */
483
484/**
485 * @brief Orthogonal projection
486 * @param[out] mtx Output matrix
487 * @param[in] left Left clip plane (X=left)
488 * @param[in] right Right clip plane (X=right)
489 * @param[in] bottom Bottom clip plane (Y=bottom)
490 * @param[in] top Top clip plane (Y=top)
491 * @param[in] near Near clip plane (Z=near)
492 * @param[in] far Far clip plane (Z=far)
493 * @param[in] isLeftHanded Whether to build a LH projection
494 * @sa Mtx_OrthoTilt
495 */
496void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded);
497
498/**
499 * @brief Perspective projection
500 * @param[out] mtx Output matrix
501 * @param[in] fovy Vertical field of view in radians
502 * @param[in] aspect Aspect ration of projection plane (width/height)
503 * @param[in] near Near clip plane (Z=near)
504 * @param[in] far Far clip plane (Z=far)
505 * @param[in] isLeftHanded Whether to build a LH projection
506 * @sa Mtx_PerspTilt
507 * @sa Mtx_PerspStereo
508 * @sa Mtx_PerspStereoTilt
509 */
510void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded);
511
512/**
513 * @brief Stereo perspective projection
514 * @note Typically you will use iod to mean the distance between the eyes. Plug
515 * in -iod for the left eye and iod for the right eye.
516 * @note The focal length is defined by screen. If objects are further than this,
517 * they will appear to be inside the screen. If objects are closer than this,
518 * they will appear to pop out of the screen. Objects at this distance appear
519 * to be at the screen.
520 * @param[out] mtx Output matrix
521 * @param[in] fovy Vertical field of view in radians
522 * @param[in] aspect Aspect ration of projection plane (width/height)
523 * @param[in] near Near clip plane (Z=near)
524 * @param[in] far Far clip plane (Z=far)
525 * @param[in] iod Interocular distance
526 * @param[in] screen Focal length
527 * @param[in] isLeftHanded Whether to build a LH projection
528 * @sa Mtx_Persp
529 * @sa Mtx_PerspTilt
530 * @sa Mtx_PerspStereoTilt
531 */
532void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded);
533
534/**
535 * @brief Orthogonal projection, tilted to account for the 3DS screen rotation
536 * @param[out] mtx Output matrix
537 * @param[in] left Left clip plane (X=left)
538 * @param[in] right Right clip plane (X=right)
539 * @param[in] bottom Bottom clip plane (Y=bottom)
540 * @param[in] top Top clip plane (Y=top)
541 * @param[in] near Near clip plane (Z=near)
542 * @param[in] far Far clip plane (Z=far)
543 * @param[in] isLeftHanded Whether to build a LH projection
544 * @sa Mtx_Ortho
545 */
546void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded);
547
548/**
549 * @brief Perspective projection, tilted to account for the 3DS screen rotation
550 * @param[out] mtx Output matrix
551 * @param[in] fovy Vertical field of view in radians
552 * @param[in] aspect Aspect ration of projection plane (width/height)
553 * @param[in] near Near clip plane (Z=near)
554 * @param[in] far Far clip plane (Z=far)
555 * @param[in] isLeftHanded Whether to build a LH projection
556 * @sa Mtx_Persp
557 * @sa Mtx_PerspStereo
558 * @sa Mtx_PerspStereoTilt
559 */
560void Mtx_PerspTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded);
561
562/**
563 * @brief Stereo perspective projection, tilted to account for the 3DS screen rotation
564 * @note See the notes for @ref Mtx_PerspStereo
565 * @param[out] mtx Output matrix
566 * @param[in] fovy Vertical field of view in radians
567 * @param[in] aspect Aspect ration of projection plane (width/height)
568 * @param[in] near Near clip plane (Z=near)
569 * @param[in] far Far clip plane (Z=far)
570 * @param[in] iod Interocular distance
571 * @param[in] screen Focal length
572 * @param[in] isLeftHanded Whether to build a LH projection
573 * @sa Mtx_Persp
574 * @sa Mtx_PerspTilt
575 * @sa Mtx_PerspStereo
576 */
577void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded);
578
579/**
580 * @brief Look-At matrix, based on DirectX implementation
581 * @note See https://msdn.microsoft.com/en-us/library/windows/desktop/bb205342
582 * @param[out] out Output matrix.
583 * @param[in] cameraPosition Position of the intended camera in 3D space.
584 * @param[in] cameraTarget Position of the intended target the camera is supposed to face in 3D space.
585 * @param[in] cameraUpVector The vector that points straight up depending on the camera's "Up" direction.
586 * @param[in] isLeftHanded Whether to build a LH projection
587 */
588void Mtx_LookAt(C3D_Mtx* out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded);
589/** @} */
590
591/**
592 * @name Quaternion Math
593 * @{
594 */
595
596/**
597 * @brief Create a new Quaternion
598 * @param[in] i I-component
599 * @param[in] j J-component
600 * @param[in] k K-component
601 * @param[in] r Real component
602 * @return New Quaternion
603 */
604#define Quat_New(i,j,k,r) FVec4_New(i,j,k,r)
605
606/**
607 * @brief Negate a Quaternion
608 * @note This is equivalent to `Quat_Scale(v, -1)`
609 * @param[in] q Quaternion to negate
610 * @return -q
611 */
612#define Quat_Negate(q) FVec4_Negate(q)
613
614/**
615 * @brief Add two Quaternions
616 * @param[in] lhs Augend
617 * @param[in] rhs Addend
618 * @return lhs+rhs (sum)
619 */
620#define Quat_Add(lhs,rhs) FVec4_Add(lhs,rhs)
621
622/**
623 * @brief Subtract two Quaternions
624 * @param[in] lhs Minuend
625 * @param[in] rhs Subtrahend
626 * @return lhs-rhs (difference)
627 */
628#define Quat_Subtract(lhs,rhs) FVec4_Subtract(lhs,rhs)
629
630/**
631 * @brief Scale a Quaternion
632 * @param[in] q Quaternion to scale
633 * @param[in] s Scale factor
634 * @return q*s
635 */
636#define Quat_Scale(q,s) FVec4_Scale(q,s)
637
638/**
639 * @brief Normalize a Quaternion
640 * @param[in] q Quaternion to normalize
641 * @return q/‖q‖
642 */
643#define Quat_Normalize(q) FVec4_Normalize(q)
644
645/**
646 * @brief Dot product of two Quaternions
647 * @param[in] lhs Left-side Quaternion
648 * @param[in] rhs Right-side Quaternion
649 * @return lhs∙rhs
650 */
651#define Quat_Dot(lhs,rhs) FVec4_Dot(lhs,rhs)
652
653/**
654 * @brief Multiply two Quaternions
655 * @param[in] lhs Multiplicand
656 * @param[in] rhs Multiplier
657 * @return lhs*rhs
658 */
660
661/**
662 * @brief Raise Quaternion to a power
663 * @note If p is 0, this returns the identity Quaternion.
664 * If p is 1, this returns q.
665 * @param[in] q Base Quaternion
666 * @param[in] p Power
667 * @return q<sup>p</sup>
668 */
670
671/**
672 * @brief Cross product of Quaternion and FVec3
673 * @param[in] q Base Quaternion
674 * @param[in] v Vector to cross
675 * @return q×v
676 */
678
679/**
680 * @brief 3D Rotation
681 * @param[in] q Quaternion to rotate
682 * @param[in] axis Axis about which to rotate
683 * @param[in] r Radians to rotate
684 * @param[in] bRightSide Whether to transform from the right side
685 * @return Rotated Quaternion
686 */
687C3D_FQuat Quat_Rotate(C3D_FQuat q, C3D_FVec axis, float r, bool bRightSide);
688
689/**
690 * @brief 3D Rotation about the X axis
691 * @param[in] q Quaternion to rotate
692 * @param[in] r Radians to rotate
693 * @param[in] bRightSide Whether to transform from the right side
694 * @return Rotated Quaternion
695 */
696C3D_FQuat Quat_RotateX(C3D_FQuat q, float r, bool bRightSide);
697
698/**
699 * @brief 3D Rotation about the Y axis
700 * @param[in] q Quaternion to rotate
701 * @param[in] r Radians to rotate
702 * @param[in] bRightSide Whether to transform from the right side
703 * @return Rotated Quaternion
704 */
705C3D_FQuat Quat_RotateY(C3D_FQuat q, float r, bool bRightSide);
706
707/**
708 * @brief 3D Rotation about the Z axis
709 * @param[in] q Quaternion to rotate
710 * @param[in] r Radians to rotate
711 * @param[in] bRightSide Whether to transform from the right side
712 * @return Rotated Quaternion
713 */
714C3D_FQuat Quat_RotateZ(C3D_FQuat q, float r, bool bRightSide);
715
716/**
717 * @brief Get Quaternion equivalent to 4x4 matrix
718 * @note If the matrix is orthogonal or special orthogonal, where determinant(matrix) = +1.0f, then the matrix can be converted.
719 * @param[in] m Input Matrix
720 * @return Generated Quaternion
721 */
723
724/**
725 * @brief Identity Quaternion
726 * @return Identity Quaternion
727 */
728static inline C3D_FQuat Quat_Identity(void)
729{
730 // r=1, i=j=k=0
731 return Quat_New(0.0f, 0.0f, 0.0f, 1.0f);
732}
733
734/**
735 * @brief Quaternion conjugate
736 * @param[in] q Quaternion of which to get conjugate
737 * @return q*
738 */
740{
741 // q* = q.r - q.i - q.j - q.k
742 return Quat_New(-q.i, -q.j, -q.k, q.r);
743}
744
745/**
746 * @brief Quaternion inverse
747 * @note This is equivalent to `Quat_Pow(v, -1)`
748 * @param[in] q Quaternion of which to get inverse
749 * @return q<sup>-1</sup>
750 */
752{
753 // q^-1 = (q.r - q.i - q.j - q.k) / (q.r^2 + q.i^2 + q.j^2 + q.k^2)
754 // = q* / (q∙q)
756 float d = Quat_Dot(q, q);
757 return Quat_New(c.i/d, c.j/d, c.k/d, c.r/d);
758}
759
760/**
761 * @brief Cross product of FVec3 and Quaternion
762 * @param[in] v Base FVec3
763 * @param[in] q Quaternion to cross
764 * @return v×q
765 */
767{
768 // v×q = (q^-1)×v
769 return Quat_CrossFVec3(Quat_Inverse(q), v);
770}
771
772/**
773 * @brief Converting Pitch, Yaw, and Roll to Quaternion equivalent
774 * @param[in] pitch The pitch angle in radians.
775 * @param[in] yaw The yaw angle in radians.
776 * @param[in] roll The roll angle in radians.
777 * @param[in] bRightSide Whether to transform from the right side
778 * @return C3D_FQuat The Quaternion equivalent with the pitch, yaw, and roll (in that order) orientations applied.
779 */
780C3D_FQuat Quat_FromPitchYawRoll(float pitch, float yaw, float roll, bool bRightSide);
781
782/**
783 * @brief Quaternion Look-At
784 * @param[in] source C3D_FVec Starting position. Origin of rotation.
785 * @param[in] target C3D_FVec Target position to orient towards.
786 * @param[in] forwardVector C3D_FVec The Up vector.
787 * @param[in] upVector C3D_FVec The Up vector.
788 * @return Quaternion rotation.
789 */
790C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector);
791
792/**
793 * @brief Quaternion, created from a given axis and angle in radians.
794 * @param[in] axis C3D_FVec The axis to rotate around at.
795 * @param[in] angle float The angle to rotate. Unit: Radians
796 * @return Quaternion rotation based on the axis and angle. Axis doesn't have to be orthogonal.
797 */
799/** @} */
800/** @} */
void Mtx_PerspStereoTilt(C3D_Mtx *mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded)
Stereo perspective projection, tilted to account for the 3DS screen rotation.
static C3D_FVec FVec3_Scale(C3D_FVec v, float s)
Scale a FVec3.
Definition maths.h:249
C3D_FQuat Quat_RotateX(C3D_FQuat q, float r, bool bRightSide)
3D Rotation about the X axis
void Mtx_OrthoTilt(C3D_Mtx *mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded)
Orthogonal projection, tilted to account for the 3DS screen rotation.
#define Quat_New(i, j, k, r)
Create a new Quaternion.
Definition maths.h:604
static C3D_FVec FVec4_New(float x, float y, float z, float w)
Create a new FVec4.
Definition maths.h:57
static C3D_FVec FVec4_Add(C3D_FVec lhs, C3D_FVec rhs)
Add two FVec4s.
Definition maths.h:68
void Mtx_Rotate(C3D_Mtx *mtx, C3D_FVec axis, float angle, bool bRightSide)
3D Rotation
static C3D_FVec FVec3_Subtract(C3D_FVec lhs, C3D_FVec rhs)
Subtract two FVec3s.
Definition maths.h:225
static void Mtx_Diagonal(C3D_Mtx *out, float x, float y, float z, float w)
Creates a matrix with the diagonal using the given parameters.
Definition maths.h:315
C3D_FQuat Quat_FromPitchYawRoll(float pitch, float yaw, float roll, bool bRightSide)
Converting Pitch, Yaw, and Roll to Quaternion equivalent.
static C3D_FVec FVec4_Scale(C3D_FVec v, float s)
Scale a FVec4.
Definition maths.h:104
static void Mtx_Identity(C3D_Mtx *out)
Identity matrix.
Definition maths.h:328
void Mtx_Transpose(C3D_Mtx *out)
Transposes the matrix. Row => Column, and vice versa.
static float FVec3_Magnitude(C3D_FVec v)
Magnitude of a FVec3.
Definition maths.h:187
static C3D_FVec FVec3_New(float x, float y, float z)
Create a new FVec3.
Definition maths.h:165
void Mtx_Translate(C3D_Mtx *mtx, float x, float y, float z, bool bRightSide)
3D translation
static C3D_FQuat Quat_Identity(void)
Identity Quaternion.
Definition maths.h:728
C3D_FVec Quat_CrossFVec3(C3D_FQuat q, C3D_FVec v)
Cross product of Quaternion and FVec3.
static C3D_FVec Mtx_MultiplyFVecH(const C3D_Mtx *mtx, C3D_FVec v)
Multiply 4x3 matrix by a FVec3.
Definition maths.h:403
static C3D_FVec FVec3_Add(C3D_FVec lhs, C3D_FVec rhs)
Add two FVec3s.
Definition maths.h:213
void Mtx_PerspStereo(C3D_Mtx *mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded)
Stereo perspective projection.
void Mtx_Persp(C3D_Mtx *mtx, float fovy, float aspect, float near, float far, bool isLeftHanded)
Perspective projection.
void Mtx_Scale(C3D_Mtx *mtx, float x, float y, float z)
3D Scale
static float FVec4_Dot(C3D_FVec lhs, C3D_FVec rhs)
Dot product of two FVec4s.
Definition maths.h:127
static void Mtx_Copy(C3D_Mtx *out, const C3D_Mtx *in)
Copy a matrix.
Definition maths.h:302
static C3D_FQuat Quat_Conjugate(C3D_FQuat q)
Quaternion conjugate.
Definition maths.h:739
C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector)
Quaternion Look-At.
static C3D_FVec FVec4_Subtract(C3D_FVec lhs, C3D_FVec rhs)
Subtract two FVec4s.
Definition maths.h:80
static C3D_FVec FVec4_Negate(C3D_FVec v)
Negate a FVec4.
Definition maths.h:92
C3D_FQuat Quat_FromAxisAngle(C3D_FVec axis, float angle)
Quaternion, created from a given axis and angle in radians.
static C3D_FVec FVec3_Normalize(C3D_FVec v)
Normalize a FVec3.
Definition maths.h:198
void Mtx_LookAt(C3D_Mtx *out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded)
Look-At matrix, based on DirectX implementation.
float Mtx_Inverse(C3D_Mtx *out)
Inverse a matrix.
static C3D_FVec FVec3_Cross(C3D_FVec lhs, C3D_FVec rhs)
Cross product of two FVec3s.
Definition maths.h:275
static C3D_FQuat Quat_Inverse(C3D_FQuat q)
Quaternion inverse.
Definition maths.h:751
static float FVec4_Magnitude(C3D_FVec v)
Magnitude of a FVec4.
Definition maths.h:138
void Mtx_RotateY(C3D_Mtx *mtx, float angle, bool bRightSide)
3D Rotation about the Y axis
C3D_FQuat Quat_Multiply(C3D_FQuat lhs, C3D_FQuat rhs)
Multiply two Quaternions.
C3D_FQuat Quat_Pow(C3D_FQuat q, float p)
Raise Quaternion to a power.
void Mtx_Ortho(C3D_Mtx *mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded)
Orthogonal projection.
static void Mtx_Add(C3D_Mtx *out, const C3D_Mtx *lhs, const C3D_Mtx *rhs)
Matrix addition.
Definition maths.h:346
C3D_FVec Mtx_MultiplyFVec3(const C3D_Mtx *mtx, C3D_FVec v)
Multiply 3x3 matrix by a FVec3.
void Mtx_RotateX(C3D_Mtx *mtx, float angle, bool bRightSide)
3D Rotation about the X axis
void Mtx_Multiply(C3D_Mtx *out, const C3D_Mtx *a, const C3D_Mtx *b)
Multiply two matrices.
void Mtx_PerspTilt(C3D_Mtx *mtx, float fovy, float aspect, float near, float far, bool isLeftHanded)
Perspective projection, tilted to account for the 3DS screen rotation.
static float FVec3_Dot(C3D_FVec lhs, C3D_FVec rhs)
Dot product of two FVec3s.
Definition maths.h:176
C3D_FQuat Quat_RotateY(C3D_FQuat q, float r, bool bRightSide)
3D Rotation about the Y axis
C3D_FQuat Quat_Rotate(C3D_FQuat q, C3D_FVec axis, float r, bool bRightSide)
3D Rotation
static float FVec3_Distance(C3D_FVec lhs, C3D_FVec rhs)
Distance between two 3D points.
Definition maths.h:237
static void Mtx_Subtract(C3D_Mtx *out, const C3D_Mtx *lhs, const C3D_Mtx *rhs)
Matrix subtraction.
Definition maths.h:359
static C3D_FVec FVec4_Normalize(C3D_FVec v)
Normalize a FVec4.
Definition maths.h:149
static C3D_FVec FVec4_PerspDivide(C3D_FVec v)
Perspective divide.
Definition maths.h:115
C3D_FVec Mtx_MultiplyFVec4(const C3D_Mtx *mtx, C3D_FVec v)
Multiply 4x4 matrix by a FVec4.
static C3D_FVec FVec3_CrossQuat(C3D_FVec v, C3D_FQuat q)
Cross product of FVec3 and Quaternion.
Definition maths.h:766
void Mtx_FromQuat(C3D_Mtx *m, C3D_FQuat q)
Get 4x4 matrix equivalent to Quaternion.
static void Mtx_Zeros(C3D_Mtx *out)
Zero matrix.
Definition maths.h:292
#define Quat_Dot(lhs, rhs)
Dot product of two Quaternions.
Definition maths.h:651
void Mtx_RotateZ(C3D_Mtx *mtx, float angle, bool bRightSide)
3D Rotation about the Z axis
static C3D_FVec FVec3_Negate(C3D_FVec v)
Negate a FVec3.
Definition maths.h:261
C3D_FQuat Quat_FromMtx(const C3D_Mtx *m)
Get Quaternion equivalent to 4x4 matrix.
C3D_FQuat Quat_RotateZ(C3D_FQuat q, float r, bool bRightSide)
3D Rotation about the Z axis
Float vector.
Definition types.h:52
float x
X-component.
Definition types.h:61
float j
J-component.
Definition types.h:71
float z
Z-component.
Definition types.h:59
float w
W-component.
Definition types.h:58
float k
K-component.
Definition types.h:70
float r
Real component.
Definition types.h:69
float i
I-component.
Definition types.h:72
float y
Y-component.
Definition types.h:60
Row-major 4x4 matrix.
Definition types.h:91
C3D_FVec r[4]
Rows are vectors.
Definition types.h:92
float m[4 *4]
Raw access.
Definition types.h:93