Raito 0.1
Loading...
Searching...
No Matches
Frustum.h
Go to the documentation of this file.
1#pragma once
3
4namespace Raito::Math
5{
6 class Frustum
7 {
8 public:
9 Frustum() = default;
10
11 // m = ProjectionMatrix * ViewMatrix
13
14 // http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
15 NODISCARD bool IsBoxVisible(const V3& minp, const V3& maxp) const;
16 private:
17 enum Planes
18 {
19 LEFT = 0,
20 RIGHT,
21 BOTTOM,
22 TOP,
23 NEAR_PLANE,
24 FAR_PLANE,
25 COUNT,
26 COMBINATIONS = COUNT * (COUNT - 1) / 2
27 };
28
29 template<Planes i, Planes j>
30 struct ij2k
31 {
32 enum { k = i * (9 - i) / 2 + j - 1 };
33 };
34
35 template<Planes a, Planes b, Planes c>
36 V3 Intersection(const V3* crosses) const;
37
38 V4 m_Planes[COUNT]{};
39 V3 m_Points[8]{};
40 };
41 inline Frustum::Frustum(glm::mat4 m)
42 {
43 m = glm::transpose(m);
44 m_Planes[LEFT] = m[3] + m[0];
45 m_Planes[RIGHT] = m[3] - m[0];
46 m_Planes[BOTTOM] = m[3] + m[1];
47 m_Planes[TOP] = m[3] - m[1];
48 m_Planes[NEAR_PLANE] = m[3] + m[2];
49 m_Planes[FAR_PLANE] = m[3] - m[2];
50
51 const V3 crosses[COMBINATIONS] = {
52 cross(V3(m_Planes[LEFT]), V3(m_Planes[RIGHT])),
53 cross(V3(m_Planes[LEFT]), V3(m_Planes[BOTTOM])),
54 cross(V3(m_Planes[LEFT]), V3(m_Planes[TOP])),
55 cross(V3(m_Planes[LEFT]), V3(m_Planes[NEAR_PLANE])),
56 cross(V3(m_Planes[LEFT]), V3(m_Planes[FAR_PLANE])),
57 cross(V3(m_Planes[RIGHT]), V3(m_Planes[BOTTOM])),
58 cross(V3(m_Planes[RIGHT]), V3(m_Planes[TOP])),
59 cross(V3(m_Planes[RIGHT]), V3(m_Planes[NEAR_PLANE])),
60 cross(V3(m_Planes[RIGHT]), V3(m_Planes[FAR_PLANE])),
61 cross(V3(m_Planes[BOTTOM]), V3(m_Planes[TOP])),
62 cross(V3(m_Planes[BOTTOM]), V3(m_Planes[NEAR_PLANE])),
63 cross(V3(m_Planes[BOTTOM]), V3(m_Planes[FAR_PLANE])),
64 cross(V3(m_Planes[TOP]), V3(m_Planes[NEAR_PLANE])),
65 cross(V3(m_Planes[TOP]), V3(m_Planes[FAR_PLANE])),
66 cross(V3(m_Planes[NEAR_PLANE]), V3(m_Planes[FAR_PLANE]))
67 };
68
69 m_Points[0] = Intersection<LEFT, BOTTOM, NEAR_PLANE>(crosses);
70 m_Points[1] = Intersection<LEFT, TOP, NEAR_PLANE>(crosses);
71 m_Points[2] = Intersection<RIGHT, BOTTOM, NEAR_PLANE>(crosses);
72 m_Points[3] = Intersection<RIGHT, TOP, NEAR_PLANE>(crosses);
73 m_Points[4] = Intersection<LEFT, BOTTOM, FAR_PLANE>(crosses);
74 m_Points[5] = Intersection<LEFT, TOP, FAR_PLANE>(crosses);
75 m_Points[6] = Intersection<RIGHT, BOTTOM, FAR_PLANE>(crosses);
76 m_Points[7] = Intersection<RIGHT, TOP, FAR_PLANE>(crosses);
77
78 }
79
80 // http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
81 inline bool Frustum::IsBoxVisible(const V3& minp, const V3& maxp) const
82 {
83 // check box outside/inside of frustum
84 for (int i = 0; i < COUNT; i++)
85 {
86 if ((dot(m_Planes[i], V4(minp.x, minp.y, minp.z, 1.0f)) < 0.0) &&
87 (dot(m_Planes[i], V4(maxp.x, minp.y, minp.z, 1.0f)) < 0.0) &&
88 (dot(m_Planes[i], V4(minp.x, maxp.y, minp.z, 1.0f)) < 0.0) &&
89 (dot(m_Planes[i], V4(maxp.x, maxp.y, minp.z, 1.0f)) < 0.0) &&
90 (dot(m_Planes[i], V4(minp.x, minp.y, maxp.z, 1.0f)) < 0.0) &&
91 (dot(m_Planes[i], V4(maxp.x, minp.y, maxp.z, 1.0f)) < 0.0) &&
92 (dot(m_Planes[i], V4(minp.x, maxp.y, maxp.z, 1.0f)) < 0.0) &&
93 (dot(m_Planes[i], V4(maxp.x, maxp.y, maxp.z, 1.0f)) < 0.0))
94 {
95 return false;
96 }
97 }
98
99 // check frustum outside/inside box
100 int out;
101 out = 0; for (int i = 0; i < 8; i++) out += ((m_Points[i].x > maxp.x) ? 1 : 0); if (out == 8) return false;
102 out = 0; for (int i = 0; i < 8; i++) out += ((m_Points[i].x < minp.x) ? 1 : 0); if (out == 8) return false;
103 out = 0; for (int i = 0; i < 8; i++) out += ((m_Points[i].y > maxp.y) ? 1 : 0); if (out == 8) return false;
104 out = 0; for (int i = 0; i < 8; i++) out += ((m_Points[i].y < minp.y) ? 1 : 0); if (out == 8) return false;
105 out = 0; for (int i = 0; i < 8; i++) out += ((m_Points[i].z > maxp.z) ? 1 : 0); if (out == 8) return false;
106 out = 0; for (int i = 0; i < 8; i++) out += ((m_Points[i].z < minp.z) ? 1 : 0); if (out == 8) return false;
107
108 return true;
109 }
110
111
112
113 template<Frustum::Planes a, Frustum::Planes b, Frustum::Planes c>
114 inline V3 Frustum::Intersection(const V3* crosses) const
115 {
116 const float D = glm::dot(V3(m_Planes[a]), crosses[ij2k<b, c>::k]);
117 const V3 res = Mat3(crosses[ij2k<b, c>::k], -crosses[ij2k<a, c>::k], crosses[ij2k<a, b>::k]) *
118 V3(m_Planes[a].w, m_Planes[b].w, m_Planes[c].w);
119 return res * (-1.0f / D);
120 }
121}
#define NODISCARD
Definition Common.h:80
Definition Frustum.h:7
NODISCARD bool IsBoxVisible(const V3 &minp, const V3 &maxp) const
Definition Frustum.h:81
Definition AABB.cpp:5
glm::vec4 V4
4D Vector; 32 bit floating point components
Definition MathTypes.h:53
glm::mat4x4 Mat4
Definition MathTypes.h:80
glm::mat3x3 Mat3
3x3 Matrix: 32 bit floating point components
Definition MathTypes.h:77
glm::vec3 V3
3D Vector; 32 bit floating point components
Definition MathTypes.h:47