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