|
|
|
|
@ -26,6 +26,7 @@
|
|
|
|
|
DEALINGS IN THE SOFTWARE. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <Corrade/Containers/ArrayView.h> |
|
|
|
|
#include <Corrade/Containers/String.h> |
|
|
|
|
#include <Corrade/TestSuite/Tester.h> |
|
|
|
|
|
|
|
|
|
@ -53,6 +54,7 @@ struct IntersectionTest: TestSuite::Tester {
|
|
|
|
|
void pointCone(); |
|
|
|
|
void pointDoubleCone(); |
|
|
|
|
void sphereCone(); |
|
|
|
|
template<class T> void sphereConeNearApex(); |
|
|
|
|
void sphereConeView(); |
|
|
|
|
void sphereConeViewNotRigid(); |
|
|
|
|
void rangeCone(); |
|
|
|
|
@ -68,6 +70,25 @@ using Magnum::Constants;
|
|
|
|
|
using Magnum::Range3D; |
|
|
|
|
using Magnum::Rad; |
|
|
|
|
|
|
|
|
|
constexpr struct { |
|
|
|
|
const char* name; |
|
|
|
|
Float angle; |
|
|
|
|
Vector3 center; |
|
|
|
|
Float radius; |
|
|
|
|
bool intersects; |
|
|
|
|
} SphereConeNearApexData[]{ |
|
|
|
|
{"wide cone, beside apex", 120.0f, {1.5f, 0.0f, 0.0f}, 1.0f, true}, |
|
|
|
|
{"wide cone, behind apex", 120.0f, {1.1f, 0.0f, -0.2f}, 1.0f, true}, |
|
|
|
|
{"wide cone, in front of apex", 120.0f, {1.5f, 0.0f, 0.2f}, 1.0f, true}, |
|
|
|
|
{"narrow cone, beside apex", 60.0f, {1.1f, 0.0f, 0.0f}, 1.0f, true}, |
|
|
|
|
{"outside side", 120.0f, {2.5f, 0.0f, 0.0f}, 1.0f, false}, |
|
|
|
|
{"outside behind apex", 120.0f, {0.0f, 0.0f, -1.5f}, 1.0f, false}, |
|
|
|
|
{"contains apex", 120.0f, {0.0f, 0.0f, -0.5f}, 1.0f, true}, |
|
|
|
|
{"touches apex", 120.0f, {0.0f, 0.0f, -1.0f}, 1.0f, true}, |
|
|
|
|
{"inside cone", 120.0f, {0.0f, 0.0f, 3.0f}, 1.0f, true}, |
|
|
|
|
{"zero radius outside", 120.0f, {1.0f, 0.0f, 0.0f}, 0.0f, false} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
IntersectionTest::IntersectionTest() { |
|
|
|
|
addTests({&IntersectionTest::pointCircle, |
|
|
|
|
&IntersectionTest::pointSphere, |
|
|
|
|
@ -88,6 +109,10 @@ IntersectionTest::IntersectionTest() {
|
|
|
|
|
&IntersectionTest::sphereConeViewNotRigid, |
|
|
|
|
&IntersectionTest::rangeCone, |
|
|
|
|
&IntersectionTest::aabbCone}); |
|
|
|
|
|
|
|
|
|
addInstancedTests<IntersectionTest>({&IntersectionTest::sphereConeNearApex<Float>, |
|
|
|
|
&IntersectionTest::sphereConeNearApex<Double>}, |
|
|
|
|
Containers::arraySize(SphereConeNearApexData)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void IntersectionTest::pointCircle() { |
|
|
|
|
@ -407,6 +432,44 @@ void IntersectionTest::sphereCone() {
|
|
|
|
|
CORRADE_VERIFY(!Intersection::sphereCone(center - 4.0f*surface, 0.5f, center, normal, angle)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<class T> void IntersectionTest::sphereConeNearApex() { |
|
|
|
|
auto&& data = SphereConeNearApexData[testCaseInstanceId()]; |
|
|
|
|
setTestCaseDescription(data.name); |
|
|
|
|
setTestCaseTemplateName(TypeTraits<T>::name()); |
|
|
|
|
|
|
|
|
|
const Math::Vector3<T> sphereCenter{data.center}; |
|
|
|
|
const T radius = T(data.radius); |
|
|
|
|
const Math::Rad<T> angle{Math::Deg<T>{T(data.angle)}}; |
|
|
|
|
const T sinAngle = Math::sin(angle/T(2)); |
|
|
|
|
const T tanAngle = Math::tan(angle/T(2)); |
|
|
|
|
const Math::Vector3<T> normal = Math::Vector3<T>::zAxis(); |
|
|
|
|
|
|
|
|
|
/* A sphere beside the apex can intersect the cone's side without
|
|
|
|
|
containing the apex. For example, at (1.5, 0, 0) the distance to the |
|
|
|
|
side of a 120-degree cone is 1.5*cos(60 degrees) = 0.75. */ |
|
|
|
|
CORRADE_COMPARE(Intersection::sphereCone(sphereCenter, radius, |
|
|
|
|
Math::Vector3<T>{}, normal, angle), data.intersects); |
|
|
|
|
CORRADE_COMPARE(Intersection::sphereCone(sphereCenter, radius, |
|
|
|
|
Math::Vector3<T>{}, normal, sinAngle, T(1) + tanAngle*tanAngle), data.intersects); |
|
|
|
|
|
|
|
|
|
/* The view-based overload should agree, also after rotating and
|
|
|
|
|
translating the cone and the sphere together. */ |
|
|
|
|
const Math::Vector3<T> origin{T(1), T(-2), T(3)}; |
|
|
|
|
const Math::Vector3<T> rotatedNormal = Math::Vector3<T>::yAxis(); |
|
|
|
|
const Math::Vector3<T> transformedCenter = origin + |
|
|
|
|
Math::Vector3<T>{sphereCenter.x(), sphereCenter.z(), -sphereCenter.y()}; |
|
|
|
|
const Math::Matrix4<T> view = Math::Matrix4<T>::lookAt(origin, |
|
|
|
|
origin + rotatedNormal, Math::Vector3<T>::zAxis()).invertedRigid(); |
|
|
|
|
CORRADE_COMPARE(Intersection::sphereCone(transformedCenter, radius, |
|
|
|
|
origin, rotatedNormal, angle), data.intersects); |
|
|
|
|
CORRADE_COMPARE(Intersection::sphereCone(transformedCenter, radius, |
|
|
|
|
origin, rotatedNormal, sinAngle, T(1) + tanAngle*tanAngle), data.intersects); |
|
|
|
|
CORRADE_COMPARE(Intersection::sphereConeView(transformedCenter, radius, |
|
|
|
|
view, angle), data.intersects); |
|
|
|
|
CORRADE_COMPARE(Intersection::sphereConeView(transformedCenter, radius, |
|
|
|
|
view, sinAngle, tanAngle), data.intersects); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void IntersectionTest::sphereConeView() { |
|
|
|
|
const Vector3 center{1.0f, -2.0f, 1.3f}; |
|
|
|
|
const Vector3 normal{Vector3{0.5f, 1.0f, 2.0f}.normalized()}; |
|
|
|
|
|