added scr_lvled, a bunch of libraries, and improved framework code
[raydungeon] / libs / cgmath / cgmath.h
1 /* gph-cmath - C graphics 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  * - cgm_r... functions are operations on cgm_ray rays
15  *
16  * NOTE: *ALL* matrix arguments are pointers to 16 floats. Even the functions
17  * which operate on 3x3 matrices, actually use the upper 3x3 of a 4x4 matrix,
18  * and still expect an array of 16 floats.
19  *
20  * NOTE: matrices are treated by all operations as column-major, to match OpenGL
21  * conventions, so everything is pretty much transposed.
22 */
23 #ifndef CGMATH_H_
24 #define CGMATH_H_
25
26 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
27 #define _USE_MATH_DEFINES
28 #endif
29
30 #include <math.h>
31 #include <string.h>
32
33 #ifndef M_PI
34 #define M_PI    3.141592653589793
35 #endif
36
37 typedef struct {
38         float x, y;
39 } cgm_vec2;
40
41 typedef struct {
42         float x, y, z;
43 } cgm_vec3;
44
45 typedef struct {
46         float x, y, z, w;
47 } cgm_vec4, cgm_quat;
48
49 typedef struct {
50         cgm_vec3 origin, dir;
51 } cgm_ray;
52
53 typedef enum cgm_euler_mode {
54         CGM_EULER_XYZ,
55         CGM_EULER_XZY,
56         CGM_EULER_YXZ,
57         CGM_EULER_YZX,
58         CGM_EULER_ZXY,
59         CGM_EULER_ZYX,
60         CGM_EULER_ZXZ,
61         CGM_EULER_ZYZ,
62         CGM_EULER_YXY,
63         CGM_EULER_YZY,
64         CGM_EULER_XYX,
65         CGM_EULER_XZX
66 } cgm_euler_mode;
67
68 #ifdef __cplusplus
69 extern "C" {
70 #else
71
72 #if (__STDC_VERSION__ >= 199901) || defined(__GNUC__)
73 #define CGM_INLINE inline
74 #else
75 #define CGM_INLINE __inline
76 #endif
77
78 #endif
79
80 /* --- operations on cgm_vec3 --- */
81 static CGM_INLINE void cgm_vcons(cgm_vec3 *v, float x, float y, float z);
82 static CGM_INLINE cgm_vec3 cgm_vvec(float x, float y, float z);
83
84 static CGM_INLINE void cgm_vadd(cgm_vec3 *a, const cgm_vec3 *b);
85 static CGM_INLINE void cgm_vadd_scaled(cgm_vec3 *a, const cgm_vec3 *b, float s); /* a+b*s */
86 static CGM_INLINE void cgm_vsub(cgm_vec3 *a, const cgm_vec3 *b);
87 static CGM_INLINE void cgm_vsub_scaled(cgm_vec3 *a, const cgm_vec3 *b, float s); /* a-b*s */
88 static CGM_INLINE void cgm_vmul(cgm_vec3 *a, const cgm_vec3 *b);
89 static CGM_INLINE void cgm_vscale(cgm_vec3 *v, float s);
90 static CGM_INLINE void cgm_vmul_m4v3(cgm_vec3 *v, const float *m);      /* m4x4 * v */
91 static CGM_INLINE void cgm_vmul_v3m4(cgm_vec3 *v, const float *m);      /* v * m4x4 */
92 static CGM_INLINE void cgm_vmul_m3v3(cgm_vec3 *v, const float *m);      /* m3x3 * v (m still 16 floats) */
93 static CGM_INLINE void cgm_vmul_v3m3(cgm_vec3 *v, const float *m);      /* v * m3x3 (m still 16 floats) */
94
95 static CGM_INLINE float cgm_vdot(const cgm_vec3 *a, const cgm_vec3 *b);
96 static CGM_INLINE void cgm_vcross(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b);
97 static CGM_INLINE float cgm_vlength(const cgm_vec3 *v);
98 static CGM_INLINE float cgm_vlength_sq(const cgm_vec3 *v);
99 static CGM_INLINE float cgm_vdist(const cgm_vec3 *a, const cgm_vec3 *b);
100 static CGM_INLINE float cgm_vdist_sq(const cgm_vec3 *a, const cgm_vec3 *b);
101 static CGM_INLINE void cgm_vnormalize(cgm_vec3 *v);
102
103 static CGM_INLINE void cgm_vreflect(cgm_vec3 *v, const cgm_vec3 *n);
104 static CGM_INLINE void cgm_vrefract(cgm_vec3 *v, const cgm_vec3 *n, float ior);
105
106 static CGM_INLINE void cgm_vrotate_quat(cgm_vec3 *v, const cgm_quat *q);
107 static CGM_INLINE void cgm_vrotate_axis(cgm_vec3 *v, int axis, float angle);
108 static CGM_INLINE void cgm_vrotate(cgm_vec3 *v, float angle, float x, float y, float z);
109 static CGM_INLINE void cgm_vrotate_euler(cgm_vec3 *v, float a, float b, float c, enum cgm_euler_mode mode);
110
111 static CGM_INLINE void cgm_vlerp(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b, float t);
112
113 #define cgm_velem(vptr, idx)    ((&(vptr)->x)[idx])
114
115 /* --- operations on cgm_vec4 --- */
116 static CGM_INLINE void cgm_wcons(cgm_vec4 *v, float x, float y, float z, float w);
117 static CGM_INLINE cgm_vec4 cgm_wvec(float x, float y, float z, float w);
118
119 static CGM_INLINE void cgm_wadd(cgm_vec4 *a, const cgm_vec4 *b);
120 static CGM_INLINE void cgm_wsub(cgm_vec4 *a, const cgm_vec4 *b);
121 static CGM_INLINE void cgm_wmul(cgm_vec4 *a, const cgm_vec4 *b);
122 static CGM_INLINE void cgm_wscale(cgm_vec4 *v, float s);
123
124 static CGM_INLINE void cgm_wmul_m4v4(cgm_vec4 *v, const float *m);
125 static CGM_INLINE void cgm_wmul_v4m4(cgm_vec4 *v, const float *m);
126 static CGM_INLINE void cgm_wmul_m34v4(cgm_vec4 *v, const float *m);     /* doesn't affect w */
127 static CGM_INLINE void cgm_wmul_v4m43(cgm_vec4 *v, const float *m);     /* doesn't affect w */
128 static CGM_INLINE void cgm_wmul_m3v4(cgm_vec4 *v, const float *m); /* (m still 16 floats) */
129 static CGM_INLINE void cgm_wmul_v4m3(cgm_vec4 *v, const float *m); /* (m still 16 floats) */
130
131 static CGM_INLINE float cgm_wdot(const cgm_vec4 *a, const cgm_vec4 *b);
132
133 static CGM_INLINE float cgm_wlength(const cgm_vec4 *v);
134 static CGM_INLINE float cgm_wlength_sq(const cgm_vec4 *v);
135 static CGM_INLINE float cgm_wdist(const cgm_vec4 *a, const cgm_vec4 *b);
136 static CGM_INLINE float cgm_wdist_sq(const cgm_vec4 *a, const cgm_vec4 *b);
137 static CGM_INLINE void cgm_wnormalize(cgm_vec4 *v);
138
139 static CGM_INLINE void cgm_wlerp(cgm_vec4 *res, const cgm_vec4 *a, const cgm_vec4 *b, float t);
140
141 #define cgm_welem(vptr, idx)    ((&(vptr)->x)[idx])
142
143 /* --- operations on quaternions --- */
144 static CGM_INLINE void cgm_qcons(cgm_quat *q, float x, float y, float z, float w);
145
146 static CGM_INLINE void cgm_qneg(cgm_quat *q);
147 static CGM_INLINE void cgm_qadd(cgm_quat *a, const cgm_quat *b);
148 static CGM_INLINE void cgm_qsub(cgm_quat *a, const cgm_quat *b);
149 static CGM_INLINE void cgm_qmul(cgm_quat *a, const cgm_quat *b);
150
151 static CGM_INLINE float cgm_qlength(const cgm_quat *q);
152 static CGM_INLINE float cgm_qlength_sq(const cgm_quat *q);
153 static CGM_INLINE void cgm_qnormalize(cgm_quat *q);
154 static CGM_INLINE void cgm_qconjugate(cgm_quat *q);
155 static CGM_INLINE void cgm_qinvert(cgm_quat *q);
156
157 static CGM_INLINE void cgm_qrotation(cgm_quat *q, float angle, float x, float y, float z);
158 static CGM_INLINE void cgm_qrotate(cgm_quat *q, float angle, float x, float y, float z);
159
160 static CGM_INLINE void cgm_qslerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t);
161 static CGM_INLINE void cgm_qlerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t);
162
163 #define cgm_qelem(qptr, idx)    ((&(qptr)->x)[idx])
164
165 /* --- operations on matrices --- */
166 static CGM_INLINE void cgm_mcopy(float *dest, const float *src);
167 static CGM_INLINE void cgm_mzero(float *m);
168 static CGM_INLINE void cgm_midentity(float *m);
169
170 static CGM_INLINE void cgm_mmul(float *a, const float *b);
171 static CGM_INLINE void cgm_mpremul(float *a, const float *b);
172
173 static CGM_INLINE void cgm_msubmatrix(float *m, int row, int col);
174 static CGM_INLINE void cgm_mupper3(float *m);
175 static CGM_INLINE float cgm_msubdet(const float *m, int row, int col);
176 static CGM_INLINE float cgm_mcofactor(const float *m, int row, int col);
177 static CGM_INLINE float cgm_mdet(const float *m);
178 static CGM_INLINE void cgm_mtranspose(float *m);
179 static CGM_INLINE void cgm_mcofmatrix(float *m);
180 static CGM_INLINE int cgm_minverse(float *m);   /* returns 0 on success, -1 for singular */
181
182 static CGM_INLINE void cgm_mtranslation(float *m, float x, float y, float z);
183 static CGM_INLINE void cgm_mscaling(float *m, float sx, float sy, float sz);
184 static CGM_INLINE void cgm_mrotation_x(float *m, float angle);
185 static CGM_INLINE void cgm_mrotation_y(float *m, float angle);
186 static CGM_INLINE void cgm_mrotation_z(float *m, float angle);
187 static CGM_INLINE void cgm_mrotation_axis(float *m, int idx, float angle);
188 static CGM_INLINE void cgm_mrotation(float *m, float angle, float x, float y, float z);
189 static CGM_INLINE void cgm_mrotation_euler(float *m, float a, float b, float c, int mode);
190 static CGM_INLINE void cgm_mrotation_quat(float *m, const cgm_quat *q);
191
192 static CGM_INLINE void cgm_mtranslate(float *m, float x, float y, float z);
193 static CGM_INLINE void cgm_mscale(float *m, float sx, float sy, float sz);
194 static CGM_INLINE void cgm_mrotate_x(float *m, float angle);
195 static CGM_INLINE void cgm_mrotate_y(float *m, float angle);
196 static CGM_INLINE void cgm_mrotate_z(float *m, float angle);
197 static CGM_INLINE void cgm_mrotate_axis(float *m, int idx, float angle);
198 static CGM_INLINE void cgm_mrotate(float *m, float angle, float x, float y, float z);
199 static CGM_INLINE void cgm_mrotate_euler(float *m, float a, float b, float c, int mode);
200 static CGM_INLINE void cgm_mrotate_quat(float *m, const cgm_quat *q);
201
202 static CGM_INLINE void cgm_mpretranslate(float *m, float x, float y, float z);
203 static CGM_INLINE void cgm_mprescale(float *m, float sx, float sy, float sz);
204 static CGM_INLINE void cgm_mprerotate_x(float *m, float angle);
205 static CGM_INLINE void cgm_mprerotate_y(float *m, float angle);
206 static CGM_INLINE void cgm_mprerotate_z(float *m, float angle);
207 static CGM_INLINE void cgm_mprerotate_axis(float *m, int idx, float angle);
208 static CGM_INLINE void cgm_mprerotate(float *m, float angle, float x, float y, float z);
209 static CGM_INLINE void cgm_mprerotate_euler(float *m, float a, float b, float c, int mode);
210 static CGM_INLINE void cgm_mprerotate_quat(float *m, const cgm_quat *q);
211
212 static CGM_INLINE void cgm_mget_translation(const float *m, cgm_vec3 *res);
213 static CGM_INLINE void cgm_mget_rotation(const float *m, cgm_quat *res);
214 static CGM_INLINE void cgm_mget_scaling(const float *m, cgm_vec3 *res);
215 static CGM_INLINE void cgm_mget_frustum_plane(const float *m, int p, cgm_vec4 *res);
216
217 static CGM_INLINE void cgm_normalize_plane(cgm_vec4 *p);
218
219 static CGM_INLINE void cgm_mlookat(float *m, const cgm_vec3 *pos, const cgm_vec3 *targ,
220                 const cgm_vec3 *up);
221 static CGM_INLINE void cgm_minv_lookat(float *m, const cgm_vec3 *pos, const cgm_vec3 *targ,
222                 const cgm_vec3 *up);
223 static CGM_INLINE void cgm_mortho(float *m, float left, float right, float bot, float top,
224                 float znear, float zfar);
225 static CGM_INLINE void cgm_mfrustum(float *m, float left, float right, float bot, float top,
226                 float znear, float zfar);
227 static CGM_INLINE void cgm_mperspective(float *m, float vfov, float aspect, float znear, float zfar);
228
229 static CGM_INLINE void cgm_mmirror(float *m, float a, float b, float c, float d);
230
231 /* --- operations on rays --- */
232 static CGM_INLINE void cgm_rcons(cgm_ray *r, float x, float y, float z, float dx, float dy, float dz);
233
234 static CGM_INLINE void cgm_rmul_mr(cgm_ray *ray, const float *m);       /* m4x4 * ray */
235 static CGM_INLINE void cgm_rmul_rm(cgm_ray *ray, const float *m);       /* ray * m4x4 */
236
237 static CGM_INLINE void cgm_rreflect(cgm_ray *ray, const cgm_vec3 *n);
238 static CGM_INLINE void cgm_rrefract(cgm_ray *ray, const cgm_vec3 *n, float ior);
239
240 /* --- miscellaneous utility functions --- */
241 static CGM_INLINE float cgm_deg_to_rad(float deg);
242 static CGM_INLINE float cgm_rad_to_deg(float rad);
243
244 static CGM_INLINE float cgm_smoothstep(float a, float b, float x);
245 static CGM_INLINE float cgm_lerp(float a, float b, float t);
246 static CGM_INLINE float cgm_logerp(float a, float b, float t);
247 static CGM_INLINE float cgm_bezier(float a, float b, float c, float d, float t);
248 static CGM_INLINE float cgm_bspline(float a, float b, float c, float d, float t);
249 static CGM_INLINE float cgm_spline(float a, float b, float c, float d, float t);
250
251 static CGM_INLINE void cgm_discrand(cgm_vec3 *v, float rad);
252 static CGM_INLINE void cgm_sphrand(cgm_vec3 *v, float rad);
253
254 static CGM_INLINE void cgm_unproject(cgm_vec3 *res, const cgm_vec3 *norm_scrpos,
255                 const float *inv_viewproj);
256 static CGM_INLINE void cgm_glu_unproject(float winx, float winy, float winz,
257                 const float *view, const float *proj, const int *vp,
258                 float *objx, float *objy, float *objz);
259
260 static CGM_INLINE void cgm_pick_ray(cgm_ray *ray, float nx, float ny,
261                 const float *viewmat, const float *projmat);
262
263 static CGM_INLINE void cgm_raypos(cgm_vec3 *p, const cgm_ray *ray, float t);
264
265 /* calculate barycentric coordinates of point pt in triangle (a, b, c) */
266 static CGM_INLINE void cgm_bary(cgm_vec3 *bary, const cgm_vec3 *a,
267                 const cgm_vec3 *b, const cgm_vec3 *c, const cgm_vec3 *pt);
268
269 /* convert between unit vectors and spherical coordinates */
270 static CGM_INLINE void cgm_uvec_to_sph(float *theta, float *phi, const cgm_vec3 *v);
271 static CGM_INLINE void cgm_sph_to_uvec(cgm_vec3 *v, float theta, float phi);
272
273 #include "cgmvec3.inl"
274 #include "cgmvec4.inl"
275 #include "cgmquat.inl"
276 #include "cgmmat.inl"
277 #include "cgmray.inl"
278 #include "cgmmisc.inl"
279
280 #ifdef __cplusplus
281 }
282 #endif
283
284 #endif  /* CGMATH_H_ */