1 #include "geometry.hpp"
16 float t_max = std::numeric_limits<float>::infinity();
17 const glm::vec3 aabb_pos(M[3].x, M[3].y, M[3].z);
18 const glm::vec3 delta = aabb_pos - ray.orig;
20 glm::vec3 t1(t_min, t_min, t_min), t2(t_max, t_max, t_max);
23 const glm::vec3 xaxis(M[0].x, M[0].y, M[0].z);
24 const float e = glm::dot(xaxis, delta);
25 const float f = glm::dot(ray.dir, xaxis);
27 if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
28 t1.x = (e + aabb.min.x) / f;
29 t2.x = (e + aabb.max.x) / f;
31 t_min = std::max(t_min, std::min(t1.x, t2.x));
32 t_max = std::min(t_max, std::max(t1.x, t2.x));
38 if (aabb.min.x - e < 0.0f || -aabb.max.x - e > 0.0f) {
45 const glm::vec3 yaxis(M[1].x, M[1].y, M[1].z);
46 const float e = glm::dot(yaxis, delta);
47 const float f = glm::dot(ray.dir, yaxis);
49 if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
50 t1.y = (e + aabb.min.y) / f;
51 t2.y = (e + aabb.max.y) / f;
53 t_min = std::max(t_min, std::min(t1.y, t2.y));
54 t_max = std::min(t_max, std::max(t1.y, t2.y));
60 if (aabb.min.y - e < 0.0f || -aabb.max.y - e > 0.0f) {
67 const glm::vec3 zaxis(M[2].x, M[2].y, M[2].z);
68 const float e = glm::dot(zaxis, delta);
69 const float f = glm::dot(ray.dir, zaxis);
71 if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
72 t1.z = (e + aabb.min.z) / f;
73 t2.z = (e + aabb.max.z) / f;
75 t_min = std::max(t_min, std::min(t1.z, t2.z));
76 t_max = std::min(t_max, std::max(t1.z, t2.z));
82 if (aabb.min.z - e < 0.0f || -aabb.max.z - e > 0.0f) {
88 glm::vec3 min_all(min(t1, t2));
95 if (min_all.x > min_all.y) {
96 if (min_all.x > min_all.z) {
97 norm.x = t2.x < t1.x ? 1 : -1;
99 norm.z = t2.z < t1.z ? 1 : -1;
101 } else if (min_all.y > min_all.z) {
102 norm.y = t2.y < t1.y ? 1 : -1;
104 norm.z = t2.z < t1.z ? 1 : -1;
107 *normal = glm::vec3(norm);
112 bool CullTest(const AABB &box, const glm::mat4 &MVP) {
113 // transform corners into clip space
114 glm::vec4 corners[8] = {
115 { box.min.x, box.min.y, box.min.z, 1.0f },
116 { box.min.x, box.min.y, box.max.z, 1.0f },
117 { box.min.x, box.max.y, box.min.z, 1.0f },
118 { box.min.x, box.max.y, box.max.z, 1.0f },
119 { box.max.x, box.min.y, box.min.z, 1.0f },
120 { box.max.x, box.min.y, box.max.z, 1.0f },
121 { box.max.x, box.max.y, box.min.z, 1.0f },
122 { box.max.x, box.max.y, box.max.z, 1.0f },
124 for (glm::vec4 &corner : corners) {
125 corner = MVP * corner;
129 int hits[6] = { 0, 0, 0, 0, 0, 0 };
131 // check how many corners lie outside
132 for (const glm::vec4 &corner : corners) {
133 if (corner.x > 1.0f) ++hits[0];
134 if (corner.x < -1.0f) ++hits[1];
135 if (corner.y > 1.0f) ++hits[2];
136 if (corner.y < -1.0f) ++hits[3];
137 if (corner.z > 1.0f) ++hits[4];
138 if (corner.z < -1.0f) ++hits[5];
141 // if all corners are outside any given clip plane, the test is true
142 for (int hit : hits) {
143 if (hit == 8) return true;
146 // otherwise the box might still get culled completely, but can't say for sure ;)