Math/Frustum: Fix Contains(Box) and Intersect(points, n)

This commit is contained in:
SirLynix 2023-06-25 09:50:10 +02:00
parent 4494249dc1
commit 161c4f6aca
2 changed files with 50 additions and 21 deletions

View File

@ -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<typename T>
constexpr IntersectionSide Frustum<T>::Intersect(const Vector3<T>* 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;
}
/*!

View File

@ -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));