diff --git a/src/Magnum/Math/Intersection.h b/src/Magnum/Math/Intersection.h index 7489699838..f069e793b2 100644 --- a/src/Magnum/Math/Intersection.h +++ b/src/Magnum/Math/Intersection.h @@ -193,6 +193,7 @@ template bool aabbFrustum(const Vector3& aabbCenter, const Vector3 bool sphereFrustum(const Vector3& sphereCenter, T sphereRadius, const Frustum& frustum); @@ -441,19 +442,16 @@ template bool aabbFrustum(const Vector3& aabbCenter, const Vector3 bool sphereFrustum(const Vector3& sphereCenter, const T sphereRadius, const Frustum& frustum) { - const T radiusSq = sphereRadius*sphereRadius; - for(const Vector4& plane: frustum) { /* The sphere is in front of one of the frustum planes (normals point outwards) */ - if(Distance::pointPlaneScaled(sphereCenter, plane) < -radiusSq) + if(Distance::pointPlane(sphereCenter, plane) >= sphereRadius) return false; } return true; } - template bool pointCone(const Vector3& point, const Vector3& coneOrigin, const Vector3& coneNormal, const Rad coneAngle) { const T tanAngleSqPlusOne = Math::pow<2>(Math::tan(coneAngle*T(0.5))) + T(1); return pointCone(point, coneOrigin, coneNormal, tanAngleSqPlusOne); diff --git a/src/Magnum/Math/Test/DistanceTest.cpp b/src/Magnum/Math/Test/DistanceTest.cpp index 3430eed7d5..e501c40f80 100644 --- a/src/Magnum/Math/Test/DistanceTest.cpp +++ b/src/Magnum/Math/Test/DistanceTest.cpp @@ -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() { diff --git a/src/Magnum/Math/Test/IntersectionTest.cpp b/src/Magnum/Math/Test/IntersectionTest.cpp index 98b3b4818c..865a5d7960 100644 --- a/src/Magnum/Math/Test/IntersectionTest.cpp +++ b/src/Magnum/Math/Test/IntersectionTest.cpp @@ -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)); @@ -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() {