Browse Source

Shapes: (detailed) collision of sphere vs. point.

pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
cf11f7e8fb
  1. 23
      src/Shapes/Sphere.cpp
  2. 7
      src/Shapes/Sphere.h
  3. 29
      src/Shapes/Test/SphereTest.cpp

23
src/Shapes/Sphere.cpp

@ -41,7 +41,28 @@ template<UnsignedInt dimensions> Sphere<dimensions> Sphere<dimensions>::transfor
}
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Point<dimensions>& other) const {
return (other.position()-_position).dot() < Math::pow<2>(_radius);
return (_position - other.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();
/* No collision occured */
if(dot > Math::pow<2>(_radius)) return {};
/* Actual distance from the center */
const Float distance = Math::sqrt(dot);
/* Separating normal. If can't decide on direction, just move up. */
/** @todo How to handle this in a configurable way? */
const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal =
Math::TypeTraits<Float>::equals(dot, 0.0f) ?
DimensionTraits<dimensions, Float>::VectorType::yAxis() :
separating/distance;
/* Collision position is on the point */
return Collision<dimensions>(other.position(), separatingNormal, _radius - distance);
}
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Line<dimensions>& other) const {

7
src/Shapes/Sphere.h

@ -30,6 +30,7 @@
#include "Math/Vector3.h"
#include "DimensionTraits.h"
#include "Shapes/Collision.h"
#include "Shapes/Shapes.h"
#include "Shapes/magnumShapesVisibility.h"
@ -82,6 +83,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Sphere {
/** @brief %Collision occurence with point */
bool operator%(const Point<dimensions>& other) const;
/** @brief %Collision with point */
Collision<dimensions> operator/(const Point<dimensions>& other) const;
/** @brief %Collision occurence with line */
bool operator%(const Line<dimensions>& other) const;
@ -105,6 +109,9 @@ typedef Sphere<3> Sphere3D;
/** @collisionoccurenceoperator{Point,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const Point<dimensions>& a, const Sphere<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(); }
/** @collisionoccurenceoperator{Line,Sphere} */
template<UnsignedInt dimensions> inline bool operator%(const Line<dimensions>& a, const Sphere<dimensions>& b) { return b % a; }

29
src/Shapes/Test/SphereTest.cpp

@ -61,12 +61,29 @@ void SphereTest::transformed() {
}
void SphereTest::collisionPoint() {
Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f);
Shapes::Point3D point({1.0f, 3.0f, 3.0f});
Shapes::Point3D point2({1.0f, 3.0f, 1.0f});
VERIFY_COLLIDES(sphere, point);
VERIFY_NOT_COLLIDES(sphere, point2);
const Shapes::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 2.0f);
/* Collision */
const Shapes::Point3D point({2.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());
/* Collision with ambiguous separation vector */
const Shapes::Point3D point2(sphere.position());
const Shapes::Collision3D collision2 = sphere/point2;
CORRADE_COMPARE(collision2.position(), point2.position());
CORRADE_COMPARE(collision2.separationNormal(), Vector3::yAxis());
CORRADE_COMPARE(collision2.separationDistance(), 2.0f);
/* No collision */
const Shapes::Point3D point3({-1.5f, 2.0f, 3.0f});
CORRADE_VERIFY(!(sphere%point3) && !(sphere/point3));
}
void SphereTest::collisionLine() {

Loading…
Cancel
Save