Browse Source

Physics shape rework #1: simplified implementation of base shapes.

Currently only the tests for particular shapes work, everything else is
broken.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
b29f736363
  1. 83
      src/Physics/AbstractShape.cpp
  2. 146
      src/Physics/AbstractShape.h
  3. 17
      src/Physics/AxisAlignedBox.cpp
  4. 43
      src/Physics/AxisAlignedBox.h
  5. 6
      src/Physics/Box.cpp
  6. 32
      src/Physics/Box.h
  7. 30
      src/Physics/Capsule.cpp
  8. 60
      src/Physics/Capsule.h
  9. 6
      src/Physics/Line.cpp
  10. 47
      src/Physics/Line.h
  11. 12
      src/Physics/LineSegment.h
  12. 21
      src/Physics/Plane.cpp
  13. 45
      src/Physics/Plane.h
  14. 4
      src/Physics/Point.cpp
  15. 31
      src/Physics/Point.h
  16. 37
      src/Physics/Sphere.cpp
  17. 45
      src/Physics/Sphere.h
  18. 24
      src/Physics/Test/AxisAlignedBoxTest.cpp
  19. 14
      src/Physics/Test/BoxTest.cpp
  20. 35
      src/Physics/Test/CapsuleTest.cpp
  21. 15
      src/Physics/Test/LineTest.cpp
  22. 33
      src/Physics/Test/PlaneTest.cpp
  23. 13
      src/Physics/Test/PointTest.cpp
  24. 18
      src/Physics/Test/ShapeTestBase.h
  25. 44
      src/Physics/Test/SphereTest.cpp

83
src/Physics/AbstractShape.cpp

@ -1,83 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "AbstractShape.h"
#include <Utility/Debug.h>
namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> bool AbstractShape<dimensions>::collides(const AbstractShape* other) const {
/* Operate only with simpler types than this */
if(static_cast<int>(other->type()) > static_cast<int>(type()))
return other->collides(this);
return false;
}
template class AbstractShape<2>;
template class AbstractShape<3>;
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
Debug operator<<(Debug debug, ShapeDimensionTraits<2>::Type value) {
switch(value) {
#define _val(value) case AbstractShape2D::Type::value: return debug << "AbstractShape2D::Type::" #value;
_val(Point)
_val(Line)
_val(LineSegment)
_val(Sphere)
_val(Capsule)
_val(AxisAlignedBox)
_val(Box)
_val(ShapeGroup)
#undef _val
}
return debug << "AbstractShape2D::Type::(unknown)";
}
Debug operator<<(Debug debug, ShapeDimensionTraits<3>::Type value) {
switch(value) {
#define _val(value) case AbstractShape3D::Type::value: return debug << "AbstractShape3D::Type::" #value;
_val(Point)
_val(Line)
_val(LineSegment)
_val(Sphere)
_val(Capsule)
_val(AxisAlignedBox)
_val(Box)
_val(ShapeGroup)
_val(Plane)
#undef _val
}
return debug << "AbstractShape2D::Type::(unknown)";
}
}
#endif
}}

146
src/Physics/AbstractShape.h

@ -1,146 +0,0 @@
#ifndef Magnum_Physics_AbstractShape_h
#define Magnum_Physics_AbstractShape_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class Magnum::Physics::AbstractShape, typedef Magnum::Physics::AbstractShape2D, Magnum::Physics::AbstractShape3D
*/
#include "Magnum.h"
#include "DimensionTraits.h"
#include "magnumPhysicsVisibility.h"
namespace Magnum { namespace Physics {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
template<UnsignedInt dimensions> struct ShapeDimensionTraits {};
template<> struct ShapeDimensionTraits<2> {
enum class Type {
Point,
Line,
LineSegment,
Sphere,
Capsule,
AxisAlignedBox,
Box,
ShapeGroup
};
};
template<> struct ShapeDimensionTraits<3> {
enum class Type {
Point,
Line,
LineSegment,
Sphere,
Capsule,
AxisAlignedBox,
Box,
ShapeGroup,
Plane
};
};
Debug MAGNUM_PHYSICS_EXPORT operator<<(Debug debug, ShapeDimensionTraits<2>::Type value);
Debug MAGNUM_PHYSICS_EXPORT operator<<(Debug debug, ShapeDimensionTraits<3>::Type value);
}
#endif
/**
@brief Base class for shapes
See @ref collision-detection for brief introduction.
@see AbstractShape2D, AbstractShape3D
*/
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT AbstractShape {
public:
/** @brief Dimension count */
static const UnsignedInt Dimensions = dimensions;
/**
* @brief Shape type
*
* @internal Sorted by complexity, so the shape which is later in
* the list provides collision detection for previous shapes, not
* the other way around.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
enum class Type {
Point, /**< Point */
Line, /**< Line */
LineSegment, /**< @ref LineSegment "Line segment" */
Sphere, /**< Sphere */
Capsule, /**< Capsule */
AxisAlignedBox, /**< @ref AxisAlignedBox "Axis aligned box" */
Box, /**< Box */
ShapeGroup, /**< @ref ShapeGroup "Shape group" */
Plane /**< Plane (3D only) */
};
#else
typedef typename Implementation::ShapeDimensionTraits<dimensions>::Type Type;
#endif
explicit AbstractShape() = default;
virtual inline ~AbstractShape() {}
/** @brief Shape type */
virtual Type type() const = 0;
/**
* @brief Apply transformation matrix
*
* Applies transformation matrix to user-defined shape properties and
* caches them for later usage in collision detection.
*/
virtual void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) = 0;
/**
* @brief Detect collision with other shape
*
* Default implementation returns false.
*
* @internal If other shape is more complex than this, returns
* `other->collides(this)`.
*/
virtual bool collides(const AbstractShape<dimensions>* other) const;
};
/** @brief Abstract two-dimensional shape */
typedef AbstractShape<2> AbstractShape2D;
/** @brief Abstract three-dimensional shape */
typedef AbstractShape<3> AbstractShape3D;
#ifdef DOXYGEN_GENERATING_OUTPUT
/** @debugoperator{Magnum::Physics::AbstractShape} */
template<UnsignedInt dimensions> Debug operator<<(Debug debug, typename AbstractShape<dimensions>::Type value);
#endif
}}
#endif

17
src/Physics/AxisAlignedBox.cpp

