42#ifndef UFO_GEOMETRY_FRUSTUM_HPP
43#define UFO_GEOMETRY_FRUSTUM_HPP
46#include <ufo/geometry/plane.hpp>
47#include <ufo/numeric/vec.hpp>
67template <std::
size_t Dim = 3, std::
floating_po
int T =
float>
79 std::array<Plane<Dim, T>, 2 * Dim>
planes;
94 constexpr
Frustum(
Vec<2, T> const& far_right,
Vec<2, T> const& far_left,
95 Vec<2, T> const& near_left,
Vec<2, T> const& near_right)
119 auto half_fov = fov * T(0.5);
120 auto half_width_near = near_dist * std::tan(half_fov);
121 auto half_width_far = far_dist * std::tan(half_fov);
123 Vec<2, T> far_right = pos + dir * far_dist + half_width_far * right_dir;
124 Vec<2, T> far_left = pos + dir * far_dist - half_width_far * right_dir;
125 Vec<2, T> near_left = pos + dir * near_dist - half_width_near * right_dir;
126 Vec<2, T> near_right = pos + dir * near_dist + half_width_near * right_dir;
154 Plane<Dim, T>(near_bottom_right, near_top_right, far_bottom_right);
156 Plane<Dim, T>(near_bottom_left, near_bottom_right, far_bottom_right);
174 T vertical_fov, T horizontal_fov, T near_distance, T far_distance)
177 T ratio = horizontal_fov / vertical_fov;
179 T tang = std::tan(vertical_fov *
static_cast<T
>(0.5));
180 T near_height = near_distance * tang;
181 T near_width = near_height * ratio;
182 T far_height = far_distance * tang;
183 T far_width = far_height * ratio;
187 auto Y =
cross(Z, X);
189 auto nc = pos - Z * near_distance;
190 auto fc = pos - Z * far_distance;
192 auto ntl = nc + Y * near_height - X * near_width;
193 auto ntr = nc + Y * near_height + X * near_width;
194 auto nbl = nc - Y * near_height - X * near_width;
195 auto nbr = nc - Y * near_height + X * near_width;
197 auto ftl = fc + Y * far_height - X * far_width;
198 auto ftr = fc + Y * far_height + X * far_width;
199 auto fbl = fc - Y * far_height - X * far_width;
200 auto fbr = fc - Y * far_height + X * far_width;
221 template <std::convertible_to<T> U>
224 for (std::size_t i = 0; i < 2 * Dim; ++i) {
232 [[nodiscard]]
static constexpr std::size_t
dimension() noexcept {
return Dim; }
240 [[nodiscard]]
constexpr auto&
operator[](
this auto& self, std::size_t pos)
noexcept
242 return self.planes[pos];
258 for (
auto const& p :
planes) {
259 c += p.normal * p.distance;
261 return c / T(2 * Dim);
282 for (
auto const& p :
planes) {
283 if (p.isDegenerate()) {
294template <std::
size_t Dim, std::
floating_po
int T>
297 if constexpr (2 == Dim) {
298 return out <<
"Left: [" << frustum[0] <<
"], Right: [" << frustum[1] <<
"], Bottom: ["
299 << frustum[2] <<
"], Top: [" << frustum[3] <<
"]";
300 }
else if constexpr (3 == Dim) {
301 return out <<
"Left: [" << frustum[0] <<
"], Right: [" << frustum[1] <<
"], Bottom: ["
302 << frustum[2] <<
"], Top: [" << frustum[3] <<
"], Near: [" << frustum[4]
303 <<
"], Far: [" << frustum[5] <<
"]";
306 for (std::size_t i = 0; i < 2 * Dim; ++i) {
307 out <<
"[" << frustum[i] <<
"]" << (i == 2 * Dim - 1 ?
"" :
", ");
313template <std::
size_t Dim, std::
floating_po
int T>
314using FrustumX = Frustum<Dim, T>;
316template <std::
floating_po
int T>
317using Frustum1 = Frustum<1, T>;
318template <std::
floating_po
int T>
319using Frustum2 = Frustum<2, T>;
320template <std::
floating_po
int T>
321using Frustum3 = Frustum<3, T>;
322template <std::
floating_po
int T>
323using Frustum4 = Frustum<4, T>;
325using Frustum1f = Frustum<1, float>;
326using Frustum2f = Frustum<2, float>;
327using Frustum3f = Frustum<3, float>;
328using Frustum4f = Frustum<4, float>;
330using Frustum1d = Frustum<1, double>;
331using Frustum2d = Frustum<2, double>;
332using Frustum3d = Frustum<3, double>;
333using Frustum4d = Frustum<4, double>;
337template <std::
size_t Dim, std::
floating_po
int T>
338 requires std::formattable<T, char>
339struct std::formatter<
ufo::Frustum<Dim, T>> {
340 constexpr auto parse(std::format_parse_context& ctx) {
return ctx.begin(); }
344 if constexpr (2 == Dim) {
345 return std::format_to(ctx.out(),
"Left: [{}], Right: [{}], Bottom: [{}], Top: [{}]",
346 frustum[0], frustum[1], frustum[2], frustum[3]);
347 }
else if constexpr (3 == Dim) {
348 return std::format_to(
350 "Left: [{}], Right: [{}], Bottom: [{}], Top: [{}], Near: [{}], Far: [{}]",
351 frustum[0], frustum[1], frustum[2], frustum[3], frustum[4], frustum[5]);
353 std::format_to(ctx.out(),
"Planes: ");
354 for (std::size_t i = 0; i < 2 * Dim; ++i) {
355 std::format_to(ctx.out(),
"[{}]{}", frustum[i], (i == 2 * Dim - 1 ?
"" :
", "));
All vision-related classes and functions.
constexpr Quat< T > normalize(Quat< T > const &q) noexcept
Returns a unit quaternion in the same direction as q.
constexpr Quat< T > cross(Quat< T > const &q1, Quat< T > const &q2) noexcept
Computes the Hamilton cross product of two quaternions.
Axis-Aligned Bounding Box (AABB) in Dim-dimensional space.
Frustum in Dim-dimensional space.
constexpr Frustum(Vec< 2, T > const &pos, Vec< 2, T > const &target, T fov, T near_dist, T far_dist)
Constructs a 2D frustum from a camera-like setup.
constexpr Frustum() noexcept=default
Default constructor.
constexpr AABB< Dim, T > aabb() const noexcept
Returns the AABB of the frustum.
bool operator==(Frustum const &) const =default
Equality operator.
std::array< Plane< Dim, T >, 2 *Dim > planes
The planes defining the frustum.
constexpr Frustum(Vec< 3, T > const &pos, Vec< 3, T > const &target, Vec< 3, T > const &up, T vertical_fov, T horizontal_fov, T near_distance, T far_distance)
Constructs a 3D frustum from a camera-like setup.
constexpr Frustum(Vec< 3, T > const &far_top_right, Vec< 3, T > const &far_top_left, Vec< 3, T > const &far_bottom_left, Vec< 3, T > const &far_bottom_right, Vec< 3, T > const &near_top_right, Vec< 3, T > const &near_top_left, Vec< 3, T > const &near_bottom_left, Vec< 3, T > const &near_bottom_right)
Constructs a 3D frustum from eight points.
static constexpr std::size_t dimension() noexcept
Returns the dimensionality of the frustum.
constexpr Vec< Dim, T > center() const noexcept
Returns the center of the frustum.
constexpr Frustum(Frustum< Dim, U > const &other) noexcept
Converting constructor from a frustum with a different scalar type.
constexpr Frustum(Frustum const &) noexcept=default
Copy constructor.
constexpr auto & operator[](this auto &self, std::size_t pos) noexcept
Accesses the plane at position pos.
constexpr bool isDegenerate() const noexcept
Returns whether the frustum is degenerate.
A fixed-size arithmetic vector of up to 4 dimensions.