Antkeeper  0.0.1
math/projection.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_MATH_PROJECTION_HPP
21 #define ANTKEEPER_MATH_PROJECTION_HPP
22 
23 #include <engine/math/matrix.hpp>
24 #include <cmath>
25 #include <tuple>
26 
27 namespace math {
28 
39 template <class T>
40 [[nodiscard]] T horizontal_fov(T v, T r)
41 {
42  return T{2} * std::atan(std::tan(v * T{0.5}) * r);
43 }
44 
55 template <class T>
56 [[nodiscard]] T vertical_fov(T h, T r)
57 {
58  return T{2} * std::atan(std::tan(h * T{0.5}) / r);
59 }
60 
73 template <class T>
74 [[nodiscard]] constexpr mat4<T> ortho(T left, T right, T bottom, T top, T near, T far) noexcept
75 {
76  return
77  {{
78  {T{2} / (right - left), T{0}, T{0}, T{0}},
79  {T{0}, T{2} / (top - bottom), T{0}, T{0}},
80  {T{0}, T{0}, T{-2} / (far - near), T{0}},
81  {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((far + near) / (far - near)), T{1}}
82  }};
83 }
84 
99 template <class T>
100 [[nodiscard]] constexpr std::tuple<mat4<T>, mat4<T>> ortho_inv(T left, T right, T bottom, T top, T near, T far) noexcept
101 {
102  return
103  {
104  mat4<T>
105  {{
106  {T{2} / (right - left), T{0}, T{0}, T{0}},
107  {T{0}, T{2} / (top - bottom), T{0}, T{0}},
108  {T{0}, T{0}, T{-2} / (far - near), T{0}},
109  {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((far + near) / (far - near)), T{1}}
110  }},
111 
112  mat4<T>
113  {{
114  {(right - left) / T{2}, T{0}, T{0}, T{0}},
115  {T{0}, (top - bottom) / T{2}, T{0}, T{0}},
116  {T{0}, T{0}, (-far + near) / T{2}, T{0}},
117  {(right + left) / T{2}, (bottom + top) / T{2}, (-far - near) / T{2}, T{1}}
118  }}
119  };
120 }
121 
134 template <class T>
135 [[nodiscard]] constexpr mat4<T> ortho_half_z(T left, T right, T bottom, T top, T near, T far) noexcept
136 {
137  return
138  {{
139  {T{2} / (right - left), T{0}, T{0}, T{0}},
140  {T{0}, T{2} / (top - bottom), T{0}, T{0}},
141  {T{0}, T{0}, T{-1} / (far - near), T{0}},
142  {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -near / (far - near), T{1}}
143  }};
144 }
145 
160 template <class T>
161 [[nodiscard]] constexpr std::tuple<mat4<T>, mat4<T>> ortho_half_z_inv(T left, T right, T bottom, T top, T near, T far) noexcept
162 {
163  return
164  {
165  mat4<T>
166  {{
167  {T{2} / (right - left), T{0}, T{0}, T{0}},
168  {T{0}, T{2} / (top - bottom), T{0}, T{0}},
169  {T{0}, T{0}, T{-1} / (far - near), T{0}},
170  {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -near / (far - near), T{1}}
171  }},
172 
173  mat4<T>
174  {{
175  {(right - left) / T{2}, T{0}, T{0}, T{0}},
176  {T{0}, (top - bottom) / T{2}, T{0}, T{0}},
177  {T{0}, T{0}, -far + near, T{0}},
178  {(right + left) / T{2}, (bottom + top) / T{2}, -near, T{1}}
179  }}
180  };
181 }
182 
193 template <class T>
194 [[nodiscard]] mat4<T> perspective(T vertical_fov, T aspect_ratio, T near, T far)
195 {
196  const T half_fov = vertical_fov * T{0.5};
197  const T f = std::cos(half_fov) / std::sin(half_fov);
198 
199  return
200  {{
201  {f / aspect_ratio, T{0}, T{0}, T{0}},
202  {T{0}, f, T{0}, T{0}},
203  {T{0}, T{0}, (far + near) / (near - far), T{-1}},
204  {T{0}, T{0}, (T{2} * far * near) / (near - far), T{0}}
205  }};
206 }
207 
220 template <class T>
221 [[nodiscard]] std::tuple<mat4<T>, mat4<T>> perspective_inv(T vertical_fov, T aspect_ratio, T near, T far)
222 {
223  const T half_fov = vertical_fov * T{0.5};
224  const T f = std::cos(half_fov) / std::sin(half_fov);
225 
226  return
227  {
228  mat4<T>
229  {{
230  {f / aspect_ratio, T{0}, T{0}, T{0}},
231  {T{0}, f, T{0}, T{0}},
232  {T{0}, T{0}, (far + near) / (near - far), T{-1}},
233  {T{0}, T{0}, (T{2} * far * near) / (near - far), T{0}}
234  }},
235 
236  mat4<T>
237  {{
238  {aspect_ratio / f, T{0}, T{0}, T{0}},
239  {T{0}, T{1} / f, T{0}, T{0}},
240  {T{0}, T{0}, T{0}, (near - far) / (T{2} * near * far)},
241  {T{0}, T{0}, T{-1}, (near + far) / (T{2} * near * far)}
242  }}
243  };
244 }
245 
256 template <class T>
257 [[nodiscard]] mat4<T> perspective_half_z(T vertical_fov, T aspect_ratio, T near, T far)
258 {
259  const T half_fov = vertical_fov * T{0.5};
260  const T f = std::cos(half_fov) / std::sin(half_fov);
261 
262  return
263  {{
264  {f / aspect_ratio, T{0}, T{0}, T{0}},
265  {T{0}, f, T{0}, T{0}},
266  {T{0}, T{0}, far / (near - far), T{-1}},
267  {T{0}, T{0}, -(far * near) / (far - near), T{0}}
268  }};
269 }
270 
283 template <class T>
284 [[nodiscard]] std::tuple<mat4<T>, mat4<T>> perspective_half_z_inv(T vertical_fov, T aspect_ratio, T near, T far)
285 {
286  const T half_fov = vertical_fov * T{0.5};
287  const T f = std::cos(half_fov) / std::sin(half_fov);
288 
289  return
290  {
291  mat4<T>
292  {{
293  {f / aspect_ratio, T{0}, T{0}, T{0}},
294  {T{0}, f, T{0}, T{0}},
295  {T{0}, T{0}, far / (near - far), T{-1}},
296  {T{0}, T{0}, -(far * near) / (far - near), T{0}}
297  }},
298 
299  mat4<T>
300  {{
301  {aspect_ratio / f, T{0}, T{0}, T{0}},
302  {T{0}, T{1} / f, T{0}, T{0}},
303  {T{0}, T{0}, T{0}, T{1} / far - T{1} / near},
304  {T{0}, T{0}, T{-1}, T{1} / near}
305  }}
306  };
307 }
308 
318 template <class T>
319 [[nodiscard]] mat4<T> inf_perspective_half_z_reverse(T vertical_fov, T aspect_ratio, T near)
320 {
321  const T half_fov = vertical_fov * T{0.5};
322  const T f = std::cos(half_fov) / std::sin(half_fov);
323 
324  return
325  {{
326  {f / aspect_ratio, T{0}, T{0}, T{0}},
327  {T{0}, f, T{0}, T{0}},
328  {T{0}, T{0}, T{0}, T{-1}},
329  {T{0}, T{0}, near, T{0}}
330  }};
331 }
332 
344 template <class T>
345 [[nodiscard]] std::tuple<mat4<T>, mat4<T>> inf_perspective_half_z_reverse_inv(T vertical_fov, T aspect_ratio, T near)
346 {
347  const T half_fov = vertical_fov * T{0.5};
348  const T f = std::cos(half_fov) / std::sin(half_fov);
349 
350  return
351  {
352  mat4<T>
353  {{
354  {f / aspect_ratio, T{0}, T{0}, T{0}},
355  {T{0}, f, T{0}, T{0}},
356  {T{0}, T{0}, T{0}, T{-1}},
357  {T{0}, T{0}, near, T{0}}
358  }},
359 
360  mat4<T>
361  {{
362  {aspect_ratio / f, T{0}, T{0}, T{0}},
363  {T{0}, T{1} / f, T{0}, T{0}},
364  {T{0}, T{0}, T{0}, T{1} / near},
365  {T{0}, T{0}, T{-1}, T{0}}
366  }}
367  };
368 }
369 
370 } // namespace math
371 
372 #endif // ANTKEEPER_MATH_PROJECTION_HPP
Mathematical functions and data types.
Definition: angles.hpp:26
constexpr std::tuple< mat4< T >, mat4< T > > ortho_inv(T left, T right, T bottom, T top, T near, T far) noexcept
Constructs an orthographic projection matrix which will transform the near and far clipping planes to...
T vertical_fov(T h, T r)
Calculates a vertical FoV given a horizontal FoV and aspect ratio.
constexpr mat4< T > ortho_half_z(T left, T right, T bottom, T top, T near, T far) noexcept
Constructs an orthographic projection matrix which will transform the near and far clipping planes to...
constexpr std::tuple< mat4< T >, mat4< T > > ortho_half_z_inv(T left, T right, T bottom, T top, T near, T far) noexcept
Constructs an orthographic projection matrix which will transform the near and far clipping planes to...
mat4< T > perspective_half_z(T vertical_fov, T aspect_ratio, T near, T far)
Constructs a perspective projection matrix which will transform the near and far clipping planes to [...
constexpr mat4< T > ortho(T left, T right, T bottom, T top, T near, T far) noexcept
Constructs an orthographic projection matrix which will transform the near and far clipping planes to...
T horizontal_fov(T v, T r)
Calculates a horizontal FoV given a vertical FoV and aspect ratio.
std::tuple< mat4< T >, mat4< T > > perspective_inv(T vertical_fov, T aspect_ratio, T near, T far)
Constructs a perspective projection matrix which will transform the near and far clipping planes to [...
mat4< T > perspective(T vertical_fov, T aspect_ratio, T near, T far)
Constructs a perspective projection matrix which will transform the near and far clipping planes to [...
mat4< T > inf_perspective_half_z_reverse(T vertical_fov, T aspect_ratio, T near)
Constructs a perspective projection matrix, with an infinite far plane, which will transform the near...
std::tuple< mat4< T >, mat4< T > > perspective_half_z_inv(T vertical_fov, T aspect_ratio, T near, T far)
Constructs a perspective projection matrix which will transform the near and far clipping planes to [...
std::tuple< mat4< T >, mat4< T > > inf_perspective_half_z_reverse_inv(T vertical_fov, T aspect_ratio, T near)
Constructs a perspective projection matrix, with an infinite far plane, which will transform the near...
n by m column-major matrix.
Definition: math/matrix.hpp:44