SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
ViewFrustum.hpp
Go to the documentation of this file.
1#ifndef _VIEW_FRUSTUM_HPP_
2#define _VIEW_FRUSTUM_HPP_
3
4#include <Math/Matrix.hpp>
5#include <Math/Vector.hpp>
6#include <cmath>
7
8namespace Sleak {
9
10/// A plane in ax + by + cz + d = 0 form, used as one face of a ViewFrustum.
11/// @ingroup camera
12struct Plane {
13 float a, b, c, d;
14
15 float DistanceToPoint(const Math::Vector3D& p) const {
16 return a * p.GetX() + b * p.GetY() + c * p.GetZ() + d;
17 }
18
19 /// Rescales the plane coefficients so (a, b, c) is unit length.
20 void Normalize() {
21 float len = std::sqrt(a * a + b * b + c * c);
22 if (len > 0.0f) {
23 float inv = 1.0f / len;
24 a *= inv;
25 b *= inv;
26 c *= inv;
27 d *= inv;
28 }
29 }
30};
31
32/// Six-plane view frustum, extracted from a view-projection matrix and used
33/// for CPU-side AABB visibility tests.
34/// @ingroup camera
36public:
37 /// Index of each plane within ViewFrustum::planes.
38 enum { Left = 0, Right, Bottom, Top, Near, Far, COUNT };
40
41 // Extract frustum planes from VP matrix (row-vector convention: clip = point * VP).
42 // Uses column-based Gribb-Hartmann extraction.
44 // Left: col0 + col3 (clip.x >= -clip.w)
45 planes[Left].a = m(0, 0) + m(0, 3);
46 planes[Left].b = m(1, 0) + m(1, 3);
47 planes[Left].c = m(2, 0) + m(2, 3);
48 planes[Left].d = m(3, 0) + m(3, 3);
49
50 // Right: col3 - col0 (clip.x <= clip.w)
51 planes[Right].a = m(0, 3) - m(0, 0);
52 planes[Right].b = m(1, 3) - m(1, 0);
53 planes[Right].c = m(2, 3) - m(2, 0);
54 planes[Right].d = m(3, 3) - m(3, 0);
55
56 // Bottom: col1 + col3 (clip.y >= -clip.w)
57 planes[Bottom].a = m(0, 1) + m(0, 3);
58 planes[Bottom].b = m(1, 1) + m(1, 3);
59 planes[Bottom].c = m(2, 1) + m(2, 3);
60 planes[Bottom].d = m(3, 1) + m(3, 3);
61
62 // Top: col3 - col1 (clip.y <= clip.w)
63 planes[Top].a = m(0, 3) - m(0, 1);
64 planes[Top].b = m(1, 3) - m(1, 1);
65 planes[Top].c = m(2, 3) - m(2, 1);
66 planes[Top].d = m(3, 3) - m(3, 1);
67
68 // Near: col2 (clip.z >= 0, depth range [0, w])
69 planes[Near].a = m(0, 2);
70 planes[Near].b = m(1, 2);
71 planes[Near].c = m(2, 2);
72 planes[Near].d = m(3, 2);
73
74 // Far: col3 - col2 (clip.z <= clip.w)
75 planes[Far].a = m(0, 3) - m(0, 2);
76 planes[Far].b = m(1, 3) - m(1, 2);
77 planes[Far].c = m(2, 3) - m(2, 2);
78 planes[Far].d = m(3, 3) - m(3, 2);
79
80 for (int i = 0; i < COUNT; ++i)
81 planes[i].Normalize();
82 }
83
84 // Test AABB against frustum using the positive-vertex method.
85 // For each plane, find the AABB corner most along the plane normal;
86 // if that corner is behind the plane, the AABB is fully outside.
87 bool IsAABBVisible(const Math::Vector3D& min, const Math::Vector3D& max) const {
88 for (int i = 0; i < COUNT; ++i) {
89 // Pick the positive vertex (corner furthest in the plane normal direction)
90 float px = (planes[i].a >= 0.0f) ? max.GetX() : min.GetX();
91 float py = (planes[i].b >= 0.0f) ? max.GetY() : min.GetY();
92 float pz = (planes[i].c >= 0.0f) ? max.GetZ() : min.GetZ();
93
94 if (planes[i].a * px + planes[i].b * py + planes[i].c * pz + planes[i].d < 0.0f)
95 return false;
96 }
97 return true;
98 }
99};
100
101} // namespace Sleak
102
103#endif
float GetY() const
Definition Vector.hpp:361
float GetX() const
Definition Vector.hpp:360
float GetZ() const
Definition Vector.hpp:362
void ExtractFromVP(const Math::Matrix4 &m)
bool IsAABBVisible(const Math::Vector3D &min, const Math::Vector3D &max) const
Plane planes[COUNT]
Matrix< float, 4, 4 > Matrix4
Definition Matrix.hpp:413
Root namespace for everything the engine exposes.
Definition Camera.hpp:10
void Normalize()
Rescales the plane coefficients so (a, b, c) is unit length.
float DistanceToPoint(const Math::Vector3D &p) const