Toast Engine
Loading...
Searching...
No Matches
frustum.hpp
Go to the documentation of this file.
1
4
5#pragma once
6
7#include <array>
8#include <glm/glm.hpp>
9#include <limits>
10#include <utility>
11
12namespace renderer {
13
14using FrustumPlanes = std::array<glm::vec4, 6>;
15
16struct Box {
17 glm::vec3 min {0.0f};
18 glm::vec3 max {0.0f};
19};
20
23[[nodiscard]]
24inline auto extractFrustumPlanes(const glm::mat4& view_projection, bool reversed_depth = false) -> FrustumPlanes {
25 const auto& m = view_projection;
26 // glm is column major
27 const glm::vec4 row0(m[0][0], m[1][0], m[2][0], m[3][0]);
28 const glm::vec4 row1(m[0][1], m[1][1], m[2][1], m[3][1]);
29 const glm::vec4 row2(m[0][2], m[1][2], m[2][2], m[3][2]);
30 const glm::vec4 row3(m[0][3], m[1][3], m[2][3], m[3][3]);
31
32 FrustumPlanes planes {row3 + row0, row3 - row0, row3 + row1, row3 - row1, row2, row3 - row2};
33 if (reversed_depth) {
34 std::swap(planes[4], planes[5]);
35 }
36
37 for (auto& plane : planes) {
38 const float length = glm::length(glm::vec3(plane));
39 if (length > 0.0f) {
40 plane /= length;
41 }
42 }
43 return planes;
44}
45
46[[nodiscard]]
47inline auto sphereInFrustum(const FrustumPlanes& planes, const glm::vec3& center, float radius) -> bool {
48 for (const auto& plane : planes) {
49 if (glm::dot(glm::vec3(plane), center) + plane.w < -radius) {
50 return false;
51 }
52 }
53 return true;
54}
55
57[[nodiscard]]
58inline auto transformBox(const glm::mat4& model, const glm::vec3& min, const glm::vec3& max) -> Box {
59 Box out {glm::vec3(std::numeric_limits<float>::max()), glm::vec3(std::numeric_limits<float>::lowest())};
60 for (int corner = 0; corner < 8; ++corner) {
61 const glm::vec3 local(
62 (corner & 1) != 0 ? max.x : min.x, (corner & 2) != 0 ? max.y : min.y, (corner & 4) != 0 ? max.z : min.z
63 );
64 const glm::vec3 world = glm::vec3(model * glm::vec4(local, 1.0f));
65 out.min = glm::min(out.min, world);
66 out.max = glm::max(out.max, world);
67 }
68 return out;
69}
70
72[[nodiscard]]
73inline auto boxTouchesLateralFrustum(const FrustumPlanes& planes, const Box& box) -> bool {
74 constexpr size_t k_near = 4;
75 for (size_t i = 0; i < planes.size(); ++i) {
76 if (i == k_near) {
77 continue;
78 }
79 const glm::vec3 normal(planes[i]);
80 const glm::vec3 support(
81 normal.x >= 0.0f ? box.max.x : box.min.x,
82 normal.y >= 0.0f ? box.max.y : box.min.y,
83 normal.z >= 0.0f ? box.max.z : box.min.z
84 );
85 if (glm::dot(normal, support) + planes[i].w < 0.0f) {
86 return false;
87 }
88 }
89 return true;
90}
91
92}
auto transformBox(const glm::mat4 &model, const glm::vec3 &min, const glm::vec3 &max) -> Box
World axis aligned box around a box in the space model maps from.
Definition frustum.hpp:58
auto boxTouchesLateralFrustum(const FrustumPlanes &planes, const Box &box) -> bool
Skips the near plane so a box in front of it still counts.
Definition frustum.hpp:73
auto extractFrustumPlanes(const glm::mat4 &view_projection, bool reversed_depth=false) -> FrustumPlanes
Definition frustum.hpp:24
Definition frustum.hpp:16