Browse Source

Shapes: collision of InvertedSphere and Point.

pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
42691fb035
  1. 4
      src/Shapes/Implementation/CollisionDispatch.cpp
  2. 21
      src/Shapes/Sphere.cpp
  3. 12
      src/Shapes/Sphere.h
  4. 21
      src/Shapes/Test/SphereTest.cpp

4
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)

21
src/Shapes/Sphere.cpp

@ -44,6 +44,10 @@ template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Point<
return (_position - other.position()).dot() < Math::pow<2>(_radius);
}
template<UnsignedInt dimensions> bool InvertedSphere<dimensions>::operator%(const Point<dimensions>& other) const {
return (other.position() - position()).dot() > Math::pow<2>(radius());
}
template<UnsignedInt dimensions> Collision<dimensions> Sphere<dimensions>::operator/(const Point<dimensions>& other) const {
const typename DimensionTraits<dimensions, Float>::VectorType separating = _position - other.position();
const Float dot = separating.dot();
@ -65,6 +69,23 @@ template<UnsignedInt dimensions> Collision<dimensions> Sphere<dimensions>::opera
return Collision<dimensions>(other.position(), separatingNormal, _radius - distance);
}
template<UnsignedInt dimensions> Collision<dimensions> InvertedSphere<dimensions>::operator/(const Point<dimensions>& other) const {
const typename DimensionTraits<dimensions, Float>::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<dimensions, Float>::VectorType separatingNormal = separating/distance;
/* Collision position is on the point */
return Collision<dimensions>(other.position(), separatingNormal, distance - radius());
}
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Line<dimensions>& other) const {
return Distance::linePointSquared(other.a(), other.b(), _position) < Math::pow<2>(_radius);
}

12
src/Shapes/Sphere.h

@ -146,6 +146,12 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT InvertedSphere:
using Sphere<dimensions>::radius;
using Sphere<dimensions>::setRadius;
/** @brief %Collision occurence with point */
bool operator%(const Point<dimensions>& other) const;
/** @brief %Collision with point */
Collision<dimensions> operator/(const Point<dimensions>& other) const;
private:
constexpr /*implicit*/ InvertedSphere(const Sphere<dimensions>& other): Sphere<dimensions>(other) {}
};
@ -159,9 +165,15 @@ typedef InvertedSphere<3> InvertedSphere3D;
/** @collisionoccurenceoperator{Point,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const Point<dimensions>& a, const Sphere<dimensions>& b) { return b % a; }
/** @collisionoccurenceoperator{Point,InvertedSphere} */
template<UnsignedInt dimensions> inline bool operator%(const Point<dimensions>& a, const InvertedSphere<dimensions>& b) { return b % a; }
/** @collisionoperator{Point,Sphere} */
template<UnsignedInt dimensions> inline Collision<dimensions> operator/(const Point<dimensions>& a, const Sphere<dimensions>& b) { return (b/a).flipped(); }
/** @collisionoperator{Point,InvertedSphere} */
template<UnsignedInt dimensions> inline Collision<dimensions> operator/(const Point<dimensions>& a, const InvertedSphere<dimensions>& b) { return (b/a).flipped(); }
/** @collisionoccurenceoperator{Line,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const Line<dimensions>& a, const Sphere<dimensions>& b) { return b % a; }

21
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});

Loading…
Cancel
Save