Browse Source

Physics shape rework #4: new ObjectShape implementation.

The feature is now templated on shape type, which makes it actually
useful, as it is possible to conveniently query shape parameters from
it. It has now non-templated base and ObjectShapeGroup operates only
with it.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
d9bc507e00
  1. 63
      src/Physics/AbstractObjectShape.cpp
  2. 119
      src/Physics/AbstractObjectShape.h
  3. 4
      src/Physics/CMakeLists.txt
  4. 41
      src/Physics/ObjectShape.cpp
  5. 127
      src/Physics/ObjectShape.h
  6. 10
      src/Physics/ObjectShapeGroup.cpp
  7. 8
      src/Physics/ObjectShapeGroup.h
  8. 10
      src/Physics/Physics.h
  9. 72
      src/Physics/Test/ObjectShapeTest.cpp

63
src/Physics/AbstractObjectShape.cpp

@ -0,0 +1,63 @@
/*
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 "AbstractObjectShape.h"
#include <Utility/Debug.h>
#include "Physics/ObjectShapeGroup.h"
#include "Physics/Implementation/CollisionDispatch.h"
namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> AbstractObjectShape<dimensions>::AbstractObjectShape(SceneGraph::AbstractObject<dimensions>* object, ObjectShapeGroup<dimensions>* group): SceneGraph::AbstractGroupedFeature<dimensions, AbstractObjectShape<dimensions>>(object, group) {
this->setCachedTransformations(SceneGraph::AbstractFeature<dimensions>::CachedTransformation::Absolute);
}
template<UnsignedInt dimensions> ObjectShapeGroup<dimensions>* AbstractObjectShape<dimensions>::group() {
return static_cast<ObjectShapeGroup<dimensions>*>(SceneGraph::AbstractGroupedFeature<dimensions, AbstractObjectShape<dimensions>>::group());
}
template<UnsignedInt dimensions> const ObjectShapeGroup<dimensions>* AbstractObjectShape<dimensions>::group() const {
return static_cast<const ObjectShapeGroup<dimensions>*>(SceneGraph::AbstractGroupedFeature<dimensions, AbstractObjectShape<dimensions>>::group());
}
template<UnsignedInt dimensions> auto AbstractObjectShape<dimensions>::type() const -> Type {
return abstractTransformedShape()->type();
}
template<UnsignedInt dimensions> bool AbstractObjectShape<dimensions>::collides(const AbstractObjectShape<dimensions>* other) const {
return Implementation::collides(abstractTransformedShape(), other->abstractTransformedShape());
}
template<UnsignedInt dimensions> void AbstractObjectShape<dimensions>::markDirty() {
group()->setDirty();
}
#ifndef DOXYGEN_GENERATING_OUTPUT
template class MAGNUM_PHYSICS_EXPORT AbstractObjectShape<2>;
template class MAGNUM_PHYSICS_EXPORT AbstractObjectShape<3>;
#endif
}}

119
src/Physics/AbstractObjectShape.h

@ -0,0 +1,119 @@
#ifndef Magnum_Physics_AbstractObjectShape_h
#define Magnum_Physics_AbstractObjectShape_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::AbstractObjectShape, typedef Magnum::Physics::AbstractObjectShape2D, Magnum::Physics::AbstractObjectShape3D
*/
#include "Magnum.h"
#include "DimensionTraits.h"
#include "Physics/magnumPhysicsVisibility.h"
#include "Physics/shapeImplementation.h"
#include "SceneGraph/AbstractGroupedFeature.h"
namespace Magnum { namespace Physics {
namespace Implementation {
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>* getAbstractShape(const AbstractObjectShape<dimensions>* objectShape) {
return objectShape->abstractTransformedShape();
}
}
/**
@brief Base class for object shapes
This class is not directly instantiable, see ObjectShape instead.
@see AbstractObjectShape2D, AbstractObjectShape3D
*/
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT AbstractObjectShape: public SceneGraph::AbstractGroupedFeature<dimensions, AbstractObjectShape<dimensions>> {
friend const Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(const AbstractObjectShape<dimensions>* objectShape);
public:
enum: UnsignedInt {
Dimensions = dimensions /**< Dimension count */
};
/** @brief Shape type */
#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
/**
* @brief Constructor
* @param object Object holding this feature
* @param group Group this shape belongs to
*/
explicit AbstractObjectShape(SceneGraph::AbstractObject<dimensions>* object, ObjectShapeGroup<dimensions>* group = nullptr);
/**
* @brief Object shape group containing this shape
*
* If the shape doesn't belong to any group, returns `nullptr`.
*/
ObjectShapeGroup<dimensions>* group();
const ObjectShapeGroup<dimensions>* group() const; /**< @overload */
/**
* @brief Shape type
*/
Type type() const;
/**
* @brief Detect collision with other shape
*
* Default implementation returns false.
*/
bool collides(const AbstractObjectShape<dimensions>* other) const;
protected:
/** Marks also the group as dirty */
void markDirty() override;
private:
virtual const Implementation::AbstractShape<dimensions> MAGNUM_PHYSICS_LOCAL * abstractTransformedShape() const = 0;
};
/** @brief Base class for two-dimensional object shapes */
typedef AbstractObjectShape<2> AbstractObjectShape2D;
/** @brief Base class for three-dimensional object shapes */
typedef AbstractObjectShape<3> AbstractObjectShape3D;
}}
#endif

