git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / include / gfx / math / matrix_4x4.h
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (matrix_4x4.h).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #ifndef __LIBRETRO_SDK_GFX_MATH_MATRIX_4X4_H__
24 #define __LIBRETRO_SDK_GFX_MATH_MATRIX_4X4_H__
25
26 #include <retro_common_api.h>
27
28 #include <math.h>
29 #include <gfx/math/vector_3.h>
30
31 /* Column-major matrix (OpenGL-style).
32  * Reimplements functionality from FF OpenGL pipeline to be able
33  * to work on GLES 2.0 and modern GL variants.
34  */
35
36 #define MAT_ELEM_4X4(mat, row, column) ((mat).data[4 * (column) + (row)])
37
38 RETRO_BEGIN_DECLS
39
40 typedef struct math_matrix_4x4
41 {
42    float data[16];
43 } math_matrix_4x4;
44
45 #define matrix_4x4_copy(dst, src) \
46    MAT_ELEM_4X4(dst, 0, 0) = MAT_ELEM_4X4(src, 0, 0); \
47    MAT_ELEM_4X4(dst, 0, 1) = MAT_ELEM_4X4(src, 0, 1); \
48    MAT_ELEM_4X4(dst, 0, 2) = MAT_ELEM_4X4(src, 0, 2); \
49    MAT_ELEM_4X4(dst, 0, 3) = MAT_ELEM_4X4(src, 0, 3); \
50    MAT_ELEM_4X4(dst, 1, 0) = MAT_ELEM_4X4(src, 1, 0); \
51    MAT_ELEM_4X4(dst, 1, 1) = MAT_ELEM_4X4(src, 1, 1); \
52    MAT_ELEM_4X4(dst, 1, 2) = MAT_ELEM_4X4(src, 1, 2); \
53    MAT_ELEM_4X4(dst, 1, 3) = MAT_ELEM_4X4(src, 1, 3); \
54    MAT_ELEM_4X4(dst, 2, 0) = MAT_ELEM_4X4(src, 2, 0); \
55    MAT_ELEM_4X4(dst, 2, 1) = MAT_ELEM_4X4(src, 2, 1); \
56    MAT_ELEM_4X4(dst, 2, 2) = MAT_ELEM_4X4(src, 2, 2); \
57    MAT_ELEM_4X4(dst, 2, 3) = MAT_ELEM_4X4(src, 2, 3); \
58    MAT_ELEM_4X4(dst, 3, 0) = MAT_ELEM_4X4(src, 3, 0); \
59    MAT_ELEM_4X4(dst, 3, 1) = MAT_ELEM_4X4(src, 3, 1); \
60    MAT_ELEM_4X4(dst, 3, 2) = MAT_ELEM_4X4(src, 3, 2); \
61    MAT_ELEM_4X4(dst, 3, 3) = MAT_ELEM_4X4(src, 3, 3)
62
63 /*
64  * Sets mat to an identity matrix
65  */
66 #define matrix_4x4_identity(mat) \
67    MAT_ELEM_4X4(mat, 0, 0)    = 1.0f; \
68    MAT_ELEM_4X4(mat, 0, 1)    = 0.0f; \
69    MAT_ELEM_4X4(mat, 0, 2)    = 0.0f; \
70    MAT_ELEM_4X4(mat, 0, 3)    = 0.0f; \
71    MAT_ELEM_4X4(mat, 1, 0)    = 0.0f; \
72    MAT_ELEM_4X4(mat, 1, 1)    = 1.0f; \
73    MAT_ELEM_4X4(mat, 1, 2)    = 0.0f; \
74    MAT_ELEM_4X4(mat, 1, 3)    = 0.0f; \
75    MAT_ELEM_4X4(mat, 2, 0)    = 0.0f; \
76    MAT_ELEM_4X4(mat, 2, 1)    = 0.0f; \
77    MAT_ELEM_4X4(mat, 2, 2)    = 1.0f; \
78    MAT_ELEM_4X4(mat, 2, 3)    = 0.0f; \
79    MAT_ELEM_4X4(mat, 3, 0)    = 0.0f; \
80    MAT_ELEM_4X4(mat, 3, 1)    = 0.0f; \
81    MAT_ELEM_4X4(mat, 3, 2)    = 0.0f; \
82    MAT_ELEM_4X4(mat, 3, 3)    = 1.0f
83
84 /*
85  * Sets out to the transposed matrix of in
86  */
87
88 #define matrix_4x4_transpose(out, in) \
89    MAT_ELEM_4X4(out, 0, 0) = MAT_ELEM_4X4(in, 0, 0); \
90    MAT_ELEM_4X4(out, 1, 0) = MAT_ELEM_4X4(in, 0, 1); \
91    MAT_ELEM_4X4(out, 2, 0) = MAT_ELEM_4X4(in, 0, 2); \
92    MAT_ELEM_4X4(out, 3, 0) = MAT_ELEM_4X4(in, 0, 3); \
93    MAT_ELEM_4X4(out, 0, 1) = MAT_ELEM_4X4(in, 1, 0); \
94    MAT_ELEM_4X4(out, 1, 1) = MAT_ELEM_4X4(in, 1, 1); \
95    MAT_ELEM_4X4(out, 2, 1) = MAT_ELEM_4X4(in, 1, 2); \
96    MAT_ELEM_4X4(out, 3, 1) = MAT_ELEM_4X4(in, 1, 3); \
97    MAT_ELEM_4X4(out, 0, 2) = MAT_ELEM_4X4(in, 2, 0); \
98    MAT_ELEM_4X4(out, 1, 2) = MAT_ELEM_4X4(in, 2, 1); \
99    MAT_ELEM_4X4(out, 2, 2) = MAT_ELEM_4X4(in, 2, 2); \
100    MAT_ELEM_4X4(out, 3, 2) = MAT_ELEM_4X4(in, 2, 3); \
101    MAT_ELEM_4X4(out, 0, 3) = MAT_ELEM_4X4(in, 3, 0); \
102    MAT_ELEM_4X4(out, 1, 3) = MAT_ELEM_4X4(in, 3, 1); \
103    MAT_ELEM_4X4(out, 2, 3) = MAT_ELEM_4X4(in, 3, 2); \
104    MAT_ELEM_4X4(out, 3, 3) = MAT_ELEM_4X4(in, 3, 3)
105
106 /*
107  * Builds an X-axis rotation matrix
108  */
109 #define matrix_4x4_rotate_x(mat, radians) \
110 { \
111    float cosine            = cosf(radians); \
112    float sine              = sinf(radians); \
113    MAT_ELEM_4X4(mat, 0, 0) = 1.0f; \
114    MAT_ELEM_4X4(mat, 0, 1) = 0.0f; \
115    MAT_ELEM_4X4(mat, 0, 2) = 0.0f; \
116    MAT_ELEM_4X4(mat, 0, 3) = 0.0f; \
117    MAT_ELEM_4X4(mat, 1, 0) = 0.0f; \
118    MAT_ELEM_4X4(mat, 1, 1) = cosine; \
119    MAT_ELEM_4X4(mat, 1, 2) = -sine; \
120    MAT_ELEM_4X4(mat, 1, 3) = 0.0f; \
121    MAT_ELEM_4X4(mat, 2, 0) = 0.0f; \
122    MAT_ELEM_4X4(mat, 2, 1) = sine; \
123    MAT_ELEM_4X4(mat, 2, 2) = cosine; \
124    MAT_ELEM_4X4(mat, 2, 3) = 0.0f; \
125    MAT_ELEM_4X4(mat, 3, 0) = 0.0f; \
126    MAT_ELEM_4X4(mat, 3, 1) = 0.0f; \
127    MAT_ELEM_4X4(mat, 3, 2) = 0.0f; \
128    MAT_ELEM_4X4(mat, 3, 3) = 1.0f; \
129 }
130
131 /*
132  * Builds a rotation matrix using the
133  * rotation around the Y-axis.
134  */
135
136 #define matrix_4x4_rotate_y(mat, radians) \
137 { \
138    float cosine            = cosf(radians); \
139    float sine              = sinf(radians); \
140    MAT_ELEM_4X4(mat, 0, 0) = cosine; \
141    MAT_ELEM_4X4(mat, 0, 1) = 0.0f; \
142    MAT_ELEM_4X4(mat, 0, 2) = -sine; \
143    MAT_ELEM_4X4(mat, 0, 3) = 0.0f; \
144    MAT_ELEM_4X4(mat, 1, 0) = 0.0f; \
145    MAT_ELEM_4X4(mat, 1, 1) = 1.0f; \
146    MAT_ELEM_4X4(mat, 1, 2) = 0.0f; \
147    MAT_ELEM_4X4(mat, 1, 3) = 0.0f; \
148    MAT_ELEM_4X4(mat, 2, 0) = sine; \
149    MAT_ELEM_4X4(mat, 2, 1) = 0.0f; \
150    MAT_ELEM_4X4(mat, 2, 2) = cosine; \
151    MAT_ELEM_4X4(mat, 2, 3) = 0.0f; \
152    MAT_ELEM_4X4(mat, 3, 0) = 0.0f; \
153    MAT_ELEM_4X4(mat, 3, 1) = 0.0f; \
154    MAT_ELEM_4X4(mat, 3, 2) = 0.0f; \
155    MAT_ELEM_4X4(mat, 3, 3) = 1.0f; \
156 }
157
158 /*
159  * Builds a rotation matrix using the
160  * rotation around the Z-axis.
161  */
162 #define matrix_4x4_rotate_z(mat, radians) \
163 { \
164    float cosine            = cosf(radians); \
165    float sine              = sinf(radians); \
166    MAT_ELEM_4X4(mat, 0, 0) = cosine; \
167    MAT_ELEM_4X4(mat, 0, 1) = -sine; \
168    MAT_ELEM_4X4(mat, 0, 2) = 0.0f; \
169    MAT_ELEM_4X4(mat, 0, 3) = 0.0f; \
170    MAT_ELEM_4X4(mat, 1, 0) = sine; \
171    MAT_ELEM_4X4(mat, 1, 1) = cosine; \
172    MAT_ELEM_4X4(mat, 1, 2) = 0.0f; \
173    MAT_ELEM_4X4(mat, 1, 3) = 0.0f; \
174    MAT_ELEM_4X4(mat, 2, 0) = 0.0f; \
175    MAT_ELEM_4X4(mat, 2, 1) = 0.0f; \
176    MAT_ELEM_4X4(mat, 2, 2) = 1.0f; \
177    MAT_ELEM_4X4(mat, 2, 3) = 0.0f; \
178    MAT_ELEM_4X4(mat, 3, 0) = 0.0f; \
179    MAT_ELEM_4X4(mat, 3, 1) = 0.0f; \
180    MAT_ELEM_4X4(mat, 3, 2) = 0.0f; \
181    MAT_ELEM_4X4(mat, 3, 3) = 1.0f; \
182 }
183
184 /*
185  * Creates an orthographic projection matrix.
186  */
187 #define matrix_4x4_ortho(mat, left, right, bottom, top, znear, zfar) \
188 { \
189    float rl                = (right) - (left); \
190    float tb                = (top)   - (bottom); \
191    float fn                = (zfar)  - (znear); \
192    MAT_ELEM_4X4(mat, 0, 0) =  2.0f / rl; \
193    MAT_ELEM_4X4(mat, 0, 1) =  0.0f; \
194    MAT_ELEM_4X4(mat, 0, 2) =  0.0f; \
195    MAT_ELEM_4X4(mat, 0, 3) = -((left) + (right))  / rl; \
196    MAT_ELEM_4X4(mat, 1, 0) =  0.0f; \
197    MAT_ELEM_4X4(mat, 1, 1) =  2.0f / tb; \
198    MAT_ELEM_4X4(mat, 1, 2) =  0.0f; \
199    MAT_ELEM_4X4(mat, 1, 3) = -((top)  + (bottom)) / tb; \
200    MAT_ELEM_4X4(mat, 2, 0) =  0.0f; \
201    MAT_ELEM_4X4(mat, 2, 1) =  0.0f; \
202    MAT_ELEM_4X4(mat, 2, 2) = -2.0f / fn; \
203    MAT_ELEM_4X4(mat, 2, 3) = -((zfar) + (znear))  / fn; \
204    MAT_ELEM_4X4(mat, 3, 0) =  0.0f; \
205    MAT_ELEM_4X4(mat, 3, 1) =  0.0f; \
206    MAT_ELEM_4X4(mat, 3, 2) =  0.0f; \
207    MAT_ELEM_4X4(mat, 3, 3) =  1.0f; \
208 }
209
210 #define matrix_4x4_lookat(out, eye, center, up) \
211 { \
212    vec3_t zaxis;   /* the "forward" vector */ \
213    vec3_t xaxis;   /* the "right"   vector */ \
214    vec3_t yaxis;   /* the "up"      vector */ \
215    vec3_copy(zaxis, center); \
216    vec3_subtract(zaxis, eye); \
217    vec3_normalize(zaxis); \
218    vec3_cross(xaxis, zaxis, up); \
219    vec3_normalize(xaxis); \
220    vec3_cross(yaxis, xaxis, zaxis); \
221    MAT_ELEM_4X4(out, 0, 0) = xaxis[0]; \
222    MAT_ELEM_4X4(out, 0, 1) = yaxis[0]; \
223    MAT_ELEM_4X4(out, 0, 2) = -zaxis[0]; \
224    MAT_ELEM_4X4(out, 0, 3) = 0.0; \
225    MAT_ELEM_4X4(out, 1, 0) = xaxis[1]; \
226    MAT_ELEM_4X4(out, 1, 1) = yaxis[1]; \
227    MAT_ELEM_4X4(out, 1, 2) = -zaxis[1]; \
228    MAT_ELEM_4X4(out, 1, 3) = 0.0f; \
229    MAT_ELEM_4X4(out, 2, 0) = xaxis[2]; \
230    MAT_ELEM_4X4(out, 2, 1) = yaxis[2]; \
231    MAT_ELEM_4X4(out, 2, 2) = -zaxis[2]; \
232    MAT_ELEM_4X4(out, 2, 3) = 0.0f; \
233    MAT_ELEM_4X4(out, 3, 0) = -(xaxis[0] * eye[0] + xaxis[1] * eye[1] + xaxis[2] * eye[2]); \
234    MAT_ELEM_4X4(out, 3, 1) = -(yaxis[0] * eye[0] + yaxis[1] * eye[1] + yaxis[2] * eye[2]); \
235    MAT_ELEM_4X4(out, 3, 2) = (zaxis[0] * eye[0] + zaxis[1] * eye[1] + zaxis[2] * eye[2]); \
236    MAT_ELEM_4X4(out, 3, 3) = 1.f; \
237 }
238
239 /*
240  * Multiplies a with b, stores the result in out
241  */
242
243 #define matrix_4x4_multiply(out, a, b) \
244    MAT_ELEM_4X4(out, 0, 0) =  \
245       MAT_ELEM_4X4(a, 0, 0) * MAT_ELEM_4X4(b, 0, 0) + \
246       MAT_ELEM_4X4(a, 0, 1) * MAT_ELEM_4X4(b, 1, 0) + \
247       MAT_ELEM_4X4(a, 0, 2) * MAT_ELEM_4X4(b, 2, 0) + \
248       MAT_ELEM_4X4(a, 0, 3) * MAT_ELEM_4X4(b, 3, 0); \
249    MAT_ELEM_4X4(out, 0, 1) =  \
250       MAT_ELEM_4X4(a, 0, 0) * MAT_ELEM_4X4(b, 0, 1) + \
251       MAT_ELEM_4X4(a, 0, 1) * MAT_ELEM_4X4(b, 1, 1) + \
252       MAT_ELEM_4X4(a, 0, 2) * MAT_ELEM_4X4(b, 2, 1) + \
253       MAT_ELEM_4X4(a, 0, 3) * MAT_ELEM_4X4(b, 3, 1); \
254    MAT_ELEM_4X4(out, 0, 2) =  \
255       MAT_ELEM_4X4(a, 0, 0) * MAT_ELEM_4X4(b, 0, 2) + \
256       MAT_ELEM_4X4(a, 0, 1) * MAT_ELEM_4X4(b, 1, 2) + \
257       MAT_ELEM_4X4(a, 0, 2) * MAT_ELEM_4X4(b, 2, 2) + \
258       MAT_ELEM_4X4(a, 0, 3) * MAT_ELEM_4X4(b, 3, 2); \
259    MAT_ELEM_4X4(out, 0, 3) =  \
260       MAT_ELEM_4X4(a, 0, 0) * MAT_ELEM_4X4(b, 0, 3) + \
261       MAT_ELEM_4X4(a, 0, 1) * MAT_ELEM_4X4(b, 1, 3) + \
262       MAT_ELEM_4X4(a, 0, 2) * MAT_ELEM_4X4(b, 2, 3) + \
263       MAT_ELEM_4X4(a, 0, 3) * MAT_ELEM_4X4(b, 3, 3); \
264    MAT_ELEM_4X4(out, 1, 0) =  \
265       MAT_ELEM_4X4(a, 1, 0) * MAT_ELEM_4X4(b, 0, 0) + \
266       MAT_ELEM_4X4(a, 1, 1) * MAT_ELEM_4X4(b, 1, 0) + \
267       MAT_ELEM_4X4(a, 1, 2) * MAT_ELEM_4X4(b, 2, 0) + \
268       MAT_ELEM_4X4(a, 1, 3) * MAT_ELEM_4X4(b, 3, 0); \
269    MAT_ELEM_4X4(out, 1, 1) =  \
270       MAT_ELEM_4X4(a, 1, 0) * MAT_ELEM_4X4(b, 0, 1) + \
271       MAT_ELEM_4X4(a, 1, 1) * MAT_ELEM_4X4(b, 1, 1) + \
272       MAT_ELEM_4X4(a, 1, 2) * MAT_ELEM_4X4(b, 2, 1) + \
273       MAT_ELEM_4X4(a, 1, 3) * MAT_ELEM_4X4(b, 3, 1); \
274    MAT_ELEM_4X4(out, 1, 2) =  \
275       MAT_ELEM_4X4(a, 1, 0) * MAT_ELEM_4X4(b, 0, 2) + \
276       MAT_ELEM_4X4(a, 1, 1) * MAT_ELEM_4X4(b, 1, 2) + \
277       MAT_ELEM_4X4(a, 1, 2) * MAT_ELEM_4X4(b, 2, 2) + \
278       MAT_ELEM_4X4(a, 1, 3) * MAT_ELEM_4X4(b, 3, 2); \
279    MAT_ELEM_4X4(out, 1, 3) =  \
280       MAT_ELEM_4X4(a, 1, 0) * MAT_ELEM_4X4(b, 0, 3) + \
281       MAT_ELEM_4X4(a, 1, 1) * MAT_ELEM_4X4(b, 1, 3) + \
282       MAT_ELEM_4X4(a, 1, 2) * MAT_ELEM_4X4(b, 2, 3) + \
283       MAT_ELEM_4X4(a, 1, 3) * MAT_ELEM_4X4(b, 3, 3); \
284    MAT_ELEM_4X4(out, 2, 0) =  \
285       MAT_ELEM_4X4(a, 2, 0) * MAT_ELEM_4X4(b, 0, 0) + \
286       MAT_ELEM_4X4(a, 2, 1) * MAT_ELEM_4X4(b, 1, 0) + \
287       MAT_ELEM_4X4(a, 2, 2) * MAT_ELEM_4X4(b, 2, 0) + \
288       MAT_ELEM_4X4(a, 2, 3) * MAT_ELEM_4X4(b, 3, 0); \
289    MAT_ELEM_4X4(out, 2, 1) =  \
290       MAT_ELEM_4X4(a, 2, 0) * MAT_ELEM_4X4(b, 0, 1) + \
291       MAT_ELEM_4X4(a, 2, 1) * MAT_ELEM_4X4(b, 1, 1) + \
292       MAT_ELEM_4X4(a, 2, 2) * MAT_ELEM_4X4(b, 2, 1) + \
293       MAT_ELEM_4X4(a, 2, 3) * MAT_ELEM_4X4(b, 3, 1); \
294    MAT_ELEM_4X4(out, 2, 2) =  \
295       MAT_ELEM_4X4(a, 2, 0) * MAT_ELEM_4X4(b, 0, 2) + \
296       MAT_ELEM_4X4(a, 2, 1) * MAT_ELEM_4X4(b, 1, 2) + \
297       MAT_ELEM_4X4(a, 2, 2) * MAT_ELEM_4X4(b, 2, 2) + \
298       MAT_ELEM_4X4(a, 2, 3) * MAT_ELEM_4X4(b, 3, 2); \
299    MAT_ELEM_4X4(out, 2, 3) =  \
300       MAT_ELEM_4X4(a, 2, 0) * MAT_ELEM_4X4(b, 0, 3) + \
301       MAT_ELEM_4X4(a, 2, 1) * MAT_ELEM_4X4(b, 1, 3) + \
302       MAT_ELEM_4X4(a, 2, 2) * MAT_ELEM_4X4(b, 2, 3) + \
303       MAT_ELEM_4X4(a, 2, 3) * MAT_ELEM_4X4(b, 3, 3); \
304    MAT_ELEM_4X4(out, 3, 0) =  \
305       MAT_ELEM_4X4(a, 3, 0) * MAT_ELEM_4X4(b, 0, 0) + \
306       MAT_ELEM_4X4(a, 3, 1) * MAT_ELEM_4X4(b, 1, 0) + \
307       MAT_ELEM_4X4(a, 3, 2) * MAT_ELEM_4X4(b, 2, 0) + \
308       MAT_ELEM_4X4(a, 3, 3) * MAT_ELEM_4X4(b, 3, 0); \
309    MAT_ELEM_4X4(out, 3, 1) =  \
310       MAT_ELEM_4X4(a, 3, 0) * MAT_ELEM_4X4(b, 0, 1) + \
311       MAT_ELEM_4X4(a, 3, 1) * MAT_ELEM_4X4(b, 1, 1) + \
312       MAT_ELEM_4X4(a, 3, 2) * MAT_ELEM_4X4(b, 2, 1) + \
313       MAT_ELEM_4X4(a, 3, 3) * MAT_ELEM_4X4(b, 3, 1); \
314    MAT_ELEM_4X4(out, 3, 2) = \
315       MAT_ELEM_4X4(a, 3, 0) * MAT_ELEM_4X4(b, 0, 2) + \
316       MAT_ELEM_4X4(a, 3, 1) * MAT_ELEM_4X4(b, 1, 2) + \
317       MAT_ELEM_4X4(a, 3, 2) * MAT_ELEM_4X4(b, 2, 2) + \
318       MAT_ELEM_4X4(a, 3, 3) * MAT_ELEM_4X4(b, 3, 2); \
319    MAT_ELEM_4X4(out, 3, 3) =  \
320       MAT_ELEM_4X4(a, 3, 0) * MAT_ELEM_4X4(b, 0, 3) + \
321       MAT_ELEM_4X4(a, 3, 1) * MAT_ELEM_4X4(b, 1, 3) + \
322       MAT_ELEM_4X4(a, 3, 2) * MAT_ELEM_4X4(b, 2, 3) + \
323       MAT_ELEM_4X4(a, 3, 3) * MAT_ELEM_4X4(b, 3, 3)
324
325 #define matrix_4x4_scale(mat, x, y, z) \
326    MAT_ELEM_4X4(mat, 0, 0) = x; \
327    MAT_ELEM_4X4(mat, 0, 1) = 0.0f; \
328    MAT_ELEM_4X4(mat, 0, 2) = 0.0f; \
329    MAT_ELEM_4X4(mat, 0, 3) = 0.0f; \
330    MAT_ELEM_4X4(mat, 1, 0) = 0.0f; \
331    MAT_ELEM_4X4(mat, 1, 1) = y; \
332    MAT_ELEM_4X4(mat, 1, 2) = 0.0f; \
333    MAT_ELEM_4X4(mat, 1, 3) = 0.0f; \
334    MAT_ELEM_4X4(mat, 2, 0) = 0.0f; \
335    MAT_ELEM_4X4(mat, 2, 1) = 0.0f; \
336    MAT_ELEM_4X4(mat, 2, 2) = z; \
337    MAT_ELEM_4X4(mat, 2, 3) = 0.0f; \
338    MAT_ELEM_4X4(mat, 3, 0) = 0.0f; \
339    MAT_ELEM_4X4(mat, 3, 1) = 0.0f; \
340    MAT_ELEM_4X4(mat, 3, 2) = 0.0f; \
341    MAT_ELEM_4X4(mat, 3, 3) = 1.0f
342
343 /*
344  * Builds a translation matrix. All other elements in
345  * the matrix will be set to zero except for the
346  * diagonal which is set to 1.0
347  */
348
349 #define matrix_4x4_translate(mat, x, y, z) \
350    MAT_ELEM_4X4(mat, 0, 0) = 1.0f; \
351    MAT_ELEM_4X4(mat, 0, 1) = 0.0f; \
352    MAT_ELEM_4X4(mat, 0, 2) = 0.0f; \
353    MAT_ELEM_4X4(mat, 0, 3) = x; \
354    MAT_ELEM_4X4(mat, 1, 0) = 0.0f; \
355    MAT_ELEM_4X4(mat, 1, 1) = 1.0f; \
356    MAT_ELEM_4X4(mat, 1, 2) = 1.0f; \
357    MAT_ELEM_4X4(mat, 1, 3) = y; \
358    MAT_ELEM_4X4(mat, 2, 0) = 0.0f; \
359    MAT_ELEM_4X4(mat, 2, 1) = 0.0f; \
360    MAT_ELEM_4X4(mat, 2, 2) = 1.0f; \
361    MAT_ELEM_4X4(mat, 2, 3) = z; \
362    MAT_ELEM_4X4(mat, 3, 0) = 0.0f; \
363    MAT_ELEM_4X4(mat, 3, 1) = 0.0f; \
364    MAT_ELEM_4X4(mat, 3, 2) = 0.0f; \
365    MAT_ELEM_4X4(mat, 3, 3) = 1.0f
366
367 /*
368  * Creates a perspective projection matrix.
369  */
370
371 #define  matrix_4x4_projection(mat, y_fov, aspect, znear, zfar) \
372 { \
373    float const a           = 1.f / tan((y_fov) / 2.f); \
374    float delta_z           = (zfar) - (znear); \
375    MAT_ELEM_4X4(mat, 0, 0) = a / (aspect); \
376    MAT_ELEM_4X4(mat, 0, 1) = 0.0f; \
377    MAT_ELEM_4X4(mat, 0, 2) = 0.0f; \
378    MAT_ELEM_4X4(mat, 0, 3) = 0.0f; \
379    MAT_ELEM_4X4(mat, 1, 0) = 0.0f; \
380    MAT_ELEM_4X4(mat, 1, 1) = a; \
381    MAT_ELEM_4X4(mat, 1, 2) = 0.0f; \
382    MAT_ELEM_4X4(mat, 1, 3) = 0.0f; \
383    MAT_ELEM_4X4(mat, 2, 0) = 0.0f; \
384    MAT_ELEM_4X4(mat, 2, 1) = 0.0f; \
385    MAT_ELEM_4X4(mat, 2, 2) = -(((zfar) + (znear)) / delta_z); \
386    MAT_ELEM_4X4(mat, 2, 3) = -1.f; \
387    MAT_ELEM_4X4(mat, 3, 0) = 0.0f; \
388    MAT_ELEM_4X4(mat, 3, 1) = 0.0f; \
389    MAT_ELEM_4X4(mat, 3, 2) = -((2.f * (zfar) * (znear)) / delta_z); \
390    MAT_ELEM_4X4(mat, 3, 3) = 0.0f; \
391 }
392
393 RETRO_END_DECLS
394
395 #endif