8auto get_transformed_bbox_vertices(
const bbox& AABB,
const transform& t) -> std::array<vec3, 8>
10 std::array<vec3, 8> vertices;
15 vertices[0] =
t.transform_coord(vec3(min.x, min.y, min.z));
16 vertices[1] =
t.transform_coord(vec3(max.x, min.y, min.z));
17 vertices[2] =
t.transform_coord(vec3(min.x, max.y, min.z));
18 vertices[3] =
t.transform_coord(vec3(max.x, max.y, min.z));
19 vertices[4] =
t.transform_coord(vec3(min.x, min.y, max.z));
20 vertices[5] =
t.transform_coord(vec3(max.x, min.y, max.z));
21 vertices[6] =
t.transform_coord(vec3(min.x, max.y, max.z));
22 vertices[7] =
t.transform_coord(vec3(max.x, max.y, max.z));
32 planes.fill(vec4(0.0f, 0.0f, 0.0f, 0.0f));
33 points.fill(vec3(0.0f, 0.0f, 0.0f));
39 update(View, Proj, homogeneousDepth);
122 position = vec3(view[0][0], view[1][0], view[2][0]) * -view[3][0];
123 position += vec3(view[0][1], view[1][1], view[2][1]) * -view[3][1];
124 position += vec3(view[0][2], view[1][2], view[2][2]) * -view[3][2];
127 vec3 forward = -vec3(view[0][2], view[1][2], view[2][2]);
156 for(std::size_t i = 0; i < 8; ++i)
168 vec3 n1_n2 = glm::cross(n1, n2);
169 vec3 n2_n0 = glm::cross(n2, n0);
170 vec3 n0_n1 = glm::cross(n0, n1);
172 float cosTheta = glm::dot(n0, n1_n2);
173 float secTheta = 1.0f / cosTheta;
175 n1_n2 = n1_n2 * p0.
data.w;
176 n2_n0 = n2_n0 * p1.
data.w;
177 n0_n1 = n0_n1 * p2.
data.w;
179 points[i] = -(n1_n2 + n2_n0 + n0_n1) * secTheta;
190 for(
const auto&
plane : planes)
192 bool allOutside =
true;
193 bool anyOutside =
false;
196 for(
size_t i = 0; i < count; ++i)
230 vec3 nearPoint, farPoint;
232 for(
const auto&
plane : planes)
234 nearPoint.x =
plane.
data.x > 0.0f ? AABB.min.x : AABB.max.x;
235 farPoint.x =
plane.
data.x > 0.0f ? AABB.max.x : AABB.min.x;
237 nearPoint.y =
plane.
data.y > 0.0f ? AABB.min.y : AABB.max.y;
238 farPoint.y =
plane.
data.y > 0.0f ? AABB.max.y : AABB.min.y;
240 nearPoint.z =
plane.
data.z > 0.0f ? AABB.min.z : AABB.max.z;
241 farPoint.z =
plane.
data.z > 0.0f ? AABB.max.z : AABB.min.z;
259 auto vertices = get_transformed_bbox_vertices(AABB, t);
260 return classify_vertices(vertices.data(), vertices.size());
266 vec3 nearPoint, farPoint;
268 if(lastOutside >= 0 && ((frustumBits >> lastOutside) & 0x1) == 0x0)
272 nearPoint.x =
plane.
data.x > 0.0f ? AABB.min.x : AABB.max.x;
273 farPoint.x =
plane.
data.x > 0.0f ? AABB.max.x : AABB.min.x;
275 nearPoint.y =
plane.
data.y > 0.0f ? AABB.min.y : AABB.max.y;
276 farPoint.y =
plane.
data.y > 0.0f ? AABB.max.y : AABB.min.y;
278 nearPoint.z =
plane.
data.z > 0.0f ? AABB.min.z : AABB.max.z;
279 farPoint.z =
plane.
data.z > 0.0f ? AABB.max.z : AABB.min.z;
292 frustumBits |= (0x1 << lastOutside);
296 for(
size_t i = 0; i < planes.size(); i++)
298 if(((frustumBits >> i) & 0x1) == 0x1)
300 if(lastOutside >= 0 && lastOutside ==
int(i))
305 nearPoint.x =
plane.
data.x > 0.0f ? AABB.min.x : AABB.max.x;
306 farPoint.x =
plane.
data.x > 0.0f ? AABB.max.x : AABB.min.x;
308 nearPoint.y =
plane.
data.y > 0.0f ? AABB.min.y : AABB.max.y;
309 farPoint.y =
plane.
data.y > 0.0f ? AABB.max.y : AABB.min.y;
311 nearPoint.z =
plane.
data.z > 0.0f ? AABB.min.z : AABB.max.z;
312 farPoint.z =
plane.
data.z > 0.0f ? AABB.max.z : AABB.min.z;
316 lastOutside = int(i);
326 frustumBits |= (0x1 << i);
338 for(
const auto&
plane : planes)
340 nearPoint.x =
plane.
data.x > 0.0f ? AABB.min.x : AABB.max.x;
341 nearPoint.y =
plane.
data.y > 0.0f ? AABB.min.y : AABB.max.y;
342 nearPoint.z =
plane.
data.z > 0.0f ? AABB.min.z : AABB.max.z;
359 for(
const auto&
plane : planes)
361 bool allOutside =
true;
363 for(
size_t i = 0; i < vert_count; ++i)
386 auto vertices = get_transformed_bbox_vertices(AABB, t);
387 return test_vertices(vertices.data(), vertices.size());
395 for(
const auto&
plane : planes)
400 if(fDot >= sphere.radius)
406 if(fDot >= -sphere.radius)
420 for(
const auto&
plane : planes)
425 if(fDot >= sphere.radius)
438 return test_sphere(
bsphere(t.transform_coord(sphere.position), sphere.radius));
441auto frustum::swept_sphere_intersect_plane(
float& t0,
445 const vec3& vecSweepDirection) ->
bool
452 if(b_dot_n <= sphere.radius)
456 t1 = std::numeric_limits<float>::max();
466 float tmp0 = (
sphere.radius - b_dot_n) / d_dot_n;
467 float tmp1 = (-
sphere.radius - b_dot_n) / d_dot_n;
468 t0 = glm::min<float>(tmp0, tmp1);
469 t1 = glm::max<float>(tmp0, tmp1);
477 unsigned int i, nCount = 0;
478 float t0, t1, fDisplacedRadius;
479 float pDisplacements[12];
480 vec3 vDisplacedCenter;
484 for(
const auto&
plane : planes)
487 if(swept_sphere_intersect_plane(t0, t1,
plane, sphere, vecSweepDirection))
492 pDisplacements[nCount++] = t0;
496 pDisplacements[nCount++] = t1;
506 for(i = 0; i < nCount; ++i)
508 vDisplacedCenter = sphere.position + (vecSweepDirection * pDisplacements[i]);
509 fDisplacedRadius = sphere.radius * 1.1f;
510 if(test_sphere(
bsphere(vDisplacedCenter, fDisplacedRadius)))
523 return test_sphere(
bsphere(vecPoint, 0.0f));
528 int nCode1 = 0, nCode2 = 0;
529 float fDist1, fDist2, t;
531 vec3 vDir, vIntersect;
535 for(i = 0; i < 6; ++i)
540 nSide1 = (fDist1 >= 0) ? 1 : 0;
541 nSide2 = (fDist2 >= 0) ? 1 : 0;
545 nCode1 |= (nSide1 << i);
546 nCode2 |= (nSide2 << i);
550 if(nSide1 == 1 && nSide2 == 1)
556 if((nSide1 ^ nSide2) != 0)
563 if((t >= 0.0f) && (t <= 1.0f))
565 vIntersect = v1 + (vDir * t);
566 if(test_sphere(
bsphere(vIntersect, 0.01f)))
578 return (nCode1 == 0) || (nCode2 == 0);
583 unsigned int nInFrontCount = 0;
584 unsigned int nBehindCount = 0;
587 for(
unsigned int i = 0; i < 8; ++i)
602 if(nInFrontCount == 8)
608 if(nBehindCount == 8)
692 for(
auto&
plane : planes)
698 for(
auto&
point : points)
704 position = mtx.transform_coord(position);
713 for(
size_t i = 0; i < planes.size(); ++i)
715 const plane& p1 = planes[i];
717 if(!(glm::abs<float>(p1.
data.x - p2.
data.x) <= glm::epsilon<float>() &&
718 glm::abs<float>(p1.
data.y - p2.
data.y) <= glm::epsilon<float>() &&
719 glm::abs<float>(p1.
data.z - p2.
data.z) <= glm::epsilon<float>() &&
720 glm::abs<float>(p1.
data.w - p2.
data.w) <= glm::epsilon<float>()))
Provides storage for common representation of spherical bounding volume, and wraps up common function...
Storage for frustum planes / values and wraps up common functionality.
auto classify_aabb(const bbox &bounds) const -> volume_query
Classifies an axis-aligned bounding box (AABB) with respect to the frustum.
auto classify_sphere(const bsphere &sphere) const -> volume_query
Classifies a sphere with respect to the frustum.
void recompute_points()
Recomputes the frustum's corner points based on its planes.
frustum()
Default constructor.
auto test_aabb(const bbox &bounds) const -> bool
Tests if an axis-aligned bounding box (AABB) is inside or intersecting the frustum.
auto test_point(const vec3 &point) const -> bool
Tests if a point is inside or intersecting the frustum.
auto test_sphere(const bsphere &sphere) const -> bool
Tests if a sphere is inside or intersecting the frustum.
auto mul(const transform &t) -> frustum &
Multiplies the frustum by a transform.
void update(const transform &view, const transform &proj, bool _oglNDC)
Updates the frustum based on the specified view and projection matrices.
auto test_swept_sphere(const bsphere &sphere, const vec3 &sweepDirection) const -> bool
Determine whether or not the specified sphere, swept along the provided direction vector,...
std::array< plane, 6 > planes
< The 6 planes of the frustum.
auto test_vertices(const vec3 *vertices, size_t count) const -> bool
Tests if vertices are inside or intersect the frustum.
void set_planes(const std::array< plane, 6 > &new_planes)
Sets the frustum planes.
auto classify_plane(const plane &plane) const -> volume_query
Classifies a plane with respect to the frustum.
auto test_line(const vec3 &v1, const vec3 &v2) const -> bool
Tests if a line intersects the frustum.
auto classify_vertices(const vec3 *vertices, size_t count) const -> volume_query
Classifies vertices with respect to the frustum.
auto classify_obb(const bbox &bounds, const transform &t) const -> volume_query
Classifies an oriented bounding box (OBB) with respect to the frustum.
auto test_frustum(const frustum &frustum) const -> bool
Tests if another frustum intersects this frustum.
auto operator==(const frustum &f) const -> bool
Equality operator.
auto test_obb(const bbox &bounds, const transform &t) const -> bool
Tests if an oriented bounding box (OBB) is inside or intersecting the frustum.
std::array< vec3, 8 > points
The originating position of the frustum.
auto inverse(transform_t< T, Q > const &t) noexcept -> transform_t< T, Q >
transform_t< float > transform
auto transpose(transform_t< T, Q > const &t) noexcept -> transform_t< T, Q >
@ sphere
Sphere type reflection probe.
Storage for box vector values and wraps up common functionality.
plane get_plane(volume_plane::e side) const
Retrieves the plane for the specified side of the bounding box.
vec3 get_extents() const
Returns a vector containing the extents of the bounding box (the half-dimensions)
vec3 get_center() const
Returns a vector containing the exact center point of the box.
Storage for infinite plane.
static auto normalize(const plane &p) -> plane
Normalizes the plane.
static auto dot_normal(const plane &p, const vec3 &v) -> float
Computes the dot product of the plane normal and a vec3.
static auto dot_coord(const plane &p, const vec3 &v) -> float
Computes the dot product of the plane and a vec3 (considering the plane's distance).
static auto mul(const plane &p, const mat4 &m) -> plane
Transforms a plane by a 4x4 matrix.
vec4 data
The components of the plane.