9ec2fc8bc43c9dd4692dc2a5d965aac668a3cdee
[gph-cmath] / src / cgmath.h
1 /* C version of the graphene math library
2  * Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
3  *
4  * This program is free software. Feel free to use, modify, and/or redistribute
5  * it under the terms of the MIT/X11 license. See LICENSE for details.
6  * If you intend to redistribute parts of the code without the LICENSE file
7  * replace this paragraph with the full contents of the LICENSE file.
8  *
9  * Function prefixes signify the data type of their operand(s):
10  * - cgm_v... functions are operations on cgm_vec3 vectors
11  * - cgm_w... functions are operations on cgm_vec4 vectors
12  * - cgm_q... functions are operations on cgm_quat quaternions (w + xi + yj + zk)
13  * - cgm_m... functions are operations on 4x4 matrices (stored as linear 16 float arrays)
14  *
15  * NOTE: *ALL* matrix arguments are pointers to 16 floats. Even the functions
16  * which operate on 3x3 matrices, actually use the upper 3x3 of a 4x4 matrix,
17  * and still expect an array of 16 floats.
18  *
19  * NOTE: matrices are treated by all operations as column-major, to match OpenGL
20  * conventions, so everything is pretty much transposed.
21  */
22 #ifndef CGMATH_H_
23 #define CGMATH_H_
24
25 #include <math.h>
26 #include <string.h>
27
28 typedef struct {
29         float x, y, z;
30 } cgm_vec3;
31
32 typedef struct {
33         float x, y, z, w;
34 } cgm_vec4, cgm_quat;
35
36 typedef enum cgm_euler_mode {
37         CGM_EULER_XYZ,
38         CGM_EULER_XZY,
39         CGM_EULER_YXZ,
40         CGM_EULER_YZX,
41         CGM_EULER_ZXY,
42         CGM_EULER_ZYX,
43         CGM_EULER_ZXZ,
44         CGM_EULER_ZYZ,
45         CGM_EULER_YXY,
46         CGM_EULER_YZY,
47         CGM_EULER_XYX,
48         CGM_EULER_XZX
49 } cgm_euler_mode;
50
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54
55 /* --- operations on cgm_vec3 --- */
56 static inline void cgm_vcons(cgm_vec3 *v, float x, float y, float z);
57
58 static inline void cgm_vadd(cgm_vec3 *a, const cgm_vec3 *b);
59 static inline void cgm_vsub(cgm_vec3 *a, const cgm_vec3 *b);
60 static inline void cgm_vmul(cgm_vec3 *a, const cgm_vec3 *b);
61 static inline void cgm_vscale(cgm_vec3 *v, float s);
62 static inline void cgm_vmul_m4v3(cgm_vec3 *v, const float *m);  /* m4x4 * v */
63 static inline void cgm_vmul_v3m4(cgm_vec3 *v, const float *m);  /* v * m4x4 */
64 static inline void cgm_vmul_m3v3(cgm_vec3 *v, const float *m);  /* m3x3 * v (m still 16 floats) */
65 static inline void cgm_vmul_v3m3(cgm_vec3 *v, const float *m);  /* v * m3x3 (m still 16 floats) */
66
67 static inline float cgm_vdot(const cgm_vec3 *a, const cgm_vec3 *b);
68 static inline void cgm_vcross(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b);
69 static inline float cgm_vlength(const cgm_vec3 *v);
70 static inline float cgm_vlength_sq(const cgm_vec3 *v);
71 static inline float cgm_vdist(const cgm_vec3 *a, const cgm_vec3 *b);
72 static inline float cgm_vdist_sq(const cgm_vec3 *a, const cgm_vec3 *b);
73 static inline void cgm_vnormalize(cgm_vec3 *v);
74
75 static inline void cgm_vreflect(cgm_vec3 *v, const cgm_vec3 *n);
76 static inline void cgm_vrefract(cgm_vec3 *v, const cgm_vec3 *n, float ior);
77
78 static inline void cgm_vrotate_quat(cgm_vec3 *v, const cgm_quat *q);
79 static inline void cgm_vrotate_axis(cgm_vec3 *v, const cgm_vec3 *axis, float angle);
80 static inline void cgm_vrotate_euler(cgm_vec3 *v, const cgm_vec3 *euler, enum cgm_euler_mode mode);
81
82 static inline void cgm_vlerp(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b, float t);
83
84 /* --- operations on cgm_vec4 --- */
85 static inline void cgm_wcons(cgm_vec4 *v, float x, float y, float z, float w);
86
87 static inline void cgm_wadd(cgm_vec4 *a, const cgm_vec4 *b);
88 static inline void cgm_wsub(cgm_vec4 *a, const cgm_vec4 *b);
89 static inline void cgm_wmul(cgm_vec4 *a, const cgm_vec4 *b);
90 static inline void cgm_wscale(cgm_vec4 *v, float s);
91
92 static inline void cgm_wmul_m4v4(cgm_vec4 *v, const float *m);
93 static inline void cgm_wmul_v4m4(cgm_vec4 *v, const float *m);
94 static inline void cgm_wmul_m34v4(cgm_vec4 *v, const float *m); /* doesn't affect w */
95 static inline void cgm_wmul_v4m43(cgm_vec4 *v, const float *m); /* doesn't affect w */
96 static inline void cgm_wmul_m3v4(cgm_vec4 *v, const float *m); /* (m still 16 floats) */
97 static inline void cgm_wmul_v4m3(cgm_vec4 *v, const float *m); /* (m still 16 floats) */
98
99 static inline float cgm_wlength(const cgm_vec4 *v);
100 static inline float cgm_wlength_sq(const cgm_vec4 *v);
101 static inline float cgm_wdist(const cgm_vec4 *a, const cgm_vec4 *b);
102 static inline float cgm_wdist_sq(const cgm_vec4 *a, const cgm_vec4 *b);
103 static inline void cgm_wnormalize(cgm_vec4 *v);
104
105 static inline void cgm_wlerp(cgm_vec4 *res, const cgm_vec4 *a, const cgm_vec4 *b, float t);
106
107 /* --- operations on quaternions --- */
108 static inline void cgm_qcons(cgm_quat *q, float x, float y, float z, float w);
109
110 static inline void cgm_qneg(cgm_quat *q);
111 static inline void cgm_qadd(cgm_quat *a, const cgm_quat *b);
112 static inline void cgm_qsub(cgm_quat *a, const cgm_quat *b);
113 static inline void cgm_qmul(cgm_quat *a, const cgm_quat *b);
114
115 static inline float cgm_qlength(const cgm_quat *q);
116 static inline float cgm_qlength_sq(const cgm_quat *q);
117 static inline void cgm_qnormalize(cgm_quat *q);
118 static inline void cgm_qconjugate(cgm_quat *q);
119 static inline void cgm_qinvert(cgm_quat *q);
120
121 static inline void cgm_qrotation(cgm_quat *q, const cgm_vec3 *axis, float angle);
122 static inline void cgm_qrotate(cgm_quat *q, const cgm_vec3 *axis, float angle);
123
124 static inline void cgm_qslerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t);
125 static inline void cgm_qlerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t);
126
127 /* --- operations on matrices --- */
128 static inline void cgm_mcopy(float *dest, const float *src);
129 static inline void cgm_mzero(float *m);
130 static inline void cgm_midentity(float *m);
131
132 static inline void cgm_msetrow_v3(float *m, int idx, const cgm_vec3 *v);
133 static inline void cgm_msetrow_v4(float *m, int idx, const cgm_vec4 *v);
134 static inline void cgm_msetcol_v3(float *m, int idx, const cgm_vec3 *v);
135 static inline void cgm_msetcol_v4(float *m, int idx, const cgm_vec4 *v);
136 static inline void cgm_mgetrow_v3(cgm_vec3 *v, const float *m, int idx);
137 static inline void cgm_mgetrow_v4(cgm_vec4 *v, const float *m, int idx);
138 static inline void cgm_mgetcol_v3(cgm_vec3 *v, const float *m, int idx);
139 static inline void cgm_mgetcol_v4(cgm_vec4 *v, const float *m, int idx);
140
141 static inline void cgm_msubmatrix(float *m, int row, int col);
142 static inline void cgm_mupper3(float *m);
143 static inline float cgm_msubdet(float *m, int row, int col);
144 static inline float cgm_mcofactor(float *m, int row, int col);
145 static inline float cgm_mdet(float *m);
146 static inline void cgm_mtranspose(float *m);
147 static inline void cgm_mcofmatrix(float *m);
148 static inline int cgm_minverse(float *m);       /* returns 0 on success, -1 for singular */
149
150 #include "cgmvec3.inl"
151 #include "cgmvec4.inl"
152 #include "cgmquat.inl"
153 #include "cgmmat.inl"
154
155 #ifdef __cplusplus
156 }
157 #endif
158
159 #endif  /* CGMATH_H_ */