From 42691fb035c816b5e50b917cbc46d1b09a6583d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 26 Sep 2013 16:41:22 +0200 Subject: [PATCH] Shapes: collision of InvertedSphere and Point. --- .../Implementation/CollisionDispatch.cpp | 4 ++++ src/Shapes/Sphere.cpp | 21 +++++++++++++++++++ src/Shapes/Sphere.h | 12 +++++++++++ src/Shapes/Test/SphereTest.cpp | 21 +++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/src/Shapes/Implementation/CollisionDispatch.cpp b/src/Shapes/Implementation/CollisionDispatch.cpp index d5943d612..8bb0485fc 100644 --- a/src/Shapes/Implementation/CollisionDispatch.cpp +++ b/src/Shapes/Implementation/CollisionDispatch.cpp @@ -48,6 +48,8 @@ template<> bool collides(const AbstractShape<2>& a, const AbstractShape<2>& b) { _c(Sphere, Sphere2D, LineSegment, LineSegment2D) _c(Sphere, Sphere2D, Sphere, Sphere2D) + _c(InvertedSphere, InvertedSphere2D, Point, Point2D) + _c(Cylinder, Cylinder2D, Point, Point2D) _c(Cylinder, Cylinder2D, Sphere, Sphere2D) @@ -73,6 +75,8 @@ template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) { _c(Sphere, Sphere3D, LineSegment, LineSegment3D) _c(Sphere, Sphere3D, Sphere, Sphere3D) + _c(InvertedSphere, InvertedSphere3D, Point, Point3D) + _c(Cylinder, Cylinder3D, Point, Point3D) _c(Cylinder, Cylinder3D, Sphere, Sphere3D) diff --git a/src/Shapes/Sphere.cpp b/src/Shapes/Sphere.cpp index dd3668172..70c27347d 100644 --- a/src/Shapes/Sphere.cpp +++ b/src/Shapes/Sphere.cpp @@ -44,6 +44,10 @@ template bool Sphere::operator%(const Point< return (_position - other.position()).dot() < Math::pow<2>(_radius); } +template bool InvertedSphere::operator%(const Point& other) const { + return (other.position() - position()).dot() > Math::pow<2>(radius()); +} + template Collision Sphere::operator/(const Point& other) const { const typename DimensionTraits::VectorType separating = _position - other.position(); const Float dot = separating.dot(); @@ -65,6 +69,23 @@ template Collision Sphere::opera return Collision(other.position(), separatingNormal, _radius - distance); } +template Collision InvertedSphere::operator/(const Point& other) const { + const typename DimensionTraits::VectorType separating = other.position() - position(); + const Float dot = separating.dot(); + + /* No collision occured */ + if(dot < Math::pow<2>(radius())) return {}; + + /* Actual distance from the center */ + const Float distance = Math::sqrt(dot); + + /* Separating normal */ + const typename DimensionTraits::VectorType separatingNormal = separating/distance; + + /* Collision position is on the point */ + return Collision(other.position(), separatingNormal, distance - radius()); +} + template bool Sphere::operator%(const Line& other) const { return Distance::linePointSquared(other.a(), other.b(), _position) < Math::pow<2>(_radius); } diff --git a/src/Shapes/Sphere.h b/src/Shapes/Sphere.h index 8d0bbc346..6f85fe2fd 100644 --- a/src/Shapes/Sphere.h +++ b/src/Shapes/Sphere.h @@ -146,6 +146,12 @@ template class MAGNUM_SHAPES_EXPORT InvertedSphere: using Sphere::radius; using Sphere::setRadius; + /** @brief %Collision occurence with point */ + bool operator%(const Point& other) const; + + /** @brief %Collision with point */ + Collision operator/(const Point& other) const; + private: constexpr /*implicit*/ InvertedSphere(const Sphere& other): Sphere(other) {} }; @@ -159,9 +165,15 @@ typedef InvertedSphere<3> InvertedSphere3D; /** @collisionoccurenceoperator{Point,Sphere} */ template inline bool operator%(const Point& a, const Sphere& b) { return b % a; } +/** @collisionoccurenceoperator{Point,InvertedSphere} */ +template inline bool operator%(const Point& a, const InvertedSphere& b) { return b % a; } + /** @collisionoperator{Point,Sphere} */ template inline Collision operator/(const Point& a, const Sphere& b) { return (b/a).flipped(); } +/** @collisionoperator{Point,InvertedSphere} */ +template inline Collision operator/(const Point& a, const InvertedSphere& b) { return (b/a).flipped(); } + /** @collisionoccurenceoperator{Line,Sphere} */ template inline bool operator%(const Line& a, const Sphere& b) { return b % a; } diff --git a/src/Shapes/Test/SphereTest.cpp b/src/Shapes/Test/SphereTest.cpp index 773cccccc..b2d923d23 100644 --- a/src/Shapes/Test/SphereTest.cpp +++ b/src/Shapes/Test/SphereTest.cpp @@ -39,6 +39,7 @@ class SphereTest: public TestSuite::Tester { void transformed(); void collisionPoint(); + void collisionPointInverted(); void collisionLine(); void collisionLineSegment(); void collisionSphere(); @@ -47,6 +48,7 @@ class SphereTest: public TestSuite::Tester { SphereTest::SphereTest() { addTests({&SphereTest::transformed, &SphereTest::collisionPoint, + &SphereTest::collisionPointInverted, &SphereTest::collisionLine, &SphereTest::collisionLineSegment, &SphereTest::collisionSphere}); @@ -86,6 +88,25 @@ void SphereTest::collisionPoint() { CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3)); } +void SphereTest::collisionPointInverted() { + const Shapes::InvertedSphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); + + /* Collision */ + const Shapes::Point3D point({-1.5f, 2.0f, 3.0f}); + const Shapes::Collision3D collision = sphere/point; + CORRADE_VERIFY(sphere%point && point%sphere); + CORRADE_COMPARE(collision.position(), point.position()); + CORRADE_COMPARE(collision.separationNormal(), -Vector3::xAxis()); + CORRADE_COMPARE(collision.separationDistance(), 0.5f); + + /* Collision, flipped */ + CORRADE_COMPARE(collision.separationNormal(), -(point/sphere).separationNormal()); + + /* No collision */ + const Shapes::Point3D point3({2.0f, 2.0f, 3.0f}); + CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3)); +} + void SphereTest::collisionLine() { Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f); Shapes::Line3D line({1.0f, 1.5f, 3.5f}, {1.0f, 2.5f, 2.5f});