mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
7.7 KiB
177 lines
7.7 KiB
#ifndef Magnum_Physics_ShapeGroup_h |
|
#define Magnum_Physics_ShapeGroup_h |
|
/* |
|
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
This file is part of Magnum. |
|
|
|
Magnum is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU Lesser General Public License version 3 |
|
only, as published by the Free Software Foundation. |
|
|
|
Magnum is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU Lesser General Public License version 3 for more details. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class Magnum::Physics::ShapeGroup |
|
*/ |
|
|
|
#include "AbstractShape.h" |
|
|
|
namespace Magnum { namespace Physics { |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
#define enableIfIsBaseType typename std::enable_if<std::is_base_of<AbstractShape, T>::value, ShapeGroup>::type |
|
#define enableIfAreBaseType typename std::enable_if<std::is_base_of<AbstractShape, T>::value && std::is_base_of<AbstractShape, U>::value, ShapeGroup>::type |
|
#endif |
|
|
|
/** |
|
@brief Collider group with defined set operation |
|
|
|
Result of union, intersection, substraction or XOR of two collider objects. |
|
See @ref CollisionDetection for brief introduction. |
|
*/ |
|
class PHYSICS_EXPORT ShapeGroup: public AbstractShape { |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
template<class T> friend constexpr enableIfIsBaseType operator~(const T& a); |
|
template<class T> friend constexpr enableIfIsBaseType operator~(T&& a); |
|
template<class T> friend constexpr enableIfIsBaseType operator~(T& a); |
|
|
|
#define friendOp(char) \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(const T& a, const U& b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(const T& a, U&& b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(T&& a, const U& b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(T&& a, U&& b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(const T& a, std::reference_wrapper<U> b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(T&& a, std::reference_wrapper<U> b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(std::reference_wrapper<T> a, const U& b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(std::reference_wrapper<T> a, U&& b); \ |
|
template<class T, class U> friend constexpr enableIfAreBaseType operator char(std::reference_wrapper<T> a, std::reference_wrapper<U> b); |
|
friendOp(|) |
|
friendOp(&) |
|
friendOp(-) |
|
friendOp(^) |
|
#undef friendOp |
|
#endif |
|
|
|
ShapeGroup(const ShapeGroup& other) = delete; |
|
ShapeGroup& operator=(const ShapeGroup& other) = delete; |
|
|
|
private: |
|
enum Operation { |
|
RefA = 0x01, |
|
RefB = 0x02, |
|
RefAB = 0x03, |
|
Complement = 1 << 2, |
|
Union = 2 << 2, |
|
Intersection = 3 << 2, |
|
Difference = 4 << 2, |
|
Xor = 5 << 2, |
|
FirstObjectOnly = 6 << 2, |
|
AlwaysFalse = 7 << 2 |
|
}; |
|
|
|
public: |
|
/** @brief Default constructor */ |
|
inline ShapeGroup(): operation(AlwaysFalse), a(nullptr), b(nullptr) {} |
|
|
|
/** @brief Move constructor */ |
|
ShapeGroup(ShapeGroup&& other); |
|
|
|
/** @brief Destructor */ |
|
~ShapeGroup(); |
|
|
|
/** @brief Move assignment */ |
|
ShapeGroup& operator=(ShapeGroup&& other); |
|
|
|
void applyTransformation(const Matrix4& transformation); |
|
|
|
bool collides(const AbstractShape* other) const; |
|
|
|
protected: |
|
virtual Type type() const { return Type::ShapeGroup; } |
|
|
|
private: |
|
inline ShapeGroup(int operation, AbstractShape* a, AbstractShape* b): operation(operation), a(a), b(b) {} |
|
|
|
int operation; |
|
AbstractShape* a; |
|
AbstractShape* b; |
|
}; |
|
|
|
/** @brief Complement of shape */ |
|
template<class T> inline constexpr enableIfIsBaseType operator~(const T& a) { |
|
return ShapeGroup(ShapeGroup::Complement, new T(a), nullptr); |
|
} |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
template<class T> inline constexpr enableIfIsBaseType operator~(T&& a) { |
|
return ShapeGroup(ShapeGroup::Complement, new T(std::forward<T>(a)), nullptr); |
|
} |
|
template<class T> inline constexpr enableIfIsBaseType operator~(T& a) { |
|
return ShapeGroup(ShapeGroup::Complement|ShapeGroup::RefA, &a.get(), nullptr); |
|
} |
|
#endif |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
/** @brief Union of two shapes */ |
|
template<class T, class U> inline constexpr ShapeGroup operator&(T a, U b); |
|
|
|
/** |
|
@brief Intersection of two shapes |
|
|
|
Collision with @p a is computed first, so this operation can be also used for |
|
providing simplified version for shape @p b. See @ref CollisionDetectionShapeGroups |
|
for an example. |
|
*/ |
|
template<class T, class U> inline constexpr ShapeGroup operator&(T a, U b); |
|
|
|
/** @brief Difference of two shapes */ |
|
template<class T, class U> inline constexpr ShapeGroup operator-(T a, U b); |
|
|
|
/** @brief XOR of two shapes */ |
|
template<class T, class U> inline constexpr ShapeGroup operator^(T a, U b); |
|
#else |
|
#define op(type, char) \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(const T& a, const U& b) { \ |
|
return ShapeGroup(ShapeGroup::type, new T(a), new U(b)); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(const T& a, U&& b) { \ |
|
return ShapeGroup(ShapeGroup::type, new T(a), new U(std::forward<U>(b))); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(T&& a, const U& b) { \ |
|
return ShapeGroup(ShapeGroup::type, new T(std::forward<T>(a)), new U(b)); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(T&& a, U&& b) { \ |
|
return ShapeGroup(ShapeGroup::type, new T(std::forward<T>(a)), new U(std::forward<U>(b))); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(const T& a, std::reference_wrapper<U> b) { \ |
|
return ShapeGroup(ShapeGroup::type|ShapeGroup::RefB, new T(a), &b.get()); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(T&& a, std::reference_wrapper<U> b) { \ |
|
return ShapeGroup(ShapeGroup::type|ShapeGroup::RefB, new T(std::forward<T>(a)), &b.get()); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(std::reference_wrapper<T> a, const U& b) { \ |
|
return ShapeGroup(ShapeGroup::type|ShapeGroup::RefA, &a.get(), new U(b)); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(std::reference_wrapper<T> a, U&& b) { \ |
|
return ShapeGroup(ShapeGroup::type|ShapeGroup::RefA, &a.get(), new U(std::forward<U>(b))); \ |
|
} \ |
|
template<class T, class U> inline constexpr enableIfAreBaseType operator char(std::reference_wrapper<T> a, std::reference_wrapper<U> b) { \ |
|
return ShapeGroup(ShapeGroup::type|ShapeGroup::RefAB, &a.get(), &b.get()); \ |
|
} |
|
op(Union, |) |
|
op(Intersection, &) |
|
op(Difference, -) |
|
op(Xor, ^) |
|
#undef op |
|
#endif |
|
|
|
#undef enableIfIsBaseType |
|
#undef enableIfAreBaseType |
|
|
|
}} |
|
|
|
#endif
|
|
|