@ -30,21 +30,14 @@
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> void AxisAlignedBox<dimensions>::applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) { template<UnsignedInt dimensions> AxisAlignedBox<dimensions> AxisAlignedBox<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
_transformedMin = matrix.transformPoint(_min); return AxisAlignedBox<dimensions>(matrix.transformPoint(_min),
_transformedMax = matrix.transformPoint(_max); matrix.transformPoint(_max));
}
template<UnsignedInt dimensions> bool AxisAlignedBox<dimensions>::collides(const AbstractShape<dimensions>* other) const {
if(other->type() == AbstractShape<dimensions>::Type::Point)
return *this % *static_cast<const Point<dimensions>*>(other);
return AbstractShape<dimensions>::collides(other);
} }
template<UnsignedInt dimensions> bool AxisAlignedBox<dimensions>::operator%(const Point<dimensions>& other) const { template<UnsignedInt dimensions> bool AxisAlignedBox<dimensions>::operator%(const Point<dimensions>& other) const {
return (other.transformedPosition() >= _transformedMin).all() && return (other.position() >= _min).all() &&
(other.transformedPosition() < _transformedMax).all(); (other.position() < _max).all();
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT

43
src/Physics/AxisAlignedBox.h

@ -29,10 +29,9 @@
*/ */
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "Physics/AbstractShape.h" #include "DimensionTraits.h"
#include "Physics/Physics.h" #include "Physics/Physics.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
@ -44,28 +43,27 @@ radius.
@see AxisAlignedBox2D, AxisAlignedBox3D @see AxisAlignedBox2D, AxisAlignedBox3D
@todo Assert for rotation @todo Assert for rotation
*/ */
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT AxisAlignedBox: public AbstractShape<dimensions> { template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT AxisAlignedBox {
public: public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Creates zero sized box positioned at origin. * Creates zero sized box positioned at origin.
*/ */
inline explicit AxisAlignedBox() {} inline constexpr explicit AxisAlignedBox() {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit AxisAlignedBox(const typename DimensionTraits<dimensions>::VectorType& min, const typename DimensionTraits<dimensions>::VectorType& max): _min(min), _max(max), _transformedMin(min), _transformedMax(max) {} inline constexpr explicit AxisAlignedBox(const typename DimensionTraits<dimensions>::VectorType& min, const typename DimensionTraits<dimensions>::VectorType& max): _min(min), _max(max) {}
inline typename AbstractShape<dimensions>::Type type() const override {
return AbstractShape<dimensions>::Type::AxisAlignedBox;
}
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override;
bool collides(const AbstractShape<dimensions>* other) const override; /** @brief Transformed shape */
AxisAlignedBox<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const;
/** @brief Minimal coordinates */ /** @brief Minimal coordinates */
inline typename DimensionTraits<dimensions>::VectorType min() const { inline constexpr typename DimensionTraits<dimensions>::VectorType min() const {
return _min; return _min;
} }
@ -75,29 +73,20 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT AxisAlignedBox: pub
} }
/** @brief Maximal coordinates */ /** @brief Maximal coordinates */
inline typename DimensionTraits<dimensions>::VectorType max() const { return _max; } inline constexpr typename DimensionTraits<dimensions>::VectorType max() const {
return _max;
}
/** @brief Set maximal coordinates */ /** @brief Set maximal coordinates */
inline void setMax(const typename DimensionTraits<dimensions>::VectorType& max) { inline void setMax(const typename DimensionTraits<dimensions>::VectorType& max) {
_max = max; _max = max;
} }
/** @brief Transformed minimal coordinates */
inline typename DimensionTraits<dimensions>::VectorType transformedMin() const {
return _transformedMin;
}
/** @brief Transformed maximal coordinates */
inline typename DimensionTraits<dimensions>::VectorType transformedMax() const {
return _transformedMax;
}
/** @brief Collision with point */ /** @brief Collision with point */
bool operator%(const Point<dimensions>& other) const; bool operator%(const Point<dimensions>& other) const;
private: private:
typename DimensionTraits<dimensions>::VectorType _min, _max, typename DimensionTraits<dimensions>::VectorType _min, _max;
_transformedMin, _transformedMax;
}; };
/** @brief Two-dimensional axis-aligned box */ /** @brief Two-dimensional axis-aligned box */

6
src/Physics/Box.cpp

@ -24,12 +24,10 @@
#include "Box.h" #include "Box.h"
#include "Math/Matrix4.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> void Box<dimensions>::applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) { template<UnsignedInt dimensions> Box<dimensions> Box<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
_transformedTransformation = matrix*_transformation; return Box<dimensions>(matrix*_transformation);
} }
template class Box<2>; template class Box<2>;

32
src/Physics/Box.h

@ -30,9 +30,8 @@
#include "Math/Matrix3.h" #include "Math/Matrix3.h"
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "AbstractShape.h" #include "DimensionTraits.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
@ -45,26 +44,27 @@ radius.
@see Box2D, Box3D @see Box2D, Box3D
@todo Assert for skew @todo Assert for skew
*/ */
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Box: public AbstractShape<dimensions> { template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Box {
public: public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Creates zero-sized box positioned at origin. * Creates zero-sized box positioned at origin.
*/ */
inline explicit Box(): _transformation(DimensionTraits<dimensions>::MatrixType::Zero), _transformedTransformation(DimensionTraits<dimensions>::MatrixType::Zero) {} inline constexpr explicit Box(): _transformation(DimensionTraits<dimensions>::MatrixType::Zero) {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit Box(const typename DimensionTraits<dimensions>::MatrixType& transformation): _transformation(transformation), _transformedTransformation(transformation) {} inline constexpr explicit Box(const typename DimensionTraits<dimensions>::MatrixType& transformation): _transformation(transformation) {}
inline typename AbstractShape<dimensions>::Type type() const override {
return AbstractShape<dimensions>::Type::Box;
}
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override; /** @brief Transformed shape */
Box<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const;
/** @brief Transformation */ /** @brief Transformation */
inline typename DimensionTraits<dimensions>::MatrixType transformation() const { inline constexpr typename DimensionTraits<dimensions>::MatrixType transformation() const {
return _transformation; return _transformation;
} }
@ -73,14 +73,8 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Box: public Abstrac
_transformation = transformation; _transformation = transformation;
} }
/** @brief Transformed transformation */
inline typename DimensionTraits<dimensions>::MatrixType transformedTransformation() const {
return _transformedTransformation;
}
private: private:
typename DimensionTraits<dimensions>::MatrixType _transformation, typename DimensionTraits<dimensions>::MatrixType _transformation;
_transformedTransformation;
}; };
/** @brief Two-dimensional box */ /** @brief Two-dimensional box */

30
src/Physics/Capsule.cpp

