mirror of https://github.com/mosra/magnum.git
20 changed files with 715 additions and 715 deletions
@ -0,0 +1,167 @@
|
||||
/*
|
||||
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 "Composition.h" |
||||
|
||||
#include <algorithm> |
||||
#include <Utility/Assert.h> |
||||
|
||||
#include "Physics/Implementation/CollisionDispatch.h" |
||||
|
||||
namespace Magnum { namespace Physics { |
||||
|
||||
/*
|
||||
Hierarchy implementation notes: |
||||
|
||||
The hierarchy is stored in flat array to provide easy access for the user and |
||||
to save some allocations. Each node has zero, one or two subnodes. Value of |
||||
`Node::rightNode` describes which child nodes exist: |
||||
|
||||
* 0 - no child subnodes |
||||
* 1 - only left subnode exists |
||||
* 2 - only right subnode exists |
||||
* >2 - both child nodes exist |
||||
|
||||
If left node exists, it is right next to current one. If right node exists, it |
||||
is at position `Node::rightNode-1` relative to current one (this applies also |
||||
when `rightNode` is equal to 2, right node is right next to current one, |
||||
because there are no left nodes). |
||||
|
||||
The node also specifies which shapes belong to it. Root node owns whole shape |
||||
array and `Node::rightShape` marks first shape belonging to the right child |
||||
node, relatively to begin. This recurses into child nodes, thus left child node |
||||
has shapes from parent's begin to parent's `rightShape`. |
||||
|
||||
Shapes are merged together by concatenating its node and shape list and adding |
||||
new node at the beginning with properly set `rightNode` and `rightShape`. |
||||
Because these values are relative to parent, they don't need to be modified |
||||
when concatenating. |
||||
*/ |
||||
|
||||
template<UnsignedInt dimensions> Composition<dimensions>::Composition(const Composition<dimensions>& other): _shapeCount(other._shapeCount), _nodeCount(other._nodeCount) { |
||||
copyShapes(0, other); |
||||
copyNodes(0, other); |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> Composition<dimensions>::Composition(Composition<dimensions>&& other): _shapeCount(other._shapeCount), _nodeCount(other._nodeCount), _shapes(other._shapes), _nodes(other._nodes) { |
||||
other._shapes = nullptr; |
||||
other._shapeCount = 0; |
||||
|
||||
other._nodes = nullptr; |
||||
other._nodeCount = 0; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> Composition<dimensions>::~Composition() { |
||||
for(std::size_t i = 0; i != _shapeCount; ++i) |
||||
delete _shapes[i]; |
||||
|
||||
delete[] _shapes; |
||||
delete[] _nodes; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> Composition<dimensions>& Composition<dimensions>::operator=(const Composition<dimensions>& other) { |
||||
for(std::size_t i = 0; i != _shapeCount; ++i) |
||||
delete _shapes[i]; |
||||
|
||||
if(_shapeCount != other._shapeCount) { |
||||
delete[] _shapes; |
||||
_shapeCount = other._shapeCount; |
||||
_shapes = new Implementation::AbstractShape<dimensions>*[_shapeCount]; |
||||
} |
||||
|
||||
if(_nodeCount != other._nodeCount) { |
||||
delete[] _nodes; |
||||
_nodeCount = other._nodeCount; |
||||
_nodes = new Node[_nodeCount]; |
||||
} |
||||
|
||||
copyShapes(0, other); |
||||
copyNodes(0, other); |
||||
return *this; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> Composition<dimensions>& Composition<dimensions>::operator=(Composition<dimensions>&& other) { |
||||
std::swap(other._shapeCount, _shapeCount); |
||||
std::swap(other._nodeCount, _nodeCount); |
||||
std::swap(other._shapes, _shapes); |
||||
std::swap(other._nodes, _nodes); |
||||
return *this; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> void Composition<dimensions>::copyShapes(const std::size_t offset, Composition<dimensions>&& other) { |
||||
std::move(other._shapes, other._shapes+other._shapeCount, _shapes+offset); |
||||
delete[] other._shapes; |
||||
other._shapes = nullptr; |
||||
other._shapeCount = 0; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> void Composition<dimensions>::copyShapes(const std::size_t offset, const Composition<dimensions>& other) { |
||||
for(std::size_t i = 0; i != other._shapeCount; ++i) |
||||
_shapes[i+offset] = other._shapes[i]->clone(); |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> void Composition<dimensions>::copyNodes(std::size_t offset, const Composition<dimensions>& other) { |
||||
std::copy(other._nodes, other._nodes+other._nodeCount, _nodes+offset); |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> Composition<dimensions> Composition<dimensions>::transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const { |
||||
Composition<dimensions> out(*this); |
||||
for(std::size_t i = 0; i != _shapeCount; ++i) |
||||
_shapes[i]->transform(matrix, out._shapes[i]); |
||||
return out; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> bool Composition<dimensions>::collides(const Implementation::AbstractShape<dimensions>* const a, const std::size_t node, const std::size_t shapeBegin, const std::size_t shapeEnd) const { |
||||
/* Empty group */ |
||||
if(shapeBegin == shapeEnd) return false; |
||||
|
||||
CORRADE_INTERNAL_ASSERT(node < _nodeCount && shapeBegin < shapeEnd); |
||||
|
||||
/* Collision on the left child. If the node is leaf one (no left child
|
||||
exists), do it directly, recurse instead. */ |
||||
const bool collidesLeft = (_nodes[node].rightNode == 0 || _nodes[node].rightNode == 2) ? |
||||
Implementation::collides(a, _shapes[shapeBegin]) : |
||||
collides(a, node+1, shapeBegin, shapeBegin+_nodes[node].rightShape); |
||||
|
||||
/* NOT operation */ |
||||
if(_nodes[node].operation == CompositionOperation::Not) |
||||
return !collidesLeft; |
||||
|
||||
/* Short-circuit evaluation for AND/OR */ |
||||
if((_nodes[node].operation == CompositionOperation::Or) == collidesLeft) |
||||
return collidesLeft; |
||||
|
||||
/* Now the collision result depends only on the right child. Similar to
|
||||
collision on the left child. */ |
||||
return (_nodes[node].rightNode < 2) ? |
||||
Implementation::collides(a, _shapes[shapeBegin+_nodes[node].rightShape]) : |
||||
collides(a, node+_nodes[node].rightNode-1, shapeBegin+_nodes[node].rightShape, shapeEnd); |
||||
} |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
template class MAGNUM_PHYSICS_EXPORT Composition<2>; |
||||
template class MAGNUM_PHYSICS_EXPORT Composition<3>; |
||||
#endif |
||||
|
||||
}} |
||||
@ -0,0 +1,298 @@
|
||||
#ifndef Magnum_Physics_Composition_h |
||||
#define Magnum_Physics_Composition_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::Composition, enum Magnum::Physics::CompositionOperation |
||||
*/ |
||||
|
||||
#include <type_traits> |
||||
#include <utility> |
||||
#include <Utility/Assert.h> |
||||
|
||||
#include "DimensionTraits.h" |
||||
#include "Physics/Physics.h" |
||||
#include "Physics/magnumPhysicsVisibility.h" |
||||
#include "Physics/shapeImplementation.h" |
||||
|
||||
namespace Magnum { namespace Physics { |
||||
|
||||
namespace Implementation { |
||||
template<class> struct ShapeHelper; |
||||
|
||||
template<UnsignedInt dimensions> inline AbstractShape<dimensions>* getAbstractShape(Composition<dimensions>& group, std::size_t i) { |
||||
return group._shapes[i]; |
||||
} |
||||
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>* getAbstractShape(const Composition<dimensions>& group, std::size_t i) { |
||||
return group._shapes[i]; |
||||
} |
||||
} |
||||
|
||||
/** @brief Shape operation */ |
||||
enum class CompositionOperation: UnsignedByte { |
||||
Not, /**< Boolean NOT */ |
||||
And, /**< Boolean AND */ |
||||
Or /**< Boolean OR */ |
||||
}; |
||||
|
||||
/**
|
||||
@brief Composition of shapes |
||||
|
||||
Result of logical operations on shapes. |
||||
See @ref collision-detection for brief introduction. |
||||
*/ |
||||
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT Composition { |
||||
friend Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(Composition<dimensions>&, std::size_t); |
||||
friend const Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(const Composition<dimensions>&, std::size_t); |
||||
friend struct Implementation::ShapeHelper<Composition<dimensions>>; |
||||
|
||||
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 */ |
||||
Plane /**< Plane (3D only) */ |
||||
}; |
||||
#else |
||||
typedef typename Implementation::ShapeDimensionTraits<dimensions>::Type Type; |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Default constructor |
||||
* |
||||
* Creates empty hierarchy. |
||||
*/ |
||||
inline explicit Composition(): _shapeCount(0), _nodeCount(0), _shapes(nullptr), _nodes(nullptr) {} |
||||
|
||||
/**
|
||||
* @brief Unary operation constructor |
||||
* @param operation Unary operation |
||||
* @param a Operand |
||||
*/ |
||||
template<class T> explicit Composition(CompositionOperation operation, T&& a); |
||||
|
||||
/**
|
||||
* @brief Binary operation constructor |
||||
* @param operation Binary operation |
||||
* @param a Left operand |
||||
* @param b Right operand |
||||
*/ |
||||
template<class T, class U> explicit Composition(CompositionOperation operation, T&& a, U&& b); |
||||
|
||||
/** @brief Copy constructor */ |
||||
Composition(const Composition<dimensions>& other); |
||||
|
||||
/** @brief Move constructor */ |
||||
Composition(Composition<dimensions>&& other); |
||||
|
||||
~Composition(); |
||||
|
||||
/** @brief Assigment operator */ |
||||
Composition<dimensions>& operator=(const Composition<dimensions>& other); |
||||
|
||||
/** @brief Move assignment operator */ |
||||
Composition<dimensions>& operator=(Composition<dimensions>&& other); |
||||
|
||||
/** @brief Transformed shape */ |
||||
Composition<dimensions> transformed(const typename DimensionTraits<dimensions>::MatrixType& matrix) const; |
||||
|
||||
/** @brief Count of shapes in the hierarchy */ |
||||
inline std::size_t size() const { return _shapeCount; } |
||||
|
||||
/** @brief Type of shape at given position */ |
||||
inline Type type(std::size_t i) const { return _shapes[i]->type(); } |
||||
|
||||
/** @brief Shape at given position */ |
||||
template<class T> const T& get(std::size_t i) const; |
||||
|
||||
/** @brief Collision with another shape */ |
||||
#ifdef DOXYGEN_GENERATING_OUTPUT |
||||
template<class T> inline bool operator%(const T& other) const { |
||||
#else |
||||
template<class T> inline auto operator%(const T& other) const -> typename std::enable_if<std::is_same<decltype(Implementation::TypeOf<T>::type()), typename Implementation::ShapeDimensionTraits<dimensions>::Type>::value, bool>::type { |
||||
#endif |
||||
Implementation::Shape<T> a(other); |
||||
return collides(&a); |
||||
} |
||||
|
||||
private: |
||||
struct Node { |
||||
std::size_t rightNode, rightShape; |
||||
CompositionOperation operation; |
||||
}; |
||||
|
||||
inline bool collides(const Implementation::AbstractShape<dimensions>* a) const { |
||||
return collides(a, 0, 0, _shapeCount); |
||||
} |
||||
|
||||
bool collides(const Implementation::AbstractShape<dimensions>* a, std::size_t node, std::size_t shapeBegin, std::size_t shapeEnd) const; |
||||
|
||||
template<class T> inline constexpr static std::size_t shapeCount(const T&) { |
||||
return 1; |
||||
} |
||||
inline constexpr static std::size_t shapeCount(const Composition<dimensions>& hierarchy) { |
||||
return hierarchy._shapeCount; |
||||
} |
||||
template<class T> inline constexpr static std::size_t nodeCount(const T&) { |
||||
return 0; |
||||
} |
||||
inline constexpr static std::size_t nodeCount(const Composition<dimensions>& hierarchy) { |
||||
return hierarchy._nodeCount; |
||||
} |
||||
|
||||
template<class T> inline void copyShapes(std::size_t offset, const T& shape) { |
||||
_shapes[offset] = new Implementation::Shape<T>(shape); |
||||
} |
||||
void copyShapes(std::size_t offset, Composition<dimensions>&& other); |
||||
void copyShapes(std::size_t offset, const Composition<dimensions>& other); |
||||
|
||||
template<class T> inline void copyNodes(std::size_t, const T&) {} |
||||
void copyNodes(std::size_t offset, const Composition<dimensions>& other); |
||||
|
||||
std::size_t _shapeCount, _nodeCount; |
||||
Implementation::AbstractShape<dimensions>** _shapes; |
||||
Node* _nodes; |
||||
}; |
||||
|
||||
/** @brief Two-dimensional shape hierarchy */ |
||||
typedef Composition<2> Composition2D; |
||||
|
||||
/** @brief Three-dimensional shape hierarchy */ |
||||
typedef Composition<3> Composition3D; |
||||
|
||||
#ifdef DOXYGEN_GENERATING_OUTPUT |
||||
/** @debugoperator{Magnum::Physics::Composition} */ |
||||
template<UnsignedInt dimensions> Debug operator<<(Debug debug, typename Composition<dimensions>::Type value); |
||||
#endif |
||||
|
||||
/** @relates Composition
|
||||
@brief Collision of shape with Composition |
||||
*/ |
||||
#ifdef DOXYGEN_GENERATING_OUTPUT |
||||
template<UnsignedInt dimensions, class T> inline bool operator%(const T& a, const Composition<dimensions>& b) { |
||||
#else |
||||
template<UnsignedInt dimensions, class T> inline auto operator%(const T& a, const Composition<dimensions>& b) -> typename std::enable_if<std::is_same<decltype(Implementation::TypeOf<T>::type()), typename Implementation::ShapeDimensionTraits<dimensions>::Type>::value, bool>::type { |
||||
#endif |
||||
return b % a; |
||||
} |
||||
|
||||
#ifdef DOXYGEN_GENERATING_OUTPUT |
||||
/** @relates Composition
|
||||
@brief Logical NOT of shape |
||||
*/ |
||||
template<class T> inline Composition<T::Dimensions> operator!(T a); |
||||
|
||||
/** @relates Composition
|
||||
@brief Logical AND of two shapes |
||||
|
||||
[Short-circuit evaluation](http://en.wikipedia.org/wiki/Short-circuit_evaluation)
|
||||
is used here, so this operation can be used for providing simplified shape |
||||
version, because collision with @p b is computed only if @p a collides. |
||||
See @ref collision-detection-shape-simplification for an example. |
||||
*/ |
||||
template<class T> inline Composition<T::Dimensions> operator&&(T a, T b); |
||||
|
||||
/** @relates Composition
|
||||
@brief Logical OR of two shapes |
||||
|
||||
[Short-circuit evaluation](http://en.wikipedia.org/wiki/Short-circuit_evaluation)
|
||||
is used, so if collision with @p a is detected, collision with @p b is not |
||||
computed. |
||||
*/ |
||||
template<class T> inline Composition<T::Dimensions> operator||(T a, T b); |
||||
#endif |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#define enableIfIsShapeType typename std::enable_if< \ |
||||
std::is_same<decltype(Implementation::TypeOf<T>::type()), typename Implementation::ShapeDimensionTraits<T::Dimensions>::Type>::value, \
|
||||
Composition<T::Dimensions>>::type |
||||
#define enableIfAreShapeType typename std::enable_if< \ |
||||
std::is_same<decltype(Implementation::TypeOf<T>::type()), typename Implementation::ShapeDimensionTraits<T::Dimensions>::Type>::value && \
|
||||
std::is_same<decltype(Implementation::TypeOf<U>::type()), typename Implementation::ShapeDimensionTraits<T::Dimensions>::Type>::value, \
|
||||
Composition<T::Dimensions>>::type |
||||
template<class T> inline auto operator!(T&& a) -> enableIfIsShapeType { |
||||
return Composition<T::Dimensions>(CompositionOperation::Not, std::forward<T>(a)); |
||||
} |
||||
template<class T, class U> inline auto operator&&(T&& a, U&& b) -> enableIfAreShapeType { |
||||
return Composition<T::Dimensions>(CompositionOperation::And, std::forward<T>(a), std::forward<U>(b)); |
||||
} |
||||
template<class T, class U> inline auto operator||(T&& a, U&& b) -> enableIfAreShapeType { |
||||
return Composition<T::Dimensions>(CompositionOperation::Or, std::forward<T>(a), std::forward<U>(b)); |
||||
} |
||||
#undef enableIfIsShapeType |
||||
#undef enableIfAreShapeType |
||||
#endif |
||||
|
||||
template<UnsignedInt dimensions> template<class T> Composition<dimensions>::Composition(CompositionOperation operation, T&& a): _shapeCount(shapeCount(a)), _nodeCount(nodeCount(a)+1), _shapes(new Implementation::AbstractShape<dimensions>*[_shapeCount]), _nodes(new Node[_nodeCount]) { |
||||
CORRADE_ASSERT(operation == CompositionOperation::Not, |
||||
"Physics::Composition::Composition(): unary operation expected", ); |
||||
_nodes[0].operation = operation; |
||||
|
||||
/* 0 = no children, 1 = left child only */ |
||||
_nodes[0].rightNode = (nodeCount(a) == 0 ? 0 : 1); |
||||
_nodes[0].rightShape = shapeCount(a); |
||||
copyNodes(1, a); |
||||
copyShapes(0, std::forward<T>(a)); |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> template<class T, class U> Composition<dimensions>::Composition(CompositionOperation operation, T&& a, U&& b): _shapeCount(shapeCount(a) + shapeCount(b)), _nodeCount(nodeCount(a) + nodeCount(b) + 1), _shapes(new Implementation::AbstractShape<dimensions>*[_shapeCount]), _nodes(new Node[_nodeCount]) { |
||||
CORRADE_ASSERT(operation != CompositionOperation::Not, |
||||
"Physics::Composition::Composition(): binary operation expected", ); |
||||
_nodes[0].operation = operation; |
||||
|
||||
/* 0 = no children, 1 = left child only, 2 = right child only, >2 = both */ |
||||
if(nodeCount(a) == 0 && nodeCount(b) == 0) |
||||
_nodes[0].rightNode = 0; |
||||
else if(nodeCount(b) == 0) |
||||
_nodes[0].rightNode = 1; |
||||
else _nodes[0].rightNode = nodeCount(a) + 2; |
||||
|
||||
_nodes[0].rightShape = shapeCount(a); |
||||
copyNodes(1, a); |
||||
copyNodes(nodeCount(a) + 1, b); |
||||
copyShapes(shapeCount(a), std::forward<U>(b)); |
||||
copyShapes(0, std::forward<T>(a)); |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> template<class T> inline const T& Composition<dimensions>::get(std::size_t i) const { |
||||
CORRADE_ASSERT(_shapes[i]->type() == Implementation::TypeOf<T>::type(), |
||||
"Physics::Composition::get(): given shape is not of type" << Implementation::TypeOf<T>::type() << |
||||
"but" << _shapes[i]->type(), *static_cast<T*>(nullptr)); |
||||
return static_cast<Implementation::Shape<T>*>(_shapes[i])->shape; |
||||
} |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -1,58 +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 "ObjectShapeGroup.h" |
||||
|
||||
#include "Physics/AbstractObjectShape.h" |
||||
|
||||
namespace Magnum { namespace Physics { |
||||
|
||||
template<UnsignedInt dimensions> void ObjectShapeGroup<dimensions>::setClean() { |
||||
/* Clean all objects */ |
||||
if(!this->isEmpty()) { |
||||
std::vector<SceneGraph::AbstractObject<dimensions>*> objects(this->size()); |
||||
for(std::size_t i = 0; i != this->size(); ++i) |
||||
objects[i] = (*this)[i]->object(); |
||||
|
||||
objects[0]->setClean(objects); |
||||
} |
||||
|
||||
dirty = false; |
||||
} |
||||
|
||||
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]->collides(shape)) |
||||
return (*this)[i]; |
||||
|
||||
return nullptr; |
||||
} |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
template class MAGNUM_PHYSICS_EXPORT ObjectShapeGroup<2>; |
||||
template class MAGNUM_PHYSICS_EXPORT ObjectShapeGroup<3>; |
||||
#endif |
||||
|
||||
}} |
||||
@ -1,113 +0,0 @@
|
||||
#ifndef Magnum_Physics_ObjectShapeGroup_h |
||||
#define Magnum_Physics_ObjectShapeGroup_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::ObjectShapeGroup, typedef Magnum::Physics::ObjectShapeGroup2D, Magnum::Physics::ObjectShapeGroup3D |
||||
*/ |
||||
|
||||
#include <vector> |
||||
|
||||
#include "Physics/Physics.h" |
||||
#include "SceneGraph/FeatureGroup.h" |
||||
|
||||
#include "magnumPhysicsVisibility.h" |
||||
|
||||
namespace Magnum { namespace Physics { |
||||
|
||||
/**
|
||||
@brief Group of object shapes |
||||
|
||||
See ObjectShape for more information. |
||||
@see @ref scenegraph, ObjectShapeGroup2D, ObjectShapeGroup3D |
||||
*/ |
||||
template<UnsignedInt dimensions> class MAGNUM_PHYSICS_EXPORT ObjectShapeGroup: public SceneGraph::FeatureGroup<dimensions, AbstractObjectShape<dimensions>> { |
||||
friend class AbstractObjectShape<dimensions>; |
||||
|
||||
public: |
||||
/**
|
||||
* @brief Constructor |
||||
* |
||||
* Marks the group as dirty. |
||||
*/ |
||||
inline explicit ObjectShapeGroup(): dirty(true) {} |
||||
|
||||
/**
|
||||
* @brief Whether the group is dirty |
||||
* @return True if any object in the group is dirty, false otherwise. |
||||
*/ |
||||
inline bool isDirty() const { return dirty; } |
||||
|
||||
/**
|
||||
* @brief Set the group as dirty |
||||
* |
||||
* If some body in the group changes its transformation, it sets dirty |
||||
* status also on the group to indicate that the body and maybe also |
||||
* group state needs to be cleaned before computing collisions. |
||||
* |
||||
* @see setClean() |
||||
*/ |
||||
inline void setDirty() { dirty = true; } |
||||
|
||||
/**
|
||||
* @brief Set the group and all bodies as clean |
||||
* |
||||
* This function is called before computing any collisions to ensure |
||||
* all objects are cleaned. |
||||
*/ |
||||
void setClean(); |
||||
|
||||
/**
|
||||
* @brief First collision of given shape with other shapes in the group |
||||
* |
||||
* Returns first shape colliding with given one. If there aren't any |
||||
* collisions, returns `nullptr`. Calls setClean() before the |
||||
* operation. |
||||
*/ |
||||
AbstractObjectShape<dimensions>* firstCollision(const AbstractObjectShape<dimensions>* shape); |
||||
|
||||
private: |
||||
bool dirty; |
||||
}; |
||||
|
||||
/**
|
||||
@brief Group of two-dimensional shaped objects |
||||
|
||||
See ObjectShape for more information. |
||||
@see ObjectShapeGroup3D |
||||
*/ |
||||
typedef ObjectShapeGroup<2> ObjectShapeGroup2D; |
||||
|
||||
/**
|
||||
@brief Group of three-dimensional shaped objects |
||||
|
||||
See ObjectShape for more information. |
||||
@see ObjectShapeGroup2D |
||||
*/ |
||||
typedef ObjectShapeGroup<3> ObjectShapeGroup3D; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
Loading…
Reference in new issue