4
src/Physics/CMakeLists.txt

@ -23,7 +23,7 @@
#
set(MagnumPhysics_SRCS
AbstractShape.cpp
AbstractObjectShape.cpp
AxisAlignedBox.cpp
Box.cpp
Capsule.cpp
@ -40,7 +40,7 @@ set(MagnumPhysics_SRCS
Implementation/CollisionDispatch.cpp)
set(MagnumPhysics_HEADERS
AbstractShape.h
AbstractObjectShape.h
AxisAlignedBox.h
Box.h
Capsule.h

41
src/Physics/ObjectShape.cpp

@ -24,40 +24,25 @@
#include "ObjectShape.h"
#include <algorithm>
#include "Physics/ShapeGroup.h"
#include "AbstractShape.h"
#include "ObjectShapeGroup.h"
namespace Magnum { namespace Physics { namespace Implementation {
namespace Magnum { namespace Physics {
template<UnsignedInt dimensions> ObjectShape<dimensions>::ObjectShape(SceneGraph::AbstractObject<dimensions>* object, ObjectShapeGroup<dimensions>* group): SceneGraph::AbstractGroupedFeature<dimensions, ObjectShape<dimensions>>(object, group), _shape(nullptr) {
this->setCachedTransformations(SceneGraph::AbstractFeature<dimensions>::CachedTransformation::Absolute);
}
template<UnsignedInt dimensions> ObjectShape<dimensions>::~ObjectShape() {
delete _shape;
}
template<UnsignedInt dimensions> ObjectShapeGroup<dimensions>* ObjectShape<dimensions>::group() {
return static_cast<ObjectShapeGroup<dimensions>*>(SceneGraph::AbstractGroupedFeature<dimensions, ObjectShape<dimensions>>::group());
}
template<UnsignedInt dimensions> const ObjectShapeGroup<dimensions>* ObjectShape<dimensions>::group() const {
return static_cast<const ObjectShapeGroup<dimensions>*>(SceneGraph::AbstractGroupedFeature<dimensions, ObjectShape<dimensions>>::group());
template<UnsignedInt dimensions> void ObjectShapeHelper<ShapeGroup<dimensions>>::set(ObjectShape<ShapeGroup<dimensions>>& objectShape, const ShapeGroup<dimensions>& shape) {
objectShape._transformedShape.shape = objectShape._shape.shape = shape;
}
template<UnsignedInt dimensions> void ObjectShape<dimensions>::markDirty() {
group()->setDirty();
template<UnsignedInt dimensions> void ObjectShapeHelper<ShapeGroup<dimensions>>::set(ObjectShape<ShapeGroup<dimensions>>& objectShape, ShapeGroup<dimensions>&& shape) {
objectShape._transformedShape.shape = objectShape._shape.shape = std::move(shape);
}
template<UnsignedInt dimensions> void ObjectShape<dimensions>::clean(const typename DimensionTraits<dimensions>::MatrixType& absoluteTransformationMatrix) {
if(_shape) _shape->applyTransformationMatrix(absoluteTransformationMatrix);
template<UnsignedInt dimensions> void ObjectShapeHelper<ShapeGroup<dimensions>>::transform(ObjectShape<ShapeGroup<dimensions>>& objectShape, const typename DimensionTraits<dimensions>::MatrixType& absoluteTransformationMatrix) {
CORRADE_INTERNAL_ASSERT(objectShape._shape.shape.size() == objectShape._transformedShape.shape.size());
for(std::size_t i = 0; i != objectShape.shape().size(); ++i)
objectShape._shape.shape._shapes[i]->transform(absoluteTransformationMatrix, objectShape._transformedShape.shape._shapes[i]);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
template class MAGNUM_PHYSICS_EXPORT ObjectShape<2>;
template class MAGNUM_PHYSICS_EXPORT ObjectShape<3>;
#endif
template struct MAGNUM_PHYSICS_EXPORT ObjectShapeHelper<ShapeGroup<2>>;
template struct MAGNUM_PHYSICS_EXPORT ObjectShapeHelper<ShapeGroup<3>>;
}}
}}}

127
src/Physics/ObjectShape.h

@ -25,16 +25,20 @@
*/
/** @file
* @brief Class Magnum::Physics::ObjectShape, typedef Magnum::Physics::ObjectShape2D, Magnum::Physics::ObjectShape3D
* @brief Class Magnum::Physics::ObjectShape
*/
#include "SceneGraph/AbstractGroupedFeature.h"
#include "Physics/AbstractObjectShape.h"
#include "Physics/Physics.h"
#include "magnumPhysicsVisibility.h"
namespace Magnum { namespace Physics {
namespace Implementation {
template<class> struct ObjectShapeHelper;
}
/**
@brief Object shape
@ -45,95 +49,110 @@ collide with each other.
@section ObjectShape-usage Usage
Add the feature to the object and some shape group (you can also use
ObjectShapeGroup::add() and ObjectShapeGroup::remove() later) and then set
desired object shape using setShape().
ObjectShapeGroup::add() and ObjectShapeGroup::remove() later) and configure the
shape.
@code
Physics::ObjectShapeGroup3D shapes;
Object3D* object;
auto shape = new Physics::ObjectShape3D(object, &shapes);
shape->setShape(Physics::Sphere3D({}, 0.75f) || Physics::AxisAlignedBox3D({}, {3.0f, 1.5f, 2.0f}));
auto shape = new Physics::ObjectShape<Physics::Sphere3D>(object, {{}, 0.75f}, &shapes);
@endcode
@see @ref scenegraph, ObjectShape2D, ObjectShape3D, ObjectShapeGroup2D,
ObjectShapeGroup3D, DebugTools::ShapeRenderer
@see @ref scenegraph, ObjectShapeGroup2D, ObjectShapeGroup3D,
DebugTools::ShapeRenderer
*/
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT ObjectShape: public SceneGraph::AbstractGroupedFeature<dimensions, ObjectShape<dimensions>> {
template<class T> class MAGNUM_PHYSICS_EXPORT ObjectShape: public AbstractObjectShape<T::Dimensions> {
friend struct Implementation::ObjectShapeHelper<T>;
public:
/**
* @brief Constructor
* @param object Object holding this feature
* @param shape Shape
* @param group Group this shape belongs to
*
* Creates empty object shape.
* @see setShape()
*/
explicit ObjectShape(SceneGraph::AbstractObject<dimensions>* object, ObjectShapeGroup<dimensions>* group = nullptr);
template<class ...U> explicit ObjectShape(SceneGraph::AbstractObject<T::Dimensions>* object, const T& shape, ObjectShapeGroup<T::Dimensions>* group = nullptr): AbstractObjectShape<T::Dimensions>(object, group) {
Implementation::ObjectShapeHelper<T>::set(*this, shape);
}
/**
* @brief Destructor
*
* Deletes associated shape.
*/
~ObjectShape();
/** @overload */
template<class ...U> explicit ObjectShape(SceneGraph::AbstractObject<T::Dimensions>* object, T&& shape, ObjectShapeGroup<T::Dimensions>* group = nullptr): AbstractObjectShape<T::Dimensions>(object, group) {
Implementation::ObjectShapeHelper<T>::set(*this, std::move(shape));
}
/** @brief Shape */
inline AbstractShape<dimensions>* shape() { return _shape; }
inline const AbstractShape<dimensions>* shape() const { return _shape; } /**< @overload */
/** @overload */
template<class ...U> explicit ObjectShape(SceneGraph::AbstractObject<T::Dimensions>* object, ObjectShapeGroup<T::Dimensions>* group = nullptr): AbstractObjectShape<T::Dimensions>(object, group) {}
/**
* @brief Set shape
* @return Pointer to self (for method chaining)
*/
inline ObjectShape<dimensions>* setShape(AbstractShape<dimensions>* shape) {
_shape = shape;
this->object()->setDirty();
return this;
}
/** @brief Shape */
inline const T& shape() const { return _shape.shape; }
/**
* @brief Set shape
* @return Pointer to self (for method chaining)
*
* Convenience overload for setShape(AbstractShape*), allowing you to
* use e.g. ShapeGroup operators:
* @code
* Physics::ObjectShape3D* shape;
* shape->setShape(Physics::Sphere3D({}, 0.75f) || Physics::AxisAlignedBox3D({}, {3.0f, 1.5f, 2.0f}));
* @endcode
* Marks the feature as dirty.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline ObjectShape<dimensions>* setShape(T&& shape) {
#else
template<class T> inline typename std::enable_if<std::is_base_of<Physics::AbstractShape<dimensions>, T>::value, ObjectShape<dimensions>*>::type setShape(T&& shape) {
#endif
return setShape(new T(std::move(shape)));
}
ObjectShape<T>* setShape(const T& shape);
/**
* @brief Object shape group containing this shape
* @brief Transformed shape
*
* If the shape doesn't belong to any group, returns `nullptr`.
* Cleans the feature before returning the shape.
*/
ObjectShapeGroup<dimensions>* group();
const ObjectShapeGroup<dimensions>* group() const; /**< @overload */
const T& transformedShape();
protected:
/** Marks also the group as dirty */
void markDirty() override;
/** Applies transformation to associated shape. */
void clean(const typename DimensionTraits<dimensions>::MatrixType& absoluteTransformationMatrix) override;
void clean(const typename DimensionTraits<T::Dimensions>::MatrixType& absoluteTransformationMatrix) override;
private:
AbstractShape<dimensions>* _shape;
const Implementation::AbstractShape<T::Dimensions>* abstractTransformedShape() const override {
return &_transformedShape;
}
Implementation::Shape<T> _shape, _transformedShape;
};
/** @brief Two-dimensional object shape */
typedef ObjectShape<2> ObjectShape2D;
template<class T> inline ObjectShape<T>* ObjectShape<T>::setShape(const T& shape) {
Implementation::ObjectShapeHelper<T>::set(*this, shape);
this->object()->setDirty();
return this;
}
template<class T> inline const T& ObjectShape<T>::transformedShape() {
this->object()->setClean();
return _transformedShape.shape;
}
template<class T> void ObjectShape<T>::markDirty() {
if(this->group()) this->group()->setDirty();
}
template<class T> void ObjectShape<T>::clean(const typename DimensionTraits<T::Dimensions>::MatrixType& absoluteTransformationMatrix) {
Implementation::ObjectShapeHelper<T>::transform(*this, absoluteTransformationMatrix);
}
namespace Implementation {
template<class T> struct ObjectShapeHelper {
inline static void set(ObjectShape<T>& objectShape, const T& shape) {
objectShape._shape.shape = shape;
}
inline static void transform(ObjectShape<T>& objectShape, const typename DimensionTraits<T::Dimensions>::MatrixType& absoluteTransformationMatrix) {
objectShape._transformedShape.shape = objectShape._shape.shape.transformed(absoluteTransformationMatrix);
}
};
template<UnsignedInt dimensions> struct MAGNUM_PHYSICS_EXPORT ObjectShapeHelper<ShapeGroup<dimensions>> {
static void set(ObjectShape<ShapeGroup<dimensions>>& objectShape, const ShapeGroup<dimensions>& shape);
static void set(ObjectShape<ShapeGroup<dimensions>>& objectShape, ShapeGroup<dimensions>&& shape);
/** @brief Three-dimensional object shape */
typedef ObjectShape<3> ObjectShape3D;
static void transform(ObjectShape<ShapeGroup<dimensions>>& objectShape, const typename DimensionTraits<dimensions>::MatrixType& absoluteTransformationMatrix);
};
}
}}

10
src/Physics/ObjectShapeGroup.cpp

@ -24,8 +24,7 @@
#include "ObjectShapeGroup.h"
#include "Physics/AbstractShape.h"
#include "Physics/ObjectShape.h"
#include "Physics/AbstractObjectShape.h"
namespace Magnum { namespace Physics {
@ -42,13 +41,10 @@ template<UnsignedInt dimensions> void ObjectShapeGroup<dimensions>::setClean() {
dirty = false;
}
template<UnsignedInt dimensions> ObjectShape<dimensions>* ObjectShapeGroup<dimensions>::firstCollision(const ObjectShape<dimensions>* shape) {
/* Nothing to test with, done */
if(!shape->shape()) return nullptr;
template<UnsignedInt dimensions> AbstractObjectShape<dimensions>* ObjectShapeGroup<dimensions>::firstCollision(const AbstractObjectShape<dimensions>* shape) {
setClean();
for(std::size_t i = 0; i != this->size(); ++i)
if((*this)[i] != shape && (*this)[i]->shape() && (*this)[i]->shape()->collides(shape->shape()))
if((*this)[i] != shape && (*this)[i]->collides(shape))
return (*this)[i];
return nullptr;

8
src/Physics/ObjectShapeGroup.h

@ -30,7 +30,7 @@
#include <vector>
#include "Physics/ObjectShape.h"
#include "Physics/Physics.h"
#include "SceneGraph/FeatureGroup.h"
#include "magnumPhysicsVisibility.h"
@ -43,8 +43,8 @@ namespace Magnum { namespace Physics {
See ObjectShape for more information.
@see @ref scenegraph, ObjectShapeGroup2D, ObjectShapeGroup3D
*/
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT ObjectShapeGroup: public SceneGraph::FeatureGroup<dimensions, ObjectShape<dimensions>> {
friend class ObjectShape<dimensions>;
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT ObjectShapeGroup: public SceneGraph::FeatureGroup<dimensions, AbstractObjectShape<dimensions>> {
friend class AbstractObjectShape<dimensions>;
public:
/**
@ -86,7 +86,7 @@ template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT ObjectShapeGroup: p
* collisions, returns `nullptr`. Calls setClean() before the
* operation.
*/
ObjectShape<dimensions>* firstCollision(const ObjectShape<dimensions>* shape);
AbstractObjectShape<dimensions>* firstCollision(const AbstractObjectShape<dimensions>* shape);
private:
bool dirty;

10
src/Physics/Physics.h

@ -34,9 +34,9 @@ namespace Magnum { namespace Physics {
/** @todoc remove when doxygen is sane again */
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt> class AbstractShape;
typedef AbstractShape<2> AbstractShape2D;
typedef AbstractShape<3> AbstractShape3D;
template<UnsignedInt> class AbstractObjectShape;
typedef AbstractObjectShape<2> AbstractObjectShape2D;
typedef AbstractObjectShape<3> AbstractObjectShape3D;
template<UnsignedInt> class AxisAlignedBox;
typedef AxisAlignedBox<2> AxisAlignedBox2D;
@ -58,9 +58,7 @@ template<UnsignedInt> class LineSegment;
typedef LineSegment<2> LineSegment2D;
typedef LineSegment<3> LineSegment3D;
template<UnsignedInt> class ObjectShape;
typedef ObjectShape<2> ObjectShape2D;
typedef ObjectShape<3> ObjectShape3D;
template<class> class ObjectShape;
template<UnsignedInt> class ObjectShapeGroup;
typedef ObjectShapeGroup<2> ObjectShapeGroup2D;

72
src/Physics/Test/ObjectShapeTest.cpp

@ -27,7 +27,9 @@
#include "Physics/ObjectShapeGroup.h"
#include "Physics/ObjectShape.h"
#include "Physics/Point.h"
#include "Physics/ShapeGroup.h"
#include "Physics/Sphere.h"
#include "SceneGraph/MatrixTransformation2D.h"
#include "SceneGraph/MatrixTransformation3D.h"
#include "SceneGraph/Scene.h"
@ -39,90 +41,102 @@ class ObjectShapeTest: public Corrade::TestSuite::Tester {
void clean();
void firstCollision();
void shapeGroup();
};
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation2D<>> Scene2D;
typedef SceneGraph::Object<SceneGraph::MatrixTransformation2D<>> Object2D;
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D<>> Scene3D;
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D<>> Object3D;
ObjectShapeTest::ObjectShapeTest() {
addTests({&ObjectShapeTest::clean,
&ObjectShapeTest::firstCollision});
&ObjectShapeTest::firstCollision,
&ObjectShapeTest::shapeGroup});
}
void ObjectShapeTest::clean() {
Scene3D scene;
ObjectShapeGroup3D group;
ObjectShapeGroup3D shapes;
Object3D a(&scene);
ObjectShape3D* shape = new ObjectShape3D(&a, &group);
shape->setShape(Physics::Point3D({1.0f, -2.0f, 3.0f}));
auto shape = new Physics::ObjectShape<Physics::Point3D>(&a, {{1.0f, -2.0f, 3.0f}}, &shapes);
a.scale(Vector3(-2.0f));
Object3D b(&scene);
new ObjectShape3D(&b, &group);
new Physics::ObjectShape<Physics::Point3D>(&b, &shapes);
/* Everything is dirty at the beginning */
CORRADE_VERIFY(group.isDirty());
CORRADE_VERIFY(shapes.isDirty());
CORRADE_VERIFY(a.isDirty());
CORRADE_VERIFY(b.isDirty());
/* Cleaning object will not clean anything other */
a.setClean();
CORRADE_VERIFY(group.isDirty());
CORRADE_VERIFY(shapes.isDirty());
CORRADE_VERIFY(!a.isDirty());
CORRADE_VERIFY(b.isDirty());
/* Verify that the feature was actually cleaned */
CORRADE_COMPARE(static_cast<const Physics::Point3D*>(shape->shape())->transformedPosition(),
CORRADE_COMPARE(shape->transformedShape().position(),
Vector3(-2.0f, 4.0f, -6.0f));
/* Setting group clean will clean whole group */
a.setDirty();
group.setClean();
CORRADE_VERIFY(!group.isDirty());
shapes.setClean();
CORRADE_VERIFY(!shapes.isDirty());
CORRADE_VERIFY(!a.isDirty());
CORRADE_VERIFY(!b.isDirty());
/* Setting object dirty will set also the group, but not other objects */
b.setDirty();
CORRADE_VERIFY(group.isDirty());
CORRADE_VERIFY(shapes.isDirty());
CORRADE_VERIFY(!a.isDirty());
CORRADE_VERIFY(b.isDirty());
}
void ObjectShapeTest::firstCollision() {
Scene3D scene;
ObjectShapeGroup3D group;
ObjectShapeGroup3D shapes;
Object3D a(&scene);
ObjectShape3D* aShape = new ObjectShape3D(&a, &group);
aShape->setShape(Physics::Sphere3D({1.0f, -2.0f, 3.0f}, 1.5f));
auto aShape = new ObjectShape<Physics::Sphere3D>(&a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes);
Object3D b(&scene);
ObjectShape3D* bShape = new ObjectShape3D(&b, &group);
bShape->setShape(Physics::Point3D({3.0f, -2.0f, 3.0f}));
auto bShape = new ObjectShape<Physics::Point3D>(&b, {{3.0f, -2.0f, 3.0f}}, &shapes);
Object3D c(&scene);
ObjectShape3D* cShape = new ObjectShape3D(&c, &group);
/* No-op if the object has no shape */
CORRADE_VERIFY(group.isDirty());
CORRADE_VERIFY(!group.firstCollision(cShape));
CORRADE_VERIFY(group.isDirty());
new ObjectShape<Physics::ShapeGroup3D>(&c, &shapes);
/* No collisions initially */
CORRADE_VERIFY(!group.firstCollision(aShape));
CORRADE_VERIFY(!group.firstCollision(bShape));
CORRADE_VERIFY(!group.isDirty());
CORRADE_VERIFY(!shapes.firstCollision(aShape));
CORRADE_VERIFY(!shapes.firstCollision(bShape));
CORRADE_VERIFY(!shapes.isDirty());
/* Move point into sphere */
b.translate(Vector3::xAxis(-1.0f));
/* Collision */
CORRADE_VERIFY(group.isDirty());
CORRADE_VERIFY(group.firstCollision(aShape) == bShape);
CORRADE_VERIFY(group.firstCollision(bShape) == aShape);
CORRADE_VERIFY(!group.isDirty());
CORRADE_VERIFY(shapes.isDirty());
CORRADE_VERIFY(shapes.firstCollision(aShape) == bShape);
CORRADE_VERIFY(shapes.firstCollision(bShape) == aShape);
CORRADE_VERIFY(!shapes.isDirty());
}
void ObjectShapeTest::shapeGroup() {
Scene2D scene;
ObjectShapeGroup2D shapes;
/* Verify construction */
Object2D a(&scene);
auto shape = new ObjectShape<Physics::ShapeGroup2D>(&a, Physics::Sphere2D({}, 0.5f) || Physics::Point2D({0.25f, -1.0f}));
CORRADE_COMPARE(shape->transformedShape().size(), 2);
/* Verify the original shape is updated */
const auto& point = shape->transformedShape().get<Physics::Point2D>(1);
a.translate(Vector2::xAxis(5.0f));
a.setClean();
CORRADE_COMPARE(point.position(), Vector2(5.25f, -1.0f));
}
}}}

Loading…
Cancel
Save