@ -28,37 +28,27 @@
#include "Math/Matrix3.h" #include "Math/Matrix3.h"
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Math/Geometry/Distance.h" #include "Math/Geometry/Distance.h"
#include "Point.h" #include "Magnum.h"
#include "Sphere.h" #include "Physics/Point.h"
#include "Physics/Sphere.h"
using namespace Magnum::Math::Geometry; using namespace Magnum::Math::Geometry;
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> void Capsule<dimensions>::applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) { template<UnsignedInt dimensions> Capsule<dimensions> Capsule<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
_transformedA = matrix.transformPoint(_a); return Capsule<dimensions>(matrix.transformPoint(_a), matrix.transformPoint(_b),
_transformedB = matrix.transformPoint(_b); (matrix.rotationScaling()*typename DimensionTraits<dimensions>::VectorType(1/Constants::sqrt3())).length()*_radius);
Float scaling = (matrix.rotationScaling()*typename DimensionTraits<dimensions>::VectorType(1/Constants::sqrt3())).length();
_transformedRadius = scaling*_radius;
}
template<UnsignedInt dimensions> bool Capsule<dimensions>::collides(const AbstractShape<dimensions>* other) const {
if(other->type() == AbstractShape<dimensions>::Type::Point)
return *this % *static_cast<const Point<dimensions>*>(other);
if(other->type() == AbstractShape<dimensions>::Type::Sphere)
return *this % *static_cast<const Sphere<dimensions>*>(other);
return AbstractShape<dimensions>::collides(other);
} }
template<UnsignedInt dimensions> bool Capsule<dimensions>::operator%(const Point<dimensions>& other) const { template<UnsignedInt dimensions> bool Capsule<dimensions>::operator%(const Point<dimensions>& other) const {
return Distance::lineSegmentPointSquared(transformedA(), transformedB(), other.transformedPosition()) < return Distance::lineSegmentPointSquared(_a, _b, other.position()) <
Math::pow<2>(transformedRadius()); Math::pow<2>(_radius);
} }
template<UnsignedInt dimensions> bool Capsule<dimensions>::operator%(const Sphere<dimensions>& other) const { template<UnsignedInt dimensions> bool Capsule<dimensions>::operator%(const Sphere<dimensions>& other) const {
return Distance::lineSegmentPointSquared(transformedA(), transformedB(), other.transformedPosition()) < return Distance::lineSegmentPointSquared(_a, _b, other.position()) <
Math::pow<2>(transformedRadius()+other.transformedRadius()); Math::pow<2>(_radius+other.radius());
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT

60
src/Physics/Capsule.h

@ -29,10 +29,9 @@
*/ */
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "AbstractShape.h" #include "DimensionTraits.h"
#include "Physics.h" #include "Physics/Physics.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
@ -44,67 +43,51 @@ applying transformation, the scale factor is averaged from all axes.
@see Capsule2D, Capsule3D @see Capsule2D, Capsule3D
@todo Assert for asymmetric scaling @todo Assert for asymmetric scaling
*/ */
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Capsule: public AbstractShape<dimensions> { template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Capsule {
public: public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** /**
* @brief Constructor * @brief Constructor
* *
* Creates zero-sized capsule at origin. * Creates zero-sized capsule at origin.
*/ */
inline explicit Capsule(): _radius(0.0f), _transformedRadius(0.0f) {} inline constexpr explicit Capsule(): _radius(0.0f) {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit Capsule(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b, Float radius): _a(a), _transformedA(a), _b(b), _transformedB(b), _radius(radius), _transformedRadius(radius) {} inline constexpr explicit Capsule(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b, Float radius): _a(a), _b(b), _radius(radius) {}
inline typename AbstractShape<dimensions>::Type type() const override {
return AbstractShape<dimensions>::Type::Capsule;
}
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override;
bool collides(const AbstractShape<dimensions>* other) const override; /** @brief Transformed shape */
Capsule<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const;
/** @brief Start point */ /** @brief Start point */
inline typename DimensionTraits<dimensions>::VectorType a() const { inline constexpr typename DimensionTraits<dimensions>::VectorType a() const {
return _a; return _a;
} }
/** @brief End point */
inline typename DimensionTraits<dimensions>::VectorType b() const {
return _b;
}
/** @brief Set start point */ /** @brief Set start point */
inline void setA(const typename DimensionTraits<dimensions>::VectorType& a) { inline void setA(const typename DimensionTraits<dimensions>::VectorType& a) {
_a = a; _a = a;
} }
/** @brief End point */
inline constexpr typename DimensionTraits<dimensions>::VectorType b() const {
return _b;
}
/** @brief Set end point */ /** @brief Set end point */
inline void setB(const typename DimensionTraits<dimensions>::VectorType& b) { inline void setB(const typename DimensionTraits<dimensions>::VectorType& b) {
_b = b; _b = b;
} }
/** @brief Radius */ /** @brief Radius */
inline Float radius() const { return _radius; } inline constexpr Float radius() const { return _radius; }
/** @brief Set radius */ /** @brief Set radius */
inline void setRadius(Float radius) { _radius = radius; } inline void setRadius(Float radius) { _radius = radius; }
/** @brief Transformed first point */
inline typename DimensionTraits<dimensions>::VectorType transformedA() const {
return _transformedA;
}
/** @brief Transformed second point */
inline typename DimensionTraits<dimensions>::VectorType transformedB() const {
return _transformedB;
}
/** @brief Transformed radius */
inline Float transformedRadius() const {
return _transformedRadius;
}
/** @brief Collision with point */ /** @brief Collision with point */
bool operator%(const Point<dimensions>& other) const; bool operator%(const Point<dimensions>& other) const;
@ -112,9 +95,8 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Capsule: public Abs
bool operator%(const Sphere<dimensions>& other) const; bool operator%(const Sphere<dimensions>& other) const;
private: private:
typename DimensionTraits<dimensions>::VectorType _a, _transformedA, typename DimensionTraits<dimensions>::VectorType _a, _b;
_b, _transformedB; Float _radius;
Float _radius, _transformedRadius;
}; };
/** @brief Two-dimensional capsule */ /** @brief Two-dimensional capsule */

6
src/Physics/Line.cpp

@ -29,9 +29,9 @@
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> void Line<dimensions>::applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) { template<UnsignedInt dimensions> Line<dimensions> Line<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
_transformedA = matrix.transformPoint(_a); return Line<dimensions>(matrix.transformPoint(_a),
_transformedB = matrix.transformPoint(_b); matrix.transformPoint(_b));
} }
/* Explicitly instantiate the templates */ /* Explicitly instantiate the templates */

47
src/Physics/Line.h

@ -29,9 +29,8 @@
*/ */
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "AbstractShape.h" #include "DimensionTraits.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
@ -41,57 +40,47 @@ namespace Magnum { namespace Physics {
@see Line2D, Line3D @see Line2D, Line3D
@todo collision detection of two Line2D @todo collision detection of two Line2D
*/ */
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Line: public AbstractShape<dimensions> { template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Line {
public: public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Creates line with both points at origin. * Creates line with both points at origin.
*/ */
inline explicit Line() {} inline constexpr explicit Line() {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit Line(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b): _a(a), _transformedA(a), _b(b), _transformedB(b) {} inline constexpr explicit Line(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b): _a(a), _b(b) {}
inline typename AbstractShape<dimensions>::Type type() const override {
return AbstractShape<dimensions>::Type::Line;
}
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override; /** @brief Transformed shape */
Line<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const;
/** @brief First point */ /** @brief First point */
inline typename DimensionTraits<dimensions>::VectorType a() const { inline constexpr typename DimensionTraits<dimensions>::VectorType a() const {
return _a; return _a;
} }
/** @brief Second point */
inline typename DimensionTraits<dimensions>::VectorType b() const {
return _b;
}
/** @brief Set first point */ /** @brief Set first point */
inline void setA(const typename DimensionTraits<dimensions>::VectorType& a) { inline void setA(const typename DimensionTraits<dimensions>::VectorType& a) {
_a = a; _a = a;
} }
/** @brief Second point */
inline constexpr typename DimensionTraits<dimensions>::VectorType b() const {
return _b;
}
/** @brief Set second point */ /** @brief Set second point */
inline void setB(const typename DimensionTraits<dimensions>::VectorType& b) { inline void setB(const typename DimensionTraits<dimensions>::VectorType& b) {
_b = b; _b = b;
} }
/** @brief Transformed first point */
inline typename DimensionTraits<dimensions>::VectorType transformedA() const {
return _transformedA;
}
/** @brief Transformed second point */
inline typename DimensionTraits<dimensions>::VectorType transformedB() const {
return _transformedB;
}
private: private:
typename DimensionTraits<dimensions>::VectorType _a, _transformedA, typename DimensionTraits<dimensions>::VectorType _a, _b;
_b, _transformedB;
}; };
/** @brief Infinite two-dimensional line */ /** @brief Infinite two-dimensional line */

12
src/Physics/LineSegment.h

@ -44,14 +44,18 @@ template<UnsignedInt dimensions> class LineSegment: public Line<dimensions> {
* *
* Creates line segment with both points at origin. * Creates line segment with both points at origin.
*/ */
inline explicit LineSegment() {} inline constexpr explicit LineSegment() {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit LineSegment(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b): Line<dimensions>(a, b) {} inline constexpr explicit LineSegment(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b): Line<dimensions>(a, b) {}
inline typename AbstractShape<dimensions>::Type type() const override { /** @brief Transformed shape */
return AbstractShape<dimensions>::Type::LineSegment; inline LineSegment<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
return Line<dimensions>::transformed(matrix);
} }
private:
inline constexpr LineSegment(const Line<dimensions>& line): Line<dimensions>(line) {}
}; };
/** @brief Two-dimensional line segment */ /** @brief Two-dimensional line segment */

21
src/Physics/Plane.cpp

@ -28,33 +28,24 @@
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Math/Geometry/Intersection.h" #include "Math/Geometry/Intersection.h"
#include "LineSegment.h" #include "Physics/LineSegment.h"
using namespace Magnum::Math::Geometry; using namespace Magnum::Math::Geometry;
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
void Plane::applyTransformationMatrix(const Matrix4& matrix) { Plane Plane::transformed(const Matrix4& matrix) const {
_transformedPosition = matrix.transformPoint(_position); return Plane(matrix.transformPoint(_position),
_transformedNormal = matrix.rotation()*_normal; matrix.rotation()*_normal);
}
bool Plane::collides(const AbstractShape<3>* other) const {
if(other->type() == Type::Line)
return *this % *static_cast<const Line3D*>(other);
if(other->type() == Type::LineSegment)
return *this % *static_cast<const LineSegment3D*>(other);
return AbstractShape<3>::collides(other);
} }
bool Plane::operator%(const Line3D& other) const { bool Plane::operator%(const Line3D& other) const {
Float t = Intersection::planeLine(transformedPosition(), transformedNormal(), other.transformedA(), other.transformedB()-other.transformedA()); Float t = Intersection::planeLine(_position, _normal, other.a(), other.b()-other.a());
return t != t || (t != std::numeric_limits<Float>::infinity() && t != -std::numeric_limits<Float>::infinity()); return t != t || (t != std::numeric_limits<Float>::infinity() && t != -std::numeric_limits<Float>::infinity());
} }
bool Plane::operator%(const LineSegment3D& other) const { bool Plane::operator%(const LineSegment3D& other) const {
Float t = Intersection::planeLine(transformedPosition(), transformedNormal(), other.transformedA(), other.transformedB()-other.transformedA()); Float t = Intersection::planeLine(_position, _normal, other.a(), other.b()-other.a());
return t > 0.0f && t < 1.0f; return t > 0.0f && t < 1.0f;
} }

45
src/Physics/Plane.h

@ -29,38 +29,34 @@
*/ */
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "AbstractShape.h" #include "Magnum.h"
#include "Physics.h" #include "Physics/Physics.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
/** @brief Infinite plane, defined by position and normal (3D only) */ /** @brief Infinite plane, defined by position and normal (3D only) */
class MAGNUM_PHYSICS_EXPORT Plane: public AbstractShape<3> { class MAGNUM_PHYSICS_EXPORT Plane {
public: public:
enum: UnsignedInt {
Dimensions = 3 /**< Dimension count */
};
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Creates plane with zero-sized normal at origin. * Creates plane with zero-sized normal at origin.
*/ */
inline explicit Plane() {} inline constexpr explicit Plane() {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit Plane(const Vector3& position, const Vector3& normal): _position(position), _transformedPosition(position), _normal(normal), _transformedNormal(normal) {} inline constexpr explicit Plane(const Vector3& position, const Vector3& normal): _position(position), _normal(normal) {}
inline Type type() const override { return Type::Plane; } /** @brief Transformed shape */
Plane transformed(const Matrix4& matrix) const;
#ifndef DOXYGEN_GENERATING_OUTPUT
void applyTransformationMatrix(const Matrix4& matrix) override;
bool collides(const AbstractShape<3>* other) const override;
#else
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override;
bool collides(const AbstractShape* other) const override;
#endif
/** @brief Position */ /** @brief Position */
inline Vector3 position() const { return _position; } inline constexpr Vector3 position() const { return _position; }
/** @brief Set position */ /** @brief Set position */
inline void setPosition(const Vector3& position) { inline void setPosition(const Vector3& position) {
@ -68,23 +64,13 @@ class MAGNUM_PHYSICS_EXPORT Plane: public AbstractShape<3> {
} }
/** @brief Normal */ /** @brief Normal */
inline Vector3 normal() const { return _normal; } inline constexpr Vector3 normal() const { return _normal; }
/** @brief Set normal */ /** @brief Set normal */
inline void setNormal(const Vector3& normal) { inline void setNormal(const Vector3& normal) {
_normal = normal; _normal = normal;
} }
/** @brief Transformed position */
inline Vector3 transformedPosition() const {
return _transformedPosition;
}
/** @brief Transformed normal */
inline Vector3 transformedNormal() const {
return _transformedNormal;
}
/** @brief Collision with line */ /** @brief Collision with line */
bool operator%(const Line3D& other) const; bool operator%(const Line3D& other) const;
@ -92,8 +78,7 @@ class MAGNUM_PHYSICS_EXPORT Plane: public AbstractShape<3> {
bool operator%(const LineSegment3D& other) const; bool operator%(const LineSegment3D& other) const;
private: private:
Vector3 _position, _transformedPosition, Vector3 _position, _normal;
_normal, _transformedNormal;
}; };
/** @collisionoperator{Line,Plane} */ /** @collisionoperator{Line,Plane} */

4
src/Physics/Point.cpp

@ -29,8 +29,8 @@
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> void Point<dimensions>::applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) { template<UnsignedInt dimensions> Point<dimensions> Point<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
_transformedPosition = matrix.transformPoint(_position); return Point<dimensions>(matrix.transformPoint(_position));
} }
template class Point<2>; template class Point<2>;

31
src/Physics/Point.h

@ -29,9 +29,8 @@
*/ */
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "AbstractShape.h" #include "DimensionTraits.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
@ -40,26 +39,27 @@ namespace Magnum { namespace Physics {
@see Point2D, Point3D @see Point2D, Point3D
*/ */
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Point: public AbstractShape<dimensions> { template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Point {
public: public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Creates point at origin. * Creates point at origin.
*/ */
inline explicit Point() {} inline constexpr explicit Point() {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit Point(const typename DimensionTraits<dimensions>::VectorType& position): _position(position), _transformedPosition(position) {} inline constexpr explicit Point(const typename DimensionTraits<dimensions>::VectorType& position): _position(position) {}
inline typename AbstractShape<dimensions>::Type type() const override {
return AbstractShape<dimensions>::Type::Point;
}
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override; /** @brief Transformed shape */
Point<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const;
/** @brief Position */ /** @brief Position */
inline typename DimensionTraits<dimensions>::VectorType position() const { inline constexpr typename DimensionTraits<dimensions>::VectorType position() const {
return _position; return _position;
} }
@ -68,13 +68,8 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Point: public Abstr
_position = position; _position = position;
} }
/** @brief Transformed position */
inline typename DimensionTraits<dimensions>::VectorType transformedPosition() const {
return _transformedPosition;
}
private: private:
typename DimensionTraits<dimensions>::VectorType _position, _transformedPosition; typename DimensionTraits<dimensions>::VectorType _position;
}; };
/** @brief Two-dimensional point */ /** @brief Two-dimensional point */

37
src/Physics/Sphere.cpp

@ -28,8 +28,9 @@
#include "Math/Matrix3.h" #include "Math/Matrix3.h"
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Math/Geometry/Distance.h" #include "Math/Geometry/Distance.h"
#include "LineSegment.h" #include "Magnum.h"
#include "Point.h" #include "Physics/LineSegment.h"
#include "Physics/Point.h"
using namespace Magnum::Math::Geometry; using namespace Magnum::Math::Geometry;
@ -47,43 +48,25 @@ namespace {
} }
} }
template<UnsignedInt dimensions> void Sphere<dimensions>::applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) { template<UnsignedInt dimensions> Sphere<dimensions> Sphere<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const {
_transformedPosition = matrix.transformPoint(_position); return Sphere<dimensions>(matrix.transformPoint(_position),
Float scaling = (matrix.rotationScaling()*unitVector<dimensions>()).length(); (matrix.rotationScaling()*unitVector<dimensions>()).length()*_radius);
_transformedRadius = scaling*_radius;
}
template<UnsignedInt dimensions> bool Sphere<dimensions>::collides(const AbstractShape<dimensions>* other) const {
if(other->type() == AbstractShape<dimensions>::Type::Point)
return *this % *static_cast<const Point<dimensions>*>(other);
if(other->type() == AbstractShape<dimensions>::Type::Line)
return *this % *static_cast<const Line<dimensions>*>(other);
if(other->type() == AbstractShape<dimensions>::Type::LineSegment)
return *this % *static_cast<const LineSegment<dimensions>*>(other);
if(other->type() == AbstractShape<dimensions>::Type::Sphere)
return *this % *static_cast<const Sphere<dimensions>*>(other);
return AbstractShape<dimensions>::collides(other);
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Point<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Point<dimensions>& other) const {
return (other.transformedPosition()-transformedPosition()).dot() < return (other.position()-_position).dot() < Math::pow<2>(_radius);
Math::pow<2>(transformedRadius());
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Line<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Line<dimensions>& other) const {
return Distance::linePointSquared(other.transformedA(), other.transformedB(), transformedPosition()) < return Distance::linePointSquared(other.a(), other.b(), _position) < Math::pow<2>(_radius);
Math::pow<2>(transformedRadius());
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const LineSegment<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const LineSegment<dimensions>& other) const {
return Distance::lineSegmentPointSquared(other.transformedA(), other.transformedB(), transformedPosition()) < return Distance::lineSegmentPointSquared(other.a(), other.b(), _position) < Math::pow<2>(_radius);
Math::pow<2>(transformedRadius());
} }
template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Sphere<dimensions>& other) const { template<UnsignedInt dimensions> bool Sphere<dimensions>::operator%(const Sphere<dimensions>& other) const {
return (other.transformedPosition()-transformedPosition()).dot() < return (other._position-_position).dot() < Math::pow<2>(_radius+other._radius);
Math::pow<2>(transformedRadius()+other.transformedRadius());
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT

45
src/Physics/Sphere.h

@ -29,10 +29,9 @@
*/ */
#include "Math/Vector3.h" #include "Math/Vector3.h"
#include "AbstractShape.h" #include "DimensionTraits.h"
#include "Physics.h" #include "Physics/Physics.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace Physics { namespace Magnum { namespace Physics {
@ -44,28 +43,27 @@ applying transformation, the scale factor is averaged from all axes.
@see Sphere2D, Sphere3D @see Sphere2D, Sphere3D
@todo Assert for asymmetric scaling @todo Assert for asymmetric scaling
*/ */
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Sphere: public AbstractShape<dimensions> { template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Sphere {
public: public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** /**
* @brief Default constructor * @brief Default constructor
* *
* Creates zero-sized sphere at origin. * Creates zero-sized sphere at origin.
*/ */
inline explicit Sphere(): _radius(0.0f), _transformedRadius(0.0f) {} inline constexpr explicit Sphere(): _radius(0.0f) {}
/** @brief Constructor */ /** @brief Constructor */
inline explicit Sphere(const typename DimensionTraits<dimensions>::VectorType& position, Float radius): _position(position), _transformedPosition(position), _radius(radius), _transformedRadius(radius) {} inline constexpr explicit Sphere(const typename DimensionTraits<dimensions>::VectorType& position, Float radius): _position(position), _radius(radius) {}
inline typename AbstractShape<dimensions>::Type type() const override {
return AbstractShape<dimensions>::Type::Sphere;
}
void applyTransformationMatrix(const typename DimensionTraits<dimensions>::MatrixType& matrix) override;
bool collides(const AbstractShape<dimensions>* other) const override; /** @brief Transformed shape */
Sphere<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const;
/** @brief Position */ /** @brief Position */
inline typename DimensionTraits<dimensions>::VectorType position() const { inline constexpr typename DimensionTraits<dimensions>::VectorType position() const {
return _position; return _position;
} }
@ -75,21 +73,11 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Sphere: public Abst
} }
/** @brief Radius */ /** @brief Radius */
inline Float radius() const { return _radius; } inline constexpr Float radius() const { return _radius; }
/** @brief Set radius */ /** @brief Set radius */
inline void setRadius(Float radius) { _radius = radius; } inline void setRadius(Float radius) { _radius = radius; }
/** @brief Transformed position */
inline typename DimensionTraits<dimensions>::VectorType transformedPosition() const {
return _transformedPosition;
}
/** @brief Transformed radius */
inline Float transformedRadius() const {
return _transformedRadius;
}
/** @brief Collision with point */ /** @brief Collision with point */
bool operator%(const Point<dimensions>& other) const; bool operator%(const Point<dimensions>& other) const;
@ -103,9 +91,8 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Sphere: public Abst
bool operator%(const Sphere<dimensions>& other) const; bool operator%(const Sphere<dimensions>& other) const;
private: private:
typename DimensionTraits<dimensions>::VectorType _position, typename DimensionTraits<dimensions>::VectorType _position;
_transformedPosition; Float _radius;
Float _radius, _transformedRadius;
}; };
/** @brief Two-dimensional sphere */ /** @brief Two-dimensional sphere */

