diff --git a/include/Nazara/Math/Frustum.inl b/include/Nazara/Math/Frustum.inl index 6bddf1fe4..4fa591fd9 100644 --- a/include/Nazara/Math/Frustum.inl +++ b/include/Nazara/Math/Frustum.inl @@ -152,7 +152,7 @@ namespace Nz float radius = projectedExtents.x + projectedExtents.y + projectedExtents.z; float distance = plane.SignedDistance(center); - if (distance < T(-radius)) + if (distance < T(radius)) return false; } @@ -219,15 +219,11 @@ namespace Nz { for (const auto& plane : m_planes) { - std::size_t j; - for (j = 0; j < pointCount; j++ ) + for (std::size_t i = 0; i < pointCount; ++i) { - if (plane.SignedDistance(points[j]) > T(0.0)) - break; + if (plane.SignedDistance(points[i]) < T(0.0)) + return false; } - - if (j == pointCount) - return false; } return true; @@ -378,24 +374,27 @@ namespace Nz template constexpr IntersectionSide Frustum::Intersect(const Vector3* points, std::size_t pointCount) const { - std::size_t c = 0; + IntersectionSide side = IntersectionSide::Inside; for (const auto& plane : m_planes) { - std::size_t j; - for (j = 0; j < pointCount; j++ ) + bool outside = true; + std::size_t insidePoint = 0; + for (std::size_t i = 0; i < pointCount; ++i) { - if (plane.SignedDistance(points[j]) > T(0.0)) - break; + // If at least one point is outside of the frustum, we're intersecting + if (plane.SignedDistance(points[i]) < T(0.0)) + side = IntersectionSide::Intersecting; + else + outside = false; } - if (j == pointCount) + // But if no point is intersecting on this plane, then it's outside + if (outside) return IntersectionSide::Outside; - else - c++; } - return (c == 6) ? IntersectionSide::Inside : IntersectionSide::Intersecting; + return side; } /*! diff --git a/tests/UnitTests/Engine/Math/FrustumTest.cpp b/tests/UnitTests/Engine/Math/FrustumTest.cpp index 0a066bbd0..b48ba5ffb 100644 --- a/tests/UnitTests/Engine/Math/FrustumTest.cpp +++ b/tests/UnitTests/Engine/Math/FrustumTest.cpp @@ -10,12 +10,42 @@ SCENARIO("Frustum", "[MATH][FRUSTUM]") WHEN("We ask for intersection with objects outside the frustum") { + GIVEN("Bounding volumes") + { + Nz::BoundingVolumef bv(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 10.f)); + bv.Update(Nz::Matrix4f::Identity()); + + CHECK_FALSE(frustum.Contains(bv)); + CHECK(frustum.Intersect(bv) == Nz::IntersectionSide::Intersecting); + + bv.Update(Nz::Matrix4f::Translate(Nz::Vector3f::UnitX() * -50.f)); + + CHECK_FALSE(frustum.Contains(bv)); + CHECK(frustum.Intersect(bv) == Nz::IntersectionSide::Outside); + + bv.Update(Nz::Matrix4f::Translate(Nz::Vector3f::UnitX() * 50.f)); + + CHECK(frustum.Contains(bv)); + CHECK(frustum.Intersect(bv) == Nz::IntersectionSide::Inside); + } + + GIVEN("Boxes") + { + Nz::Boxf insideBox(Nz::Vector3f::UnitX() * 50.f, Nz::Vector3f::Unit() * 10.f); + Nz::Boxf intersectingBox(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 10.f); + Nz::Boxf outsideBox(Nz::Vector3f::UnitX() * -50.f, Nz::Vector3f::Unit() * 10.f); + + CHECK(frustum.Contains(insideBox)); + CHECK_FALSE(frustum.Contains(intersectingBox)); + CHECK_FALSE(frustum.Contains(outsideBox)); + + CHECK(frustum.Intersect(insideBox) == Nz::IntersectionSide::Inside); + CHECK(frustum.Intersect(intersectingBox) == Nz::IntersectionSide::Intersecting); + CHECK(frustum.Intersect(outsideBox) == Nz::IntersectionSide::Outside); + } + THEN("These results are expected") { - Nz::BoundingVolumef bv(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit())); - bv.Update(Nz::Matrix4f::Identity()); - REQUIRE(Nz::IntersectionSide::Outside == frustum.Intersect(bv)); - REQUIRE(Nz::IntersectionSide::Outside == frustum.Intersect(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.9f))); Nz::OrientedBoxf obb(Nz::Boxf(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.9f)); obb.Update(Nz::Matrix4f::Identity()); REQUIRE(Nz::IntersectionSide::Outside == frustum.Intersect(obb));