1 /*
2  * Copyright (c), Recep Aslantas.
3  *
4  * MIT License (MIT), http://opensource.org/licenses/MIT
5  * Full license can be found in the LICENSE file
6  */
7 
8 /*
9  Functions:
10    CGLM_INLINE void glm_frustum_lh_no(float left,    float right,
11                                        float bottom,  float top,
12                                        float nearZ, float farZ,
13                                        mat4  dest)
14    CGLM_INLINE void glm_perspective_lh_no(float fovy,
15                                           float aspect,
16                                           float nearZ,
17                                           float farZ,
18                                           mat4  dest)
19    CGLM_INLINE void glm_perspective_default_lh_no(float aspect, mat4 dest)
20    CGLM_INLINE void glm_perspective_resize_lh_no(float aspect, mat4 proj)
21    CGLM_INLINE void glm_persp_move_far_lh_no(mat4 proj,
22                                              float deltaFar)
23    CGLM_INLINE void glm_persp_decomp_lh_no(mat4 proj,
24                                            float * __restrict nearZ,
25                                            float * __restrict farZ,
26                                            float * __restrict top,
27                                            float * __restrict bottom,
28                                            float * __restrict left,
29                                            float * __restrict right)
30   CGLM_INLINE void glm_persp_decompv_lh_no(mat4 proj,
31                                            float dest[6])
32   CGLM_INLINE void glm_persp_decomp_x_lh_no(mat4 proj,
33                                             float * __restrict left,
34                                             float * __restrict right)
35   CGLM_INLINE void glm_persp_decomp_y_lh_no(mat4 proj,
36                                             float * __restrict top,
37                                             float * __restrict bottom)
38   CGLM_INLINE void glm_persp_decomp_z_lh_no(mat4 proj,
39                                             float * __restrict nearZ,
40                                             float * __restrict farZ)
41   CGLM_INLINE void glm_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ)
42   CGLM_INLINE void glm_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ)
43   CGLM_INLINE void glm_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest)
44  */
45 
46 #ifndef cglm_persp_lh_no_h
47 #define cglm_persp_lh_no_h
48 
49 #include "../common.h"
50 #include "persp.h"
51 
52 /*!
53  * @brief set up perspective peprojection matrix
54  *        with a left-hand coordinate system and a
55  *        clip-space of [-1, 1].
56  *
57  * @param[in]  left    viewport.left
58  * @param[in]  right   viewport.right
59  * @param[in]  bottom  viewport.bottom
60  * @param[in]  top     viewport.top
61  * @param[in]  nearZ   near clipping plane
62  * @param[in]  farZ    far clipping plane
63  * @param[out] dest    result matrix
64  */
65 CGLM_INLINE
66 void
glm_frustum_lh_no(float left,float right,float bottom,float top,float nearZ,float farZ,mat4 dest)67 glm_frustum_lh_no(float left,    float right,
68                   float bottom,  float top,
69                   float nearZ, float farZ,
70                   mat4  dest) {
71   float rl, tb, fn, nv;
72 
73   glm_mat4_zero(dest);
74 
75   rl = 1.0f / (right  - left);
76   tb = 1.0f / (top    - bottom);
77   fn =-1.0f / (farZ - nearZ);
78   nv = 2.0f * nearZ;
79 
80   dest[0][0] = nv * rl;
81   dest[1][1] = nv * tb;
82   dest[2][0] = (right  + left)    * rl;
83   dest[2][1] = (top    + bottom)  * tb;
84   dest[2][2] =-(farZ + nearZ) * fn;
85   dest[2][3] = 1.0f;
86   dest[3][2] = farZ * nv * fn;
87 }
88 
89 /*!
90  * @brief set up perspective projection matrix
91  *        with a left-hand coordinate system and a
92  *        clip-space of [-1, 1].
93  *
94  * @param[in]  fovy    field of view angle
95  * @param[in]  aspect  aspect ratio ( width / height )
96  * @param[in]  nearZ   near clipping plane
97  * @param[in]  farZ    far clipping planes
98  * @param[out] dest    result matrix
99  */
100 CGLM_INLINE
101 void
glm_perspective_lh_no(float fovy,float aspect,float nearZ,float farZ,mat4 dest)102 glm_perspective_lh_no(float fovy,
103                       float aspect,
104                       float nearZ,
105                       float farZ,
106                       mat4  dest) {
107   float f, fn;
108 
109   glm_mat4_zero(dest);
110 
111   f  = 1.0f / tanf(fovy * 0.5f);
112   fn = 1.0f / (nearZ - farZ);
113 
114   dest[0][0] = f / aspect;
115   dest[1][1] = f;
116   dest[2][2] =-(nearZ + farZ) * fn;
117   dest[2][3] = 1.0f;
118   dest[3][2] = 2.0f * nearZ * farZ * fn;
119 
120 }
121 
122 /*!
123  * @brief set up perspective projection matrix with default near/far
124  *        and angle values with a left-hand coordinate system and a
125  *        clip-space of [-1, 1].
126  *
127  * @param[in]  aspect aspect ratio ( width / height )
128  * @param[out] dest   result matrix
129  */
130 CGLM_INLINE
131 void
glm_perspective_default_lh_no(float aspect,mat4 dest)132 glm_perspective_default_lh_no(float aspect, mat4 dest) {
133   glm_perspective_lh_no(GLM_PI_4f, aspect, 0.01f, 100.0f, dest);
134 }
135 
136 /*!
137  * @brief resize perspective matrix by aspect ratio ( width / height )
138  *        this makes very easy to resize proj matrix when window /viewport
139  *        resized with a left-hand coordinate system and a
140  *        clip-space of [-1, 1].
141  *
142  * @param[in]      aspect aspect ratio ( width / height )
143  * @param[in, out] proj   perspective projection matrix
144  */
145 CGLM_INLINE
146 void
glm_perspective_resize_lh_no(float aspect,mat4 proj)147 glm_perspective_resize_lh_no(float aspect, mat4 proj) {
148   if (proj[0][0] == 0.0f)
149     return;
150 
151   proj[0][0] = proj[1][1] / aspect;
152 }
153 
154 /*!
155  * @brief extend perspective projection matrix's far distance
156  *        with a left-hand coordinate system and a
157  *        clip-space of [-1, 1].
158  *
159  * this function does not guarantee far >= near, be aware of that!
160  *
161  * @param[in, out] proj      projection matrix to extend
162  * @param[in]      deltaFar  distance from existing far (negative to shink)
163  */
164 CGLM_INLINE
165 void
glm_persp_move_far_lh_no(mat4 proj,float deltaFar)166 glm_persp_move_far_lh_no(mat4 proj, float deltaFar) {
167   float fn, farZ, nearZ, p22, p32;
168 
169   p22        = -proj[2][2];
170   p32        = proj[3][2];
171 
172   nearZ    = p32 / (p22 - 1.0f);
173   farZ     = p32 / (p22 + 1.0f) + deltaFar;
174   fn         = 1.0f / (nearZ - farZ);
175 
176   proj[2][2] = -(farZ + nearZ) * fn;
177   proj[3][2] = 2.0f * nearZ * farZ * fn;
178 }
179 
180 /*!
181  * @brief decomposes frustum values of perspective projection
182  *        with a left-hand coordinate system and a
183  *        clip-space of [-1, 1].
184  *
185  * @param[in]  proj    perspective projection matrix
186  * @param[out] nearZ   near
187  * @param[out] farZ    far
188  * @param[out] top     top
189  * @param[out] bottom  bottom
190  * @param[out] left    left
191  * @param[out] right   right
192  */
193 CGLM_INLINE
194 void
glm_persp_decomp_lh_no(mat4 proj,float * __restrict nearZ,float * __restrict farZ,float * __restrict top,float * __restrict bottom,float * __restrict left,float * __restrict right)195 glm_persp_decomp_lh_no(mat4 proj,
196                        float * __restrict nearZ, float * __restrict farZ,
197                        float * __restrict top,   float * __restrict bottom,
198                        float * __restrict left,  float * __restrict right) {
199   float m00, m11, m20, m21, m22, m32, n, f;
200   float n_m11, n_m00;
201 
202   m00 = proj[0][0];
203   m11 = proj[1][1];
204   m20 = proj[2][0];
205   m21 = proj[2][1];
206   m22 =-proj[2][2];
207   m32 = proj[3][2];
208 
209   n = m32 / (m22 - 1.0f);
210   f = m32 / (m22 + 1.0f);
211 
212   n_m11 = n / m11;
213   n_m00 = n / m00;
214 
215   *nearZ = n;
216   *farZ  = f;
217   *bottom  = n_m11 * (m21 - 1.0f);
218   *top     = n_m11 * (m21 + 1.0f);
219   *left    = n_m00 * (m20 - 1.0f);
220   *right   = n_m00 * (m20 + 1.0f);
221 }
222 
223 /*!
224  * @brief decomposes frustum values of perspective projection
225  *        with a left-hand coordinate system and a
226  *        clip-space of [-1, 1].
227  *        this makes easy to get all values at once
228  *
229  * @param[in]  proj   perspective projection matrix
230  * @param[out] dest   array
231  */
232 CGLM_INLINE
233 void
glm_persp_decompv_lh_no(mat4 proj,float dest[6])234 glm_persp_decompv_lh_no(mat4 proj, float dest[6]) {
235   glm_persp_decomp_lh_no(proj, &dest[0], &dest[1], &dest[2],
236                                &dest[3], &dest[4], &dest[5]);
237 }
238 
239 /*!
240  * @brief decomposes left and right values of perspective projection
241  *        with a left-hand coordinate system and a
242  *        clip-space of [-1, 1].
243  *        x stands for x axis (left / right axis)
244  *
245  * @param[in]  proj  perspective projection matrix
246  * @param[out] left  left
247  * @param[out] right right
248  */
249 CGLM_INLINE
250 void
glm_persp_decomp_x_lh_no(mat4 proj,float * __restrict left,float * __restrict right)251 glm_persp_decomp_x_lh_no(mat4 proj,
252                          float * __restrict left,
253                          float * __restrict right) {
254   float nearZ, m20, m00, m22;
255 
256   m00 = proj[0][0];
257   m20 = proj[2][0];
258   m22 =-proj[2][2];
259 
260   nearZ = proj[3][2] / (m22 - 1.0f);
261   *left   = nearZ * (m20 - 1.0f) / m00;
262   *right  = nearZ * (m20 + 1.0f) / m00;
263 }
264 
265 /*!
266  * @brief decomposes top and bottom values of perspective projection
267  *        with a left-hand coordinate system and a
268  *        clip-space of [-1, 1].
269  *        y stands for y axis (top / botom axis)
270  *
271  * @param[in]  proj   perspective projection matrix
272  * @param[out] top    top
273  * @param[out] bottom bottom
274  */
275 CGLM_INLINE
276 void
glm_persp_decomp_y_lh_no(mat4 proj,float * __restrict top,float * __restrict bottom)277 glm_persp_decomp_y_lh_no(mat4 proj,
278                          float * __restrict top,
279                          float * __restrict bottom) {
280   float nearZ, m21, m11, m22;
281 
282   m21 = proj[2][1];
283   m11 = proj[1][1];
284   m22 =-proj[2][2];
285 
286   nearZ = proj[3][2] / (m22 - 1.0f);
287   *bottom = nearZ * (m21 - 1.0f) / m11;
288   *top    = nearZ * (m21 + 1.0f) / m11;
289 }
290 
291 /*!
292  * @brief decomposes near and far values of perspective projection
293  *        with a left-hand coordinate system and a
294  *        clip-space of [-1, 1].
295  *        z stands for z axis (near / far axis)
296  *
297  * @param[in]  proj    perspective projection matrix
298  * @param[out] nearZ   near
299  * @param[out] farZ    far
300  */
301 CGLM_INLINE
302 void
glm_persp_decomp_z_lh_no(mat4 proj,float * __restrict nearZ,float * __restrict farZ)303 glm_persp_decomp_z_lh_no(mat4 proj,
304                          float * __restrict nearZ,
305                          float * __restrict farZ) {
306   float m32, m22;
307 
308   m32 = proj[3][2];
309   m22 =-proj[2][2];
310 
311   *nearZ = m32 / (m22 - 1.0f);
312   *farZ  = m32 / (m22 + 1.0f);
313 }
314 
315 /*!
316  * @brief decomposes far value of perspective projection
317  *        with a left-hand coordinate system and a
318  *        clip-space of [-1, 1].
319  *
320  * @param[in]  proj   perspective projection matrix
321  * @param[out] farZ   far
322  */
323 CGLM_INLINE
324 void
glm_persp_decomp_far_lh_no(mat4 proj,float * __restrict farZ)325 glm_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ) {
326   *farZ = proj[3][2] / (-proj[2][2] + 1.0f);
327 }
328 
329 /*!
330  * @brief decomposes near value of perspective projection
331  *        with a left-hand coordinate system and a
332  *        clip-space of [-1, 1].
333  *
334  * @param[in]  proj    perspective projection matrix
335  * @param[out] nearZ   near
336  */
337 CGLM_INLINE
338 void
glm_persp_decomp_near_lh_no(mat4 proj,float * __restrict nearZ)339 glm_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ) {
340   *nearZ = proj[3][2] / (-proj[2][2] - 1.0f);
341 }
342 
343 /*!
344  * @brief returns sizes of near and far planes of perspective projection
345  *        with a left-hand coordinate system and a
346  *        clip-space of [-1, 1].
347  *
348  * @param[in]  proj perspective projection matrix
349  * @param[in]  fovy fovy (see brief)
350  * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar]
351  */
352 CGLM_INLINE
353 void
glm_persp_sizes_lh_no(mat4 proj,float fovy,vec4 dest)354 glm_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest) {
355   float t, a, nearZ, farZ;
356 
357   t = 2.0f * tanf(fovy * 0.5f);
358   a = glm_persp_aspect(proj);
359 
360   glm_persp_decomp_z_lh_no(proj, &nearZ, &farZ);
361 
362   dest[1]  = t * nearZ;
363   dest[3]  = t * farZ;
364   dest[0]  = a * dest[1];
365   dest[2]  = a * dest[3];
366 }
367 
368 /*!
369  * @brief returns field of view angle along the Y-axis (in radians)
370  *        with a left-hand coordinate system and a clip-space of [-1, 1].
371  *
372  * if you need to degrees, use glm_deg to convert it or use this:
373  * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
374  *
375  * @param[in] proj perspective projection matrix
376  */
377 CGLM_INLINE
378 float
glm_persp_fovy_lh_no(mat4 proj)379 glm_persp_fovy_lh_no(mat4 proj) {
380   return glm_persp_fovy(proj);
381 }
382 
383 /*!
384  * @brief returns aspect ratio of perspective projection
385  *        with a left-hand coordinate system and a clip-space of [-1, 1].
386  *
387  * @param[in] proj perspective projection matrix
388  */
389 CGLM_INLINE
390 float
glm_persp_aspect_lh_no(mat4 proj)391 glm_persp_aspect_lh_no(mat4 proj) {
392   return glm_persp_aspect(proj);
393 }
394 
395 #endif /*cglm_cam_lh_no_h*/
396