24
src/Physics/Test/AxisAlignedBoxTest.cpp

@ -22,9 +22,8 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <TestSuite/Tester.h>
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Magnum.h"
#include "Physics/AxisAlignedBox.h" #include "Physics/AxisAlignedBox.h"
#include "Physics/Point.h" #include "Physics/Point.h"
@ -32,25 +31,24 @@
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
class AxisAlignedBoxTest: public Corrade::TestSuite::Tester, ShapeTestBase { class AxisAlignedBoxTest: public Corrade::TestSuite::Tester {
public: public:
AxisAlignedBoxTest(); AxisAlignedBoxTest();
void applyTransformation(); void transformed();
void collisionPoint(); void collisionPoint();
}; };
AxisAlignedBoxTest::AxisAlignedBoxTest() { AxisAlignedBoxTest::AxisAlignedBoxTest() {
addTests({&AxisAlignedBoxTest::applyTransformation, addTests({&AxisAlignedBoxTest::transformed,
&AxisAlignedBoxTest::collisionPoint}); &AxisAlignedBoxTest::collisionPoint});
} }
void AxisAlignedBoxTest::applyTransformation() { void AxisAlignedBoxTest::transformed() {
Physics::AxisAlignedBox3D box({-1.0f, -2.0f, -3.0f}, {1.0f, 2.0f, 3.0f}); const auto box = Physics::AxisAlignedBox3D({-1.0f, -2.0f, -3.0f}, {1.0f, 2.0f, 3.0f})
.transformed(Matrix4::translation(Vector3(1.0f))*Matrix4::scaling({2.0f, -1.0f, 1.5f}));
box.applyTransformationMatrix(Matrix4::translation(Vector3(1.0f))*Matrix4::scaling({2.0f, -1.0f, 1.5f})); CORRADE_COMPARE(box.min(), Vector3(-1.0f, 3.0f, -3.5f));
CORRADE_COMPARE(box.transformedMin(), Vector3(-1.0f, 3.0f, -3.5f)); CORRADE_COMPARE(box.max(), Vector3(3.0f, -1.0f, 5.5f));
CORRADE_COMPARE(box.transformedMax(), Vector3(3.0f, -1.0f, 5.5f));
} }
void AxisAlignedBoxTest::collisionPoint() { void AxisAlignedBoxTest::collisionPoint() {
@ -58,10 +56,6 @@ void AxisAlignedBoxTest::collisionPoint() {
Physics::Point3D point1({-1.5f, -1.0f, 2.0f}); Physics::Point3D point1({-1.5f, -1.0f, 2.0f});
Physics::Point3D point2({0.5f, 1.0f, -2.5f}); Physics::Point3D point2({0.5f, 1.0f, -2.5f});
randomTransformation(box);
randomTransformation(point1);
randomTransformation(point2);
VERIFY_NOT_COLLIDES(box, point1); VERIFY_NOT_COLLIDES(box, point1);
VERIFY_COLLIDES(box, point2); VERIFY_COLLIDES(box, point2);
} }

14
src/Physics/Test/BoxTest.cpp

@ -25,6 +25,7 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Magnum.h"
#include "Physics/Box.h" #include "Physics/Box.h"
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
@ -33,18 +34,17 @@ class BoxTest: public Corrade::TestSuite::Tester {
public: public:
BoxTest(); BoxTest();
void applyTransformation(); void transformed();
}; };
BoxTest::BoxTest() { BoxTest::BoxTest() {
addTests({&BoxTest::applyTransformation}); addTests({&BoxTest::transformed});
} }
void BoxTest::applyTransformation() { void BoxTest::transformed() {
Physics::Box3D box(Matrix4::translation({1.0f, 2.0f, -3.0f})); const auto box = Physics::Box3D(Matrix4::translation({1.0f, 2.0f, -3.0f}))
.transformed(Matrix4::scaling({2.0f, -1.0f, 1.5f}));
box.applyTransformationMatrix(Matrix4::scaling({2.0f, -1.0f, 1.5f})); CORRADE_COMPARE(box.transformation(), Matrix4::scaling({2.0f, -1.0f, 1.5f})*Matrix4::translation({1.0f, 2.0f, -3.0f}));
CORRADE_COMPARE(box.transformedTransformation(), Matrix4::scaling({2.0f, -1.0f, 1.5f})*Matrix4::translation({1.0f, 2.0f, -3.0f}));
} }
}}} }}}

