1 #include <glm/matrix.hpp>
8 // m = ProjectionMatrix * ViewMatrix
11 // http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
12 bool IsBoxVisible(const glm::vec3& minp, const glm::vec3& maxp) const;
24 Combinations = Count * (Count - 1) / 2
27 template<Planes i, Planes j>
30 enum { k = i * (9 - i) / 2 + j - 1 };
33 template<Planes a, Planes b, Planes c>
34 glm::vec3 intersection(const glm::vec3* crosses) const;
36 glm::vec4 m_planes[Count];
37 glm::vec3 m_points[8];
40 inline Frustum::Frustum(glm::mat4 m)
42 m = glm::transpose(m);
43 m_planes[Left] = m[3] + m[0];
44 m_planes[Right] = m[3] - m[0];
45 m_planes[Bottom] = m[3] + m[1];
46 m_planes[Top] = m[3] - m[1];
47 m_planes[Near] = m[3] + m[2];
48 m_planes[Far] = m[3] - m[2];
50 glm::vec3 crosses[Combinations] = {
51 glm::cross(glm::vec3(m_planes[Left]), glm::vec3(m_planes[Right])),
52 glm::cross(glm::vec3(m_planes[Left]), glm::vec3(m_planes[Bottom])),
53 glm::cross(glm::vec3(m_planes[Left]), glm::vec3(m_planes[Top])),
54 glm::cross(glm::vec3(m_planes[Left]), glm::vec3(m_planes[Near])),
55 glm::cross(glm::vec3(m_planes[Left]), glm::vec3(m_planes[Far])),
56 glm::cross(glm::vec3(m_planes[Right]), glm::vec3(m_planes[Bottom])),
57 glm::cross(glm::vec3(m_planes[Right]), glm::vec3(m_planes[Top])),
58 glm::cross(glm::vec3(m_planes[Right]), glm::vec3(m_planes[Near])),
59 glm::cross(glm::vec3(m_planes[Right]), glm::vec3(m_planes[Far])),
60 glm::cross(glm::vec3(m_planes[Bottom]), glm::vec3(m_planes[Top])),
61 glm::cross(glm::vec3(m_planes[Bottom]), glm::vec3(m_planes[Near])),
62 glm::cross(glm::vec3(m_planes[Bottom]), glm::vec3(m_planes[Far])),
63 glm::cross(glm::vec3(m_planes[Top]), glm::vec3(m_planes[Near])),
64 glm::cross(glm::vec3(m_planes[Top]), glm::vec3(m_planes[Far])),
65 glm::cross(glm::vec3(m_planes[Near]), glm::vec3(m_planes[Far]))
68 m_points[0] = intersection<Left, Bottom, Near>(crosses);
69 m_points[1] = intersection<Left, Top, Near>(crosses);
70 m_points[2] = intersection<Right, Bottom, Near>(crosses);
71 m_points[3] = intersection<Right, Top, Near>(crosses);
72 m_points[4] = intersection<Left, Bottom, Far>(crosses);
73 m_points[5] = intersection<Left, Top, Far>(crosses);
74 m_points[6] = intersection<Right, Bottom, Far>(crosses);
75 m_points[7] = intersection<Right, Top, Far>(crosses);
79 // http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
80 inline bool Frustum::IsBoxVisible(const glm::vec3& minp, const glm::vec3& maxp) const
82 // check box outside/inside of frustum
83 for (int i = 0; i < Count; i++)
85 if ((glm::dot(m_planes[i], glm::vec4(minp.x, minp.y, minp.z, 1.0f)) < 0.0) &&
86 (glm::dot(m_planes[i], glm::vec4(maxp.x, minp.y, minp.z, 1.0f)) < 0.0) &&
87 (glm::dot(m_planes[i], glm::vec4(minp.x, maxp.y, minp.z, 1.0f)) < 0.0) &&
88 (glm::dot(m_planes[i], glm::vec4(maxp.x, maxp.y, minp.z, 1.0f)) < 0.0) &&
89 (glm::dot(m_planes[i], glm::vec4(minp.x, minp.y, maxp.z, 1.0f)) < 0.0) &&
90 (glm::dot(m_planes[i], glm::vec4(maxp.x, minp.y, maxp.z, 1.0f)) < 0.0) &&
91 (glm::dot(m_planes[i], glm::vec4(minp.x, maxp.y, maxp.z, 1.0f)) < 0.0) &&
92 (glm::dot(m_planes[i], glm::vec4(maxp.x, maxp.y, maxp.z, 1.0f)) < 0.0))
98 // check frustum outside/inside box
100 out = 0; for (int i = 0; i<8; i++) out += ((m_points[i].x > maxp.x) ? 1 : 0); if (out == 8) return false;
101 out = 0; for (int i = 0; i<8; i++) out += ((m_points[i].x < minp.x) ? 1 : 0); if (out == 8) return false;
102 out = 0; for (int i = 0; i<8; i++) out += ((m_points[i].y > maxp.y) ? 1 : 0); if (out == 8) return false;
103 out = 0; for (int i = 0; i<8; i++) out += ((m_points[i].y < minp.y) ? 1 : 0); if (out == 8) return false;
104 out = 0; for (int i = 0; i<8; i++) out += ((m_points[i].z > maxp.z) ? 1 : 0); if (out == 8) return false;
105 out = 0; for (int i = 0; i<8; i++) out += ((m_points[i].z < minp.z) ? 1 : 0); if (out == 8) return false;
110 template<Frustum::Planes a, Frustum::Planes b, Frustum::Planes c>
111 inline glm::vec3 Frustum::intersection(const glm::vec3* crosses) const
113 float D = glm::dot(glm::vec3(m_planes[a]), crosses[ij2k<b, c>::k]);
114 glm::vec3 res = glm::mat3(crosses[ij2k<b, c>::k], -crosses[ij2k<a, c>::k], crosses[ij2k<a, b>::k]) *
115 glm::vec3(m_planes[a].w, m_planes[b].w, m_planes[c].w);
116 return res * (-1.0f / D);