Skip to content

Commit

Permalink
Math: Fix Math::Intersection::pointFrustum
Browse files Browse the repository at this point in the history
Signed-off-by: Squareys <[email protected]>
  • Loading branch information
Squareys committed Nov 17, 2020
1 parent 6f1f50d commit 1dbe8ab
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
6 changes: 2 additions & 4 deletions src/Magnum/Math/Intersection.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ template<class T> bool aabbFrustum(const Vector3<T>& aabbCenter, const Vector3<T
Checks for each plane of the frustum whether the sphere is behind the plane
(the points distance larger than the sphere's radius) using
@ref Distance::pointPlaneScaled().
*/
template<class T> bool sphereFrustum(const Vector3<T>& sphereCenter, T sphereRadius, const Frustum<T>& frustum);
Expand Down Expand Up @@ -441,19 +442,16 @@ template<class T> bool aabbFrustum(const Vector3<T>& aabbCenter, const Vector3<T
}

template<class T> bool sphereFrustum(const Vector3<T>& sphereCenter, const T sphereRadius, const Frustum<T>& frustum) {
const T radiusSq = sphereRadius*sphereRadius;

for(const Vector4<T>& plane: frustum) {
/* The sphere is in front of one of the frustum planes (normals point
outwards) */
if(Distance::pointPlaneScaled<T>(sphereCenter, plane) < -radiusSq)
if(Distance::pointPlane<T>(sphereCenter, plane) >= sphereRadius)
return false;
}

return true;
}


template<class T> bool pointCone(const Vector3<T>& point, const Vector3<T>& coneOrigin, const Vector3<T>& coneNormal, const Rad<T> coneAngle) {
const T tanAngleSqPlusOne = Math::pow<2>(Math::tan(coneAngle*T(0.5))) + T(1);
return pointCone(point, coneOrigin, coneNormal, tanAngleSqPlusOne);
Expand Down
24 changes: 20 additions & 4 deletions src/Magnum/Math/Test/DistanceTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,26 @@ void DistanceTest::lineSegmentPoint3D() {
}

void DistanceTest::pointPlane() {
Vector3 point{0.0f, 0.0f, 0.0f};
Vector4 plane{3.0f, 0.0f, 4.0f, 5.0f};

CORRADE_COMPARE(Distance::pointPlane(point, plane), 1.0f);
{
Vector4 plane{3.0f, 0.0f, 4.0f, 5.0f};
CORRADE_COMPARE(Distance::pointPlane({}, plane), 1.0f);
}
{
/* Origin plane with normal {0, 1, 0} */
Vector4 plane{0.0f, 1.0f, 0.0f, 0.0f};
/* Point lies in front of plane, 2 units away */
CORRADE_COMPARE(Distance::pointPlane({0.0f, 2.0f, 0.0f}, plane), 2.0f);
/* Point lies in begind the plane, 2 units away */
CORRADE_COMPARE(Distance::pointPlane({0.0f, -2.0f, 0.0f}, plane), -2.0f);
}
{
/* Origin plane offset by 1 normal with normal {0, 1, 0} */
Vector4 plane{0.0f, 1.0f, 0.0f, -1.0f};
/* Point lies in front of plane, 2 units away */
CORRADE_COMPARE(Distance::pointPlane({0.0f, 2.0f, 0.0f}, plane), 1.0f);
/* Point lies in begind the plane, 2 units away */
CORRADE_COMPARE(Distance::pointPlane({0.0f, -2.0f, 0.0f}, plane), -3.0f);
}
}

void DistanceTest::pointPlaneScaled() {
Expand Down
56 changes: 43 additions & 13 deletions src/Magnum/Math/Test/IntersectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,12 @@ void IntersectionTest::rangeFrustum() {

void IntersectionTest::aabbFrustum() {
const Frustum frustum{
{1.0f, 0.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f, 5.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, -1.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 10.0f}};
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 10.0f},
{0.0f, 0.0f, 1.0f, 0.0f}};

/* Fully inside */
CORRADE_VERIFY(Intersection::aabbFrustum(Vector3{0.0f}, Vector3{1.0f}, frustum));
Expand All @@ -204,20 +204,50 @@ void IntersectionTest::aabbFrustum() {
}

void IntersectionTest::sphereFrustum() {
/* Frustum spanning [(-10, -10, -10), (0, 0, 0)] */
const Frustum frustum{
{-1.0f, 0.0f, 0.0f, -10.0f},
{1.0f, 0.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f, 10.0f},
{0.0f, -0.5f, 0.0f, -5.0f}, /* Intentionally not normalized */
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, -1.0f, 0.0f, 10.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 10.0f}};

/* Sphere on edge */
CORRADE_VERIFY(Intersection::sphereFrustum({0.0f, 0.0f, -1.0f}, 1.5f, frustum));
{0.0f, 0.0f, -2.0f, -20.0f}}; /* Intentionally not normalized */

/* Sphere overlapping each face by 0.5 */
CORRADE_VERIFY(Intersection::sphereFrustum({ 1.0f, 0.0f, 0.0f}, 1.5f, frustum));
CORRADE_VERIFY(Intersection::sphereFrustum({-11.0f, 0.0f, 0.0f}, 1.5f, frustum));
CORRADE_VERIFY(Intersection::sphereFrustum({ 0.0f, 1.0f, 0.0f}, 1.5f, frustum));
CORRADE_VERIFY(Intersection::sphereFrustum({ 0.0f,-11.0f, 0.0f}, 1.5f, frustum));
CORRADE_VERIFY(Intersection::sphereFrustum({ 0.0f, 0.0f, 1.0f}, 1.5f, frustum));
CORRADE_VERIFY(Intersection::sphereFrustum({ 0.0f, 0.0f,-11.0f}, 1.5f, frustum));
/* Sphere touching each face */
CORRADE_VERIFY(!Intersection::sphereFrustum({ 1.0f, 0.0f, 0.0f}, 1.0f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({-11.0f, 0.0f, 0.0f}, 1.0f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f, 1.0f, 0.0f}, 1.0f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f,-11.0f, 0.0f}, 1.0f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f, 0.0f, 1.0f}, 1.0f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f, 0.0f,-11.0f}, 1.0f, frustum));
/* Sphere inside */
CORRADE_VERIFY(Intersection::sphereFrustum({5.5f, 5.5f, 5.5f}, 1.5f, frustum));
/* Sphere outside */
CORRADE_VERIFY(!Intersection::sphereFrustum({0.0f, 0.0f, 100.0f}, 0.5f, frustum));
CORRADE_VERIFY(Intersection::sphereFrustum({-1.0f, -2.0f, -3.0f}, 1.5f, frustum));
/* Sphere outside each face */
CORRADE_VERIFY(!Intersection::sphereFrustum({ 1.0f, 0.0f, 0.0f}, 0.5f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({-11.0f, 0.0f, 0.0f}, 0.5f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f, 1.0f, 0.0f}, 0.5f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f,-11.0f, 0.0f}, 0.5f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f, 0.0f, 1.0f}, 0.5f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({ 0.0f, 0.0f,-11.0f}, 0.5f, frustum));

/* Some "Corner" cases, sphere touching corner, but shouldn't intersect */
CORRADE_VERIFY(!Intersection::sphereFrustum({1.1f, 1.1f, 1.1f}, 1.1f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({-11.1f, -11.1f, -11.1f}, 1.1f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({1.1f, -11.1f, 1.1f}, 1.1f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({-11.1f, 1.1f, -11.1f}, 1.1f, frustum));

CORRADE_VERIFY(!Intersection::sphereFrustum({-11.1f, 1.1f, 1.1f}, 1.1f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({1.1f, -11.1f, -11.1f}, 1.1f, frustum));

CORRADE_VERIFY(!Intersection::sphereFrustum({1.1f, 1.1f, -11.1f}, 1.1f, frustum));
CORRADE_VERIFY(!Intersection::sphereFrustum({-11.1f, -11.1f, 1.1f}, 1.1f, frustum));
}

void IntersectionTest::pointCone() {
Expand Down

0 comments on commit 1dbe8ab

Please sign in to comment.