35
src/Physics/Test/CapsuleTest.cpp

@ -22,6 +22,8 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Math/Matrix4.h"
#include "Magnum.h"
#include "Physics/Capsule.h" #include "Physics/Capsule.h"
#include "Physics/Point.h" #include "Physics/Point.h"
#include "Physics/Sphere.h" #include "Physics/Sphere.h"
@ -30,32 +32,33 @@
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
class CapsuleTest: public Corrade::TestSuite::Tester, ShapeTestBase { class CapsuleTest: public Corrade::TestSuite::Tester {
public: public:
CapsuleTest(); CapsuleTest();
void applyTransformation(); void transformed();
void transformedAverageScaling();
void collisionPoint(); void collisionPoint();
void collisionSphere(); void collisionSphere();
}; };
CapsuleTest::CapsuleTest() { CapsuleTest::CapsuleTest() {
addTests({&CapsuleTest::applyTransformation, addTests({&CapsuleTest::transformed,
&CapsuleTest::collisionPoint, &CapsuleTest::collisionPoint,
&CapsuleTest::collisionSphere}); &CapsuleTest::collisionSphere});
} }
void CapsuleTest::applyTransformation() { void CapsuleTest::transformed() {
Physics::Capsule3D capsule({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}, 7.0f); const Physics::Capsule3D capsule({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}, 7.0f);
capsule.applyTransformationMatrix(Matrix4::rotation(Deg(90.0f), Vector3::zAxis())); const auto transformed = capsule.transformed(Matrix4::rotation(Deg(90.0f), Vector3::zAxis()));
CORRADE_COMPARE(capsule.transformedA(), Vector3(-2.0f, 1.0f, 3.0f)); CORRADE_COMPARE(transformed.a(), Vector3(-2.0f, 1.0f, 3.0f));
CORRADE_COMPARE(capsule.transformedB(), Vector3(2.0f, -1.0f, -3.0f)); CORRADE_COMPARE(transformed.b(), Vector3(2.0f, -1.0f, -3.0f));
CORRADE_COMPARE(capsule.transformedRadius(), 7.0f); CORRADE_COMPARE(transformed.radius(), 7.0f);
/* Apply average scaling to radius */ /* Apply average scaling to radius */
capsule.applyTransformationMatrix(Matrix4::scaling({Constants::sqrt3(), -Constants::sqrt2(), 2.0f})); const auto scaled = capsule.transformed(Matrix4::scaling({Constants::sqrt3(), -Constants::sqrt2(), 2.0f}));
CORRADE_COMPARE(capsule.transformedRadius(), Constants::sqrt3()*7.0f); CORRADE_COMPARE(scaled.radius(), Constants::sqrt3()*7.0f);
} }
void CapsuleTest::collisionPoint() { void CapsuleTest::collisionPoint() {
@ -64,11 +67,6 @@ void CapsuleTest::collisionPoint() {
Physics::Point3D point1({2.9f, 1.0f, 0.0f}); Physics::Point3D point1({2.9f, 1.0f, 0.0f});
Physics::Point3D point2({1.0f, 3.1f, 0.0f}); Physics::Point3D point2({1.0f, 3.1f, 0.0f});
randomTransformation(capsule);
randomTransformation(point);
randomTransformation(point1);
randomTransformation(point2);
VERIFY_COLLIDES(capsule, point); VERIFY_COLLIDES(capsule, point);
VERIFY_COLLIDES(capsule, point1); VERIFY_COLLIDES(capsule, point1);
VERIFY_NOT_COLLIDES(capsule, point2); VERIFY_NOT_COLLIDES(capsule, point2);
@ -80,11 +78,6 @@ void CapsuleTest::collisionSphere() {
Physics::Sphere3D sphere1({3.5f, 1.0f, 0.0f}, 0.6f); Physics::Sphere3D sphere1({3.5f, 1.0f, 0.0f}, 0.6f);
Physics::Sphere3D sphere2({1.0f, 4.1f, 0.0f}, 1.0f); Physics::Sphere3D sphere2({1.0f, 4.1f, 0.0f}, 1.0f);
randomTransformation(capsule);
randomTransformation(sphere);
randomTransformation(sphere1);
randomTransformation(sphere2);
VERIFY_COLLIDES(capsule, sphere); VERIFY_COLLIDES(capsule, sphere);
VERIFY_COLLIDES(capsule, sphere1); VERIFY_COLLIDES(capsule, sphere1);
VERIFY_NOT_COLLIDES(capsule, sphere2); VERIFY_NOT_COLLIDES(capsule, sphere2);

15
src/Physics/Test/LineTest.cpp

@ -25,6 +25,7 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Magnum.h"
#include "Physics/Line.h" #include "Physics/Line.h"
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
@ -33,18 +34,18 @@ class LineTest: public Corrade::TestSuite::Tester {
public: public:
LineTest(); LineTest();
void applyTransformation(); void transformed();
}; };
LineTest::LineTest() { LineTest::LineTest() {
addTests({&LineTest::applyTransformation}); addTests({&LineTest::transformed});
} }
void LineTest::applyTransformation() { void LineTest::transformed() {
Physics::Line3D line({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}); const auto line = Physics::Line3D({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f})
line.applyTransformationMatrix(Matrix4::rotation(Deg(90.0f), Vector3::zAxis())); .transformed(Matrix4::rotation(Deg(90.0f), Vector3::zAxis()));
CORRADE_COMPARE(line.transformedA(), Vector3(-2.0f, 1.0f, 3.0f)); CORRADE_COMPARE(line.a(), Vector3(-2.0f, 1.0f, 3.0f));
CORRADE_COMPARE(line.transformedB(), Vector3(2.0f, -1.0f, -3.0f)); CORRADE_COMPARE(line.b(), Vector3(2.0f, -1.0f, -3.0f));
} }
}}} }}}

