citro3d
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  */
57 static 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  */
68 static 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  */
80 static inline C3D_FVec FVec4_Subtract(C3D_FVec lhs, C3D_FVec rhs)
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  */
92 static inline C3D_FVec FVec4_Negate(C3D_FVec v)
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  */
104 static 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  */
127 static 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  */
138 static 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  */
165 static 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  */
176 static 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  */
187 static 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  */
213 static 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  */
225 static inline C3D_FVec FVec3_Subtract(C3D_FVec lhs, C3D_FVec rhs)
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  */
237 static 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  */
249 static 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  */
275 static 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  */
292 static 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  */
302 static 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  */
315 static 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  */
328 static 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  */
346 static 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  */
359 static 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  */
371 void 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  */
379 float Mtx_Inverse(C3D_Mtx* out);
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  */
403 static 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  */
434 void 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  */
443 void 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  */
452 void 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  */
460 void 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  */
468 void 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  */
476 void 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  */
496 void 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  */
510 void 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  */
532 void 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  */
546 void 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  */
560 void 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  */
577 void 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  */
588 void 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  */
687 C3D_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  */
696 C3D_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  */
705 C3D_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  */
714 C3D_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  */
728 static 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)
755  C3D_FQuat c = Quat_Conjugate(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  */
780 C3D_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  */
790 C3D_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