citro3d  1.2.0
maths.h
Go to the documentation of this file.
1 #pragma once
2 #include "types.h"
3 #include <math.h>
4 #include <string.h>
5 
16 #define M_TAU (2*M_PI)
17 
23 #define C3D_Angle(_angle) ((_angle)*M_TAU)
24 
30 #define C3D_AngleFromDegrees(_angle) ((_angle)*M_TAU/360.0f)
31 
32 #define C3D_AspectRatioTop (400.0f / 240.0f)
33 #define C3D_AspectRatioBot (320.0f / 240.0f)
34 
48 static inline C3D_FVec FVec4_New(float x, float y, float z, float w)
49 {
50  return (C3D_FVec){{ w, z, y, x }};
51 }
52 
59 static inline C3D_FVec FVec4_Add(C3D_FVec lhs, C3D_FVec rhs)
60 {
61  // component-wise addition
62  return FVec4_New(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w);
63 }
64 
71 static inline C3D_FVec FVec4_Subtract(C3D_FVec lhs, C3D_FVec rhs)
72 {
73  // component-wise subtraction
74  return FVec4_New(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w);
75 }
76 
83 static inline C3D_FVec FVec4_Negate(C3D_FVec v)
84 {
85  // component-wise negation
86  return FVec4_New(-v.x, -v.y, -v.z, -v.w);
87 }
88 
95 static inline C3D_FVec FVec4_Scale(C3D_FVec v, float s)
96 {
97  // component-wise scaling
98  return FVec4_New(v.x*s, v.y*s, v.z*s, v.w*s);
99 }
100 
107 {
108  // divide by w
109  return FVec4_New(v.x/v.w, v.y/v.w, v.z/v.w, 1.0f);
110 }
111 
118 static inline float FVec4_Dot(C3D_FVec lhs, C3D_FVec rhs)
119 {
120  // A∙B = sum of component-wise products
121  return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z + lhs.w*rhs.w;
122 }
123 
129 static inline float FVec4_Magnitude(C3D_FVec v)
130 {
131  // ‖v‖ = √(v∙v)
132  return sqrtf(FVec4_Dot(v,v));
133 }
134 
141 {
142  // get vector magnitude
143  float m = FVec4_Magnitude(v);
144 
145  // scale by inverse magnitude to get a unit vector
146  return FVec4_New(v.x/m, v.y/m, v.z/m, v.w/m);
147 }
148 
156 static inline C3D_FVec FVec3_New(float x, float y, float z)
157 {
158  return FVec4_New(x, y, z, 0.0f);
159 }
160 
167 static inline float FVec3_Dot(C3D_FVec lhs, C3D_FVec rhs)
168 {
169  // A∙B = sum of component-wise products
170  return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
171 }
172 
178 static inline float FVec3_Magnitude(C3D_FVec v)
179 {
180  // ‖v‖ = √(v∙v)
181  return sqrtf(FVec3_Dot(v,v));
182 }
183 
190 {
191  // get vector magnitude
192  float m = FVec3_Magnitude(v);
193 
194  // scale by inverse magnitude to get a unit vector
195  return FVec3_New(v.x/m, v.y/m, v.z/m);
196 }
197 
204 static inline C3D_FVec FVec3_Add(C3D_FVec lhs, C3D_FVec rhs)
205 {
206  // component-wise addition
207  return FVec3_New(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z);
208 }
209 
216 static inline C3D_FVec FVec3_Subtract(C3D_FVec lhs, C3D_FVec rhs)
217 {
218  // component-wise subtraction
219  return FVec3_New(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z);
220 }
221 
228 static inline float FVec3_Distance(C3D_FVec lhs, C3D_FVec rhs)
229 {
230  // distance = ‖lhs-rhs‖
231  return FVec3_Magnitude(FVec3_Subtract(lhs, rhs));
232 }
233 
240 static inline C3D_FVec FVec3_Scale(C3D_FVec v, float s)
241 {
242  // component-wise scaling
243  return FVec3_New(v.x*s, v.y*s, v.z*s);
244 }
245 
253 {
254  // component-wise negation
255  return FVec3_New(-v.x, -v.y, -v.z);
256 }
257 
266 static inline C3D_FVec FVec3_Cross(C3D_FVec lhs, C3D_FVec rhs)
267 {
268  // A×B = (AyBz - AzBy, AzBx - AxBz, AxBy - AyBx)
269  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);
270 }
283 static inline void Mtx_Zeros(C3D_Mtx* out)
284 {
285  memset(out, 0, sizeof(*out));
286 }
287 
293 static inline void Mtx_Copy(C3D_Mtx* out, const C3D_Mtx* in)
294 {
295  *out = *in;
296 }
297 
306 static inline void Mtx_Diagonal(C3D_Mtx* out, float x, float y, float z, float w)
307 {
308  Mtx_Zeros(out);
309  out->r[0].x = x;
310  out->r[1].y = y;
311  out->r[2].z = z;
312  out->r[3].w = w;
313 }
314 
319 static inline void Mtx_Identity(C3D_Mtx* out)
320 {
321  Mtx_Diagonal(out, 1.0f, 1.0f, 1.0f, 1.0f);
322 }
323 
328 void Mtx_Transpose(C3D_Mtx* out);
329 
337 static inline void Mtx_Add(C3D_Mtx* out, const C3D_Mtx* lhs, const C3D_Mtx* rhs)
338 {
339  for (int i = 0; i < 16; i++)
340  out->m[i] = lhs->m[i] + rhs->m[i];
341 }
342 
350 static inline void Mtx_Subtract(C3D_Mtx* out, const C3D_Mtx* lhs, const C3D_Mtx* rhs)
351 {
352  for (int i = 0; i < 16; i++)
353  out->m[i] = lhs->m[i] - rhs->m[i];
354 }
355 
362 void Mtx_Multiply(C3D_Mtx* out, const C3D_Mtx* a, const C3D_Mtx* b);
363 
370 float Mtx_Inverse(C3D_Mtx* out);
371 
379 
387 
394 static inline C3D_FVec Mtx_MultiplyFVecH(const C3D_Mtx* mtx, C3D_FVec v)
395 {
396  v.w = 1.0f;
397 
398  return Mtx_MultiplyFVec4(mtx, v);
399 }
400 
406 void Mtx_FromQuat(C3D_Mtx* m, C3D_FQuat q);
425 void Mtx_Translate(C3D_Mtx* mtx, float x, float y, float z, bool bRightSide);
426 
434 void Mtx_Scale(C3D_Mtx* mtx, float x, float y, float z);
435 
443 void Mtx_Rotate(C3D_Mtx* mtx, C3D_FVec axis, float angle, bool bRightSide);
444 
451 void Mtx_RotateX(C3D_Mtx* mtx, float angle, bool bRightSide);
452 
459 void Mtx_RotateY(C3D_Mtx* mtx, float angle, bool bRightSide);
460 
467 void Mtx_RotateZ(C3D_Mtx* mtx, float angle, bool bRightSide);
487 void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded);
488 
501 void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded);
502 
523 void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded);
524 
537 void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded);
538 
551 void Mtx_PerspTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded);
552 
568 void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded);
569 
579 void Mtx_LookAt(C3D_Mtx* out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded);
595 #define Quat_New(i,j,k,r) FVec4_New(i,j,k,r)
596 
603 #define Quat_Negate(q) FVec4_Negate(q)
604 
611 #define Quat_Add(lhs,rhs) FVec4_Add(lhs,rhs)
612 
619 #define Quat_Subtract(lhs,rhs) FVec4_Subtract(lhs,rhs)
620 
627 #define Quat_Scale(q,s) FVec4_Scale(q,s)
628 
634 #define Quat_Normalize(q) FVec4_Normalize(q)
635 
642 #define Quat_Dot(lhs,rhs) FVec4_Dot(lhs,rhs)
643 
651 
660 C3D_FQuat Quat_Pow(C3D_FQuat q, float p);
661 
669 
678 C3D_FQuat Quat_Rotate(C3D_FQuat q, C3D_FVec axis, float r, bool bRightSide);
679 
687 C3D_FQuat Quat_RotateX(C3D_FQuat q, float r, bool bRightSide);
688 
696 C3D_FQuat Quat_RotateY(C3D_FQuat q, float r, bool bRightSide);
697 
705 C3D_FQuat Quat_RotateZ(C3D_FQuat q, float r, bool bRightSide);
706 
713 C3D_FQuat Quat_FromMtx(const C3D_Mtx* m);
714 
719 static inline C3D_FQuat Quat_Identity(void)
720 {
721  // r=1, i=j=k=0
722  return Quat_New(0.0f, 0.0f, 0.0f, 1.0f);
723 }
724 
731 {
732  // q* = q.r - q.i - q.j - q.k
733  return Quat_New(-q.i, -q.j, -q.k, q.r);
734 }
735 
743 {
744  // q^-1 = (q.r - q.i - q.j - q.k) / (q.r^2 + q.i^2 + q.j^2 + q.k^2)
745  // = q* / (q∙q)
746  C3D_FQuat c = Quat_Conjugate(q);
747  float d = Quat_Dot(q, q);
748  return Quat_New(c.i/d, c.j/d, c.k/d, c.r/d);
749 }
750 
758 {
759  // v×q = (q^-1)×v
760  return Quat_CrossFVec3(Quat_Inverse(q), v);
761 }
762 
771 C3D_FQuat Quat_FromPitchYawRoll(float pitch, float yaw, float roll, bool bRightSide);
772 
781 C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector);
782 
789 C3D_FQuat Quat_FromAxisAngle(C3D_FVec axis, float angle);
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.
Definition: mtx_perspstereotilt.c:3
static C3D_FVec FVec3_Scale(C3D_FVec v, float s)
Scale a FVec3.
Definition: maths.h:240
C3D_FQuat Quat_RotateX(C3D_FQuat q, float r, bool bRightSide)
3D Rotation about the X axis
Definition: quat_rotatex.c:3
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.
Definition: mtx_orthotilt.c:3
#define Quat_New(i, j, k, r)
Create a new Quaternion.
Definition: maths.h:595
static C3D_FVec FVec4_New(float x, float y, float z, float w)
Create a new FVec4.
Definition: maths.h:48
static C3D_FVec FVec4_Add(C3D_FVec lhs, C3D_FVec rhs)
Add two FVec4s.
Definition: maths.h:59
void Mtx_Rotate(C3D_Mtx *mtx, C3D_FVec axis, float angle, bool bRightSide)
3D Rotation
Definition: mtx_rotate.c:3
static C3D_FVec FVec3_Subtract(C3D_FVec lhs, C3D_FVec rhs)
Subtract two FVec3s.
Definition: maths.h:216
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:306
C3D_FQuat Quat_FromPitchYawRoll(float pitch, float yaw, float roll, bool bRightSide)
Converting Pitch, Yaw, and Roll to Quaternion equivalent.
Definition: quat_frompitchyawroll.c:3
static C3D_FVec FVec4_Scale(C3D_FVec v, float s)
Scale a FVec4.
Definition: maths.h:95
static void Mtx_Identity(C3D_Mtx *out)
Identity matrix.
Definition: maths.h:319
void Mtx_Transpose(C3D_Mtx *out)
Transposes the matrix. Row => Column, and vice versa.
Definition: mtx_transpose.c:3
static float FVec3_Magnitude(C3D_FVec v)
Magnitude of a FVec3.
Definition: maths.h:178
static C3D_FVec FVec3_New(float x, float y, float z)
Create a new FVec3.
Definition: maths.h:156
void Mtx_Translate(C3D_Mtx *mtx, float x, float y, float z, bool bRightSide)
3D translation
Definition: mtx_translate.c:3
static C3D_FQuat Quat_Identity(void)
Identity Quaternion.
Definition: maths.h:719
C3D_FVec Quat_CrossFVec3(C3D_FQuat q, C3D_FVec v)
Cross product of Quaternion and FVec3.
Definition: quat_crossfvec3.c:3
static C3D_FVec Mtx_MultiplyFVecH(const C3D_Mtx *mtx, C3D_FVec v)
Multiply 4x3 matrix by a FVec3.
Definition: maths.h:394
static C3D_FVec FVec3_Add(C3D_FVec lhs, C3D_FVec rhs)
Add two FVec3s.
Definition: maths.h:204
void Mtx_PerspStereo(C3D_Mtx *mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded)
Stereo perspective projection.
Definition: mtx_perspstereo.c:3
void Mtx_Persp(C3D_Mtx *mtx, float fovy, float aspect, float near, float far, bool isLeftHanded)
Perspective projection.
Definition: mtx_persp.c:3
void Mtx_Scale(C3D_Mtx *mtx, float x, float y, float z)
3D Scale
Definition: mtx_scale.c:3
static float FVec4_Dot(C3D_FVec lhs, C3D_FVec rhs)
Dot product of two FVec4s.
Definition: maths.h:118
static void Mtx_Copy(C3D_Mtx *out, const C3D_Mtx *in)
Copy a matrix.
Definition: maths.h:293
static C3D_FQuat Quat_Conjugate(C3D_FQuat q)
Quaternion conjugate.
Definition: maths.h:730
C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector)
Quaternion Look-At.
Definition: quat_lookat.c:4
static C3D_FVec FVec4_Subtract(C3D_FVec lhs, C3D_FVec rhs)
Subtract two FVec4s.
Definition: maths.h:71
static C3D_FVec FVec4_Negate(C3D_FVec v)
Negate a FVec4.
Definition: maths.h:83
C3D_FQuat Quat_FromAxisAngle(C3D_FVec axis, float angle)
Quaternion, created from a given axis and angle in radians.
Definition: quat_fromaxisangle.c:3
static C3D_FVec FVec3_Normalize(C3D_FVec v)
Normalize a FVec3.
Definition: maths.h:189
void Mtx_LookAt(C3D_Mtx *out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded)
Look-At matrix, based on DirectX implementation.
Definition: mtx_lookat.c:3
float Mtx_Inverse(C3D_Mtx *out)
Inverse a matrix.
Definition: mtx_inverse.c:4
static C3D_FVec FVec3_Cross(C3D_FVec lhs, C3D_FVec rhs)
Cross product of two FVec3s.
Definition: maths.h:266
static C3D_FQuat Quat_Inverse(C3D_FQuat q)
Quaternion inverse.
Definition: maths.h:742
static float FVec4_Magnitude(C3D_FVec v)
Magnitude of a FVec4.
Definition: maths.h:129
void Mtx_RotateY(C3D_Mtx *mtx, float angle, bool bRightSide)
3D Rotation about the Y axis
Definition: mtx_rotatey.c:3
C3D_FQuat Quat_Multiply(C3D_FQuat lhs, C3D_FQuat rhs)
Multiply two Quaternions.
Definition: quat_multiply.c:3
C3D_FQuat Quat_Pow(C3D_FQuat q, float p)
Raise Quaternion to a power.
Definition: quat_pow.c:4
void Mtx_Ortho(C3D_Mtx *mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded)
Orthogonal projection.
Definition: mtx_ortho.c:3
static void Mtx_Add(C3D_Mtx *out, const C3D_Mtx *lhs, const C3D_Mtx *rhs)
Matrix addition.
Definition: maths.h:337
C3D_FVec Mtx_MultiplyFVec3(const C3D_Mtx *mtx, C3D_FVec v)
Multiply 3x3 matrix by a FVec3.
Definition: mtx_multiplyfvec3.c:3
void Mtx_RotateX(C3D_Mtx *mtx, float angle, bool bRightSide)
3D Rotation about the X axis
Definition: mtx_rotatex.c:3
void Mtx_Multiply(C3D_Mtx *out, const C3D_Mtx *a, const C3D_Mtx *b)
Multiply two matrices.
Definition: mtx_multiply.c:3
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.
Definition: mtx_persptilt.c:3
static float FVec3_Dot(C3D_FVec lhs, C3D_FVec rhs)
Dot product of two FVec3s.
Definition: maths.h:167
C3D_FQuat Quat_RotateY(C3D_FQuat q, float r, bool bRightSide)
3D Rotation about the Y axis
Definition: quat_rotatey.c:3
C3D_FQuat Quat_Rotate(C3D_FQuat q, C3D_FVec axis, float r, bool bRightSide)
3D Rotation
Definition: quat_rotate.c:3
static float FVec3_Distance(C3D_FVec lhs, C3D_FVec rhs)
Distance between two 3D points.
Definition: maths.h:228
static void Mtx_Subtract(C3D_Mtx *out, const C3D_Mtx *lhs, const C3D_Mtx *rhs)
Matrix subtraction.
Definition: maths.h:350
static C3D_FVec FVec4_Normalize(C3D_FVec v)
Normalize a FVec4.
Definition: maths.h:140
static C3D_FVec FVec4_PerspDivide(C3D_FVec v)
Perspective divide.
Definition: maths.h:106
C3D_FVec Mtx_MultiplyFVec4(const C3D_Mtx *mtx, C3D_FVec v)
Multiply 4x4 matrix by a FVec4.
Definition: mtx_multiplyfvec4.c:3
static C3D_FVec FVec3_CrossQuat(C3D_FVec v, C3D_FQuat q)
Cross product of FVec3 and Quaternion.
Definition: maths.h:757
void Mtx_FromQuat(C3D_Mtx *m, C3D_FQuat q)
Get 4x4 matrix equivalent to Quaternion.
Definition: mtx_fromquat.c:3
static void Mtx_Zeros(C3D_Mtx *out)
Zero matrix.
Definition: maths.h:283
#define Quat_Dot(lhs, rhs)
Dot product of two Quaternions.
Definition: maths.h:642
void Mtx_RotateZ(C3D_Mtx *mtx, float angle, bool bRightSide)
3D Rotation about the Z axis
Definition: mtx_rotatez.c:3
static C3D_FVec FVec3_Negate(C3D_FVec v)
Negate a FVec3.
Definition: maths.h:252
C3D_FQuat Quat_FromMtx(const C3D_Mtx *m)
Get Quaternion equivalent to 4x4 matrix.
Definition: quat_frommtx.c:3
C3D_FQuat Quat_RotateZ(C3D_FQuat q, float r, bool bRightSide)
3D Rotation about the Z axis
Definition: quat_rotatez.c:3
Float quaternion. See C3D_FVec.
Float vector.
Definition: types.h:37
float x
X-component.
Definition: types.h:46
float z
Z-component.
Definition: types.h:44
float w
W-component.
Definition: types.h:43
float y
Y-component.
Definition: types.h:45
Row-major 4x4 matrix.
Definition: types.h:77
C3D_FVec r[4]
Rows are vectors.
Definition: types.h:78
float m[4 *4]
Raw access.
Definition: types.h:79