33
src/Physics/Test/PlaneTest.cpp

@ -22,6 +22,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Math/Matrix4.h"
#include "Physics/LineSegment.h" #include "Physics/LineSegment.h"
#include "Physics/Point.h" #include "Physics/Point.h"
#include "Physics/Plane.h" #include "Physics/Plane.h"
@ -30,32 +31,32 @@
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
class PlaneTest: public Corrade::TestSuite::Tester, ShapeTestBase { class PlaneTest: public Corrade::TestSuite::Tester {
public: public:
PlaneTest(); PlaneTest();
void applyTransformation(); void transformed();
void collisionLine(); void collisionLine();
void collisionLineSegment(); void collisionLineSegment();
}; };
PlaneTest::PlaneTest() { PlaneTest::PlaneTest() {
addTests({&PlaneTest::applyTransformation, addTests({&PlaneTest::transformed,
&PlaneTest::collisionLine, &PlaneTest::collisionLine,
&PlaneTest::collisionLineSegment}); &PlaneTest::collisionLineSegment});
} }
void PlaneTest::applyTransformation() { void PlaneTest::transformed() {
Physics::Plane plane({1.0f, 2.0f, 3.0f}, {Constants::sqrt2(), -Constants::sqrt2(), 0}); const Physics::Plane plane({1.0f, 2.0f, 3.0f}, {Constants::sqrt2(), -Constants::sqrt2(), 0});
plane.applyTransformationMatrix(Matrix4::rotation(Deg(90.0f), Vector3::xAxis())); const auto transformed = plane.transformed(Matrix4::rotation(Deg(90.0f), Vector3::xAxis()));
CORRADE_COMPARE(plane.transformedPosition(), Vector3(1.0f, -3.0f, 2.0f)); CORRADE_COMPARE(transformed.position(), Vector3(1.0f, -3.0f, 2.0f));
CORRADE_COMPARE(plane.transformedNormal(), Vector3(Constants::sqrt2(), 0, -Constants::sqrt2())); CORRADE_COMPARE(transformed.normal(), Vector3(Constants::sqrt2(), 0, -Constants::sqrt2()));
/* The normal should stay normalized */ /* The normal should stay normalized */
plane.applyTransformationMatrix(Matrix4::scaling({1.5f, 2.0f, 3.0f})); const auto scaled = plane.transformed(Matrix4::scaling({1.5f, 2.0f, 3.0f}));
CORRADE_COMPARE(plane.transformedPosition(), Vector3(1.5f, 4.0f, 9.0f)); CORRADE_COMPARE(scaled.position(), Vector3(1.5f, 4.0f, 9.0f));
CORRADE_COMPARE(plane.transformedNormal(), Vector3(Constants::sqrt2(), -Constants::sqrt2(), 0)); CORRADE_COMPARE(scaled.normal(), Vector3(Constants::sqrt2(), -Constants::sqrt2(), 0));
} }
void PlaneTest::collisionLine() { void PlaneTest::collisionLine() {
@ -64,11 +65,6 @@ void PlaneTest::collisionLine() {
Physics::Line3D line2({0.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}); Physics::Line3D line2({0.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f});
Physics::Line3D line3({0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}); Physics::Line3D line3({0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f});
randomTransformation(plane);
randomTransformation(line);
randomTransformation(line2);
randomTransformation(line3);
VERIFY_COLLIDES(plane, line); VERIFY_COLLIDES(plane, line);
VERIFY_COLLIDES(plane, line2); VERIFY_COLLIDES(plane, line2);
VERIFY_NOT_COLLIDES(plane, line3); VERIFY_NOT_COLLIDES(plane, line3);
@ -80,11 +76,6 @@ void PlaneTest::collisionLineSegment() {
Physics::LineSegment3D line2({0.0f, 0.1f, 0.0f}, {0.0f, 7.0f, 0.0f}); Physics::LineSegment3D line2({0.0f, 0.1f, 0.0f}, {0.0f, 7.0f, 0.0f});
Physics::LineSegment3D line3({0.0f, -7.0f, 0.0f}, {0.0f, -0.1f, 0.0f}); Physics::LineSegment3D line3({0.0f, -7.0f, 0.0f}, {0.0f, -0.1f, 0.0f});
randomTransformation(plane);
randomTransformation(line);
randomTransformation(line2);
randomTransformation(line3);
VERIFY_COLLIDES(plane, line); VERIFY_COLLIDES(plane, line);
VERIFY_NOT_COLLIDES(plane, line2); VERIFY_NOT_COLLIDES(plane, line2);
VERIFY_NOT_COLLIDES(plane, line3); VERIFY_NOT_COLLIDES(plane, line3);

13
src/Physics/Test/PointTest.cpp

@ -25,6 +25,7 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "Math/Matrix4.h" #include "Math/Matrix4.h"
#include "Magnum.h"
#include "Physics/Point.h" #include "Physics/Point.h"
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
@ -33,17 +34,17 @@ class PointTest: public Corrade::TestSuite::Tester {
public: public:
PointTest(); PointTest();
void applyTransformation(); void transformed();
}; };
PointTest::PointTest() { PointTest::PointTest() {
addTests({&PointTest::applyTransformation}); addTests({&PointTest::transformed});
} }
void PointTest::applyTransformation() { void PointTest::transformed() {
Physics::Point3D point({1.0f, 2.0f, 3.0f}); const auto point = Physics::Point3D({1.0f, 2.0f, 3.0f})
point.applyTransformationMatrix(Matrix4::translation({5.0f, 6.0f, 7.0f})); .transformed(Matrix4::translation({5.0f, 6.0f, 7.0f}));
CORRADE_COMPARE(point.transformedPosition(), Vector3(6.0f, 8.0f, 10.0f)); CORRADE_COMPARE(point.position(), Vector3(6.0f, 8.0f, 10.0f));
} }
}}} }}}

18
src/Physics/Test/ShapeTestBase.h

@ -26,29 +26,15 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "Math/Matrix4.h"
#include "Magnum.h"
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
class ShapeTestBase {
protected:
template<class T> void randomTransformation(T& shape) {
shape.applyTransformationMatrix(Matrix4::translation({7.0f, 8.0f, -9.0f}));
}
};
#define VERIFY_COLLIDES(a, b) \ #define VERIFY_COLLIDES(a, b) \
CORRADE_VERIFY(a % b); \ CORRADE_VERIFY(a % b); \
CORRADE_VERIFY(b % a); \ CORRADE_VERIFY(b % a);
CORRADE_VERIFY(a.collides(&b)); \
CORRADE_VERIFY(b.collides(&a));
#define VERIFY_NOT_COLLIDES(a, b) \ #define VERIFY_NOT_COLLIDES(a, b) \
CORRADE_VERIFY(!(a % b)); \ CORRADE_VERIFY(!(a % b)); \
CORRADE_VERIFY(!(b % a)); \ CORRADE_VERIFY(!(b % a));
CORRADE_VERIFY(!(a.collides(&b))); \
CORRADE_VERIFY(!(b.collides(&a)));
}}} }}}

44
src/Physics/Test/SphereTest.cpp

@ -22,6 +22,8 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include "Math/Matrix4.h"
#include "Magnum.h"
#include "Physics/LineSegment.h" #include "Physics/LineSegment.h"
#include "Physics/Point.h" #include "Physics/Point.h"
#include "Physics/Sphere.h" #include "Physics/Sphere.h"
@ -30,11 +32,11 @@
namespace Magnum { namespace Physics { namespace Test { namespace Magnum { namespace Physics { namespace Test {
class SphereTest: public Corrade::TestSuite::Tester, ShapeTestBase { class SphereTest: public Corrade::TestSuite::Tester {
public: public:
SphereTest(); SphereTest();
void applyTransformation(); void transformed();
void collisionPoint(); void collisionPoint();
void collisionLine(); void collisionLine();
void collisionLineSegment(); void collisionLineSegment();
@ -42,28 +44,28 @@ class SphereTest: public Corrade::TestSuite::Tester, ShapeTestBase {
}; };
SphereTest::SphereTest() { SphereTest::SphereTest() {
addTests({&SphereTest::applyTransformation, addTests({&SphereTest::transformed,
&SphereTest::collisionPoint, &SphereTest::collisionPoint,
&SphereTest::collisionLine, &SphereTest::collisionLine,
&SphereTest::collisionLineSegment, &SphereTest::collisionLineSegment,
&SphereTest::collisionSphere}); &SphereTest::collisionSphere});
} }
void SphereTest::applyTransformation() { void SphereTest::transformed() {
Physics::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 7.0f); const Physics::Sphere3D sphere({1.0f, 2.0f, 3.0f}, 7.0f);
sphere.applyTransformationMatrix(Matrix4::rotation(Deg(90.0f), Vector3::yAxis())); const auto transformed = sphere.transformed(Matrix4::rotation(Deg(90.0f), Vector3::yAxis()));
CORRADE_COMPARE(sphere.transformedPosition(), Vector3(3.0f, 2.0f, -1.0f)); CORRADE_COMPARE(transformed.position(), Vector3(3.0f, 2.0f, -1.0f));
CORRADE_COMPARE(sphere.transformedRadius(), 7.0f); CORRADE_COMPARE(transformed.radius(), 7.0f);
/* Symmetric scaling */ /* Symmetric scaling */
sphere.applyTransformationMatrix(Matrix4::scaling(Vector3(2.0f))); const auto scaled = sphere.transformed(Matrix4::scaling(Vector3(2.0f)));
CORRADE_COMPARE(sphere.transformedPosition(), Vector3(2.0f, 4.0f, 6.0f)); CORRADE_COMPARE(scaled.position(), Vector3(2.0f, 4.0f, 6.0f));
CORRADE_COMPARE(sphere.transformedRadius(), 14.0f); CORRADE_COMPARE(scaled.radius(), 14.0f);
/* Apply average scaling to radius */ /* Apply average scaling to radius */
sphere.applyTransformationMatrix(Matrix4::scaling({Constants::sqrt3(), -Constants::sqrt2(), 2.0f})); const auto nonEven = sphere.transformed(Matrix4::scaling({Constants::sqrt3(), -Constants::sqrt2(), 2.0f}));
CORRADE_COMPARE(sphere.transformedRadius(), Constants::sqrt3()*7.0f); CORRADE_COMPARE(nonEven.radius(), Constants::sqrt3()*7.0f);
} }
void SphereTest::collisionPoint() { void SphereTest::collisionPoint() {
@ -71,10 +73,6 @@ void SphereTest::collisionPoint() {
Physics::Point3D point({1.0f, 3.0f, 3.0f}); Physics::Point3D point({1.0f, 3.0f, 3.0f});
Physics::Point3D point2({1.0f, 3.0f, 1.0f}); Physics::Point3D point2({1.0f, 3.0f, 1.0f});
randomTransformation(sphere);
randomTransformation(point);
randomTransformation(point2);
VERIFY_COLLIDES(sphere, point); VERIFY_COLLIDES(sphere, point);
VERIFY_NOT_COLLIDES(sphere, point2); VERIFY_NOT_COLLIDES(sphere, point2);
} }
@ -84,10 +82,6 @@ void SphereTest::collisionLine() {
Physics::Line3D line({1.0f, 1.5f, 3.5f}, {1.0f, 2.5f, 2.5f}); Physics::Line3D line({1.0f, 1.5f, 3.5f}, {1.0f, 2.5f, 2.5f});
Physics::Line3D line2({1.0f, 2.0f, 5.1f}, {1.0f, 3.0f, 5.1f}); Physics::Line3D line2({1.0f, 2.0f, 5.1f}, {1.0f, 3.0f, 5.1f});
randomTransformation(sphere);
randomTransformation(line);
randomTransformation(line2);
VERIFY_COLLIDES(sphere, line); VERIFY_COLLIDES(sphere, line);
VERIFY_NOT_COLLIDES(sphere, line2); VERIFY_NOT_COLLIDES(sphere, line2);
} }
@ -97,10 +91,6 @@ void SphereTest::collisionLineSegment() {
Physics::LineSegment3D line({1.0f, 2.0f, 4.9f}, {1.0f, 2.0f, 7.0f}); Physics::LineSegment3D line({1.0f, 2.0f, 4.9f}, {1.0f, 2.0f, 7.0f});
Physics::LineSegment3D line2({1.0f, 2.0f, 5.1f}, {1.0f, 2.0f, 7.0f}); Physics::LineSegment3D line2({1.0f, 2.0f, 5.1f}, {1.0f, 2.0f, 7.0f});
randomTransformation(sphere);
randomTransformation(line);
randomTransformation(line2);
VERIFY_COLLIDES(sphere, line); VERIFY_COLLIDES(sphere, line);
VERIFY_NOT_COLLIDES(sphere, line2); VERIFY_NOT_COLLIDES(sphere, line2);
} }
@ -110,10 +100,6 @@ void SphereTest::collisionSphere() {
Physics::Sphere3D sphere1({1.0f, 3.0f, 5.0f}, 1.0f); Physics::Sphere3D sphere1({1.0f, 3.0f, 5.0f}, 1.0f);
Physics::Sphere3D sphere2({1.0f, 3.0f, 0.0f}, 1.0f); Physics::Sphere3D sphere2({1.0f, 3.0f, 0.0f}, 1.0f);
randomTransformation(sphere);
randomTransformation(sphere1);
randomTransformation(sphere2);
VERIFY_COLLIDES(sphere, sphere1); VERIFY_COLLIDES(sphere, sphere1);
VERIFY_NOT_COLLIDES(sphere, sphere2); VERIFY_NOT_COLLIDES(sphere, sphere2);
} }

Loading…
Cancel
Save