From 60fe61ee04feffd846ce70839850b147320131a4 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Wed, 19 Jul 2017 17:24:26 +0200 Subject: [PATCH] migrated marshalling/unmarshalling/fcd to new dispatcher --- src/blockforest/BlockDataHandling.h | 13 +- src/pe/collision/Collide.cpp | 0 src/pe/communication/DynamicMarshalling.h | 73 ++++---- src/pe/communication/rigidbody/Union.h | 4 +- .../AnalyticCollisionDetection.h} | 136 ++++++++++++--- src/pe/fcd/GenericFCD.h | 59 +++++++ src/pe/fcd/SimpleFCD.h | 67 +------- src/pe/utility/BodyCast.h | 162 ++++++++++++++++++ src/pe/utility/BodyDispatcher.h | 94 ---------- tests/pe/Collision.cpp | 9 +- tests/pe/SetBodyTypeIDs.cpp | 48 ++++++ 11 files changed, 441 insertions(+), 224 deletions(-) delete mode 100644 src/pe/collision/Collide.cpp rename src/pe/{collision/Collide.h => fcd/AnalyticCollisionDetection.h} (95%) create mode 100644 src/pe/fcd/GenericFCD.h create mode 100644 src/pe/utility/BodyCast.h delete mode 100644 src/pe/utility/BodyDispatcher.h diff --git a/src/blockforest/BlockDataHandling.h b/src/blockforest/BlockDataHandling.h index 099cb9834..a9e612e84 100644 --- a/src/blockforest/BlockDataHandling.h +++ b/src/blockforest/BlockDataHandling.h @@ -69,7 +69,7 @@ public: T * deserialize( IBlock * const block ) { return this->initialize( block ); } T * deserializeCoarseToFine( Block * const block ) { return this->initialize( block ); } T * deserializeFineToCoarse( Block * const block ) { return this->initialize( block ); } - + void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) {} void deserializeCoarseToFine( Block * const, const BlockDataID &, mpi::RecvBuffer & ) {} void deserializeFineToCoarse( Block * const, const BlockDataID &, mpi::RecvBuffer &, const uint_t ) {} @@ -77,6 +77,17 @@ public: +template< typename T > +class AlwaysCreateBlockDataHandling : public AlwaysInitializeBlockDataHandling<T> +{ +public: + ~AlwaysCreateBlockDataHandling() {} + + T * initialize( IBlock * const /*block*/ ) {return new T();} +}; + + + namespace internal { diff --git a/src/pe/collision/Collide.cpp b/src/pe/collision/Collide.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/pe/communication/DynamicMarshalling.h b/src/pe/communication/DynamicMarshalling.h index 121931250..73f222c15 100644 --- a/src/pe/communication/DynamicMarshalling.h +++ b/src/pe/communication/DynamicMarshalling.h @@ -33,6 +33,7 @@ #include "pe/communication/rigidbody/Capsule.h" #include "pe/communication/rigidbody/Sphere.h" #include "pe/communication/rigidbody/Union.h" +#include "pe/utility/BodyCast.h" #include "core/Abort.h" @@ -44,7 +45,19 @@ namespace pe { namespace communication { template < typename BodyTypeTuple > -struct MarshalDynamically{ +class MarshalDynamically{ +private: + struct MarshalFunctor + { + mpi::SendBuffer& buffer_; + + MarshalFunctor(mpi::SendBuffer& buffer) : buffer_(buffer) {} + + template< typename BodyType > + void operator()( const BodyType* bd) { marshal( buffer_, *bd); } + }; + +public: //************************************************************************************************* /*!\brief Marshalling rigid body parameters dynamically. * @@ -57,29 +70,30 @@ struct MarshalDynamically{ */ static void execute(mpi::SendBuffer& buffer, const RigidBody& b) { - static_assert(boost::is_base_of<RigidBody, typename BodyTypeTuple::head_type>::value, "only derived types from RigidBody are allowed!"); - - if (BodyTypeTuple::head_type::getStaticTypeID() == b.getTypeID()) - { - typedef typename BodyTypeTuple::head_type BodyT; - marshal( buffer, static_cast<const BodyT&>(b)); - } else - { - MarshalDynamically<typename BodyTypeTuple::tail_type>::execute(buffer, b); - } + MarshalFunctor func(buffer); + return SingleCast<BodyTypeTuple, MarshalFunctor, void>::execute (&b, func); } }; -template < > -struct MarshalDynamically< boost::tuples::null_type>{ - static void execute(mpi::SendBuffer& /*buffer*/, const RigidBody& b) - { - WALBERLA_ABORT("MarshalDynamically: BodyTypeID " << b.getTypeID() << " could not be resolved!"); - } -}; - template < typename BodyTypeTuple > -struct UnmarshalDynamically{ +class UnmarshalDynamically{ +private: + struct UnmarshalFunctor + { + mpi::RecvBuffer& buffer_; + const math::AABB& domain_; + const math::AABB& block_; + + UnmarshalFunctor(mpi::RecvBuffer& buffer, const math::AABB& domain, const math::AABB& block) + : buffer_(buffer) + , domain_(domain) + , block_(block) {} + + template< typename BodyType > + BodyID operator()( BodyType* bd) { return instantiate( buffer_, domain_, block_, bd ); } + }; + +public: //************************************************************************************************* /*!\brief Marshalling rigid body parameters dynamically. * @@ -92,26 +106,11 @@ struct UnmarshalDynamically{ */ static BodyID execute(mpi::RecvBuffer& buffer, const id_t typeID, const math::AABB& domain, const math::AABB& block) { - if (BodyTypeTuple::head_type::getStaticTypeID() == typeID) - { - typedef typename BodyTypeTuple::head_type BodyT; - BodyT* newBody; - return instantiate( buffer, domain, block, newBody ); - } else - { - return UnmarshalDynamically<typename BodyTypeTuple::tail_type>::execute(buffer, typeID, domain, block); - } + UnmarshalFunctor func(buffer, domain, block); + return SingleCast<BodyTypeTuple, UnmarshalFunctor, BodyID>::execute (typeID, func); } }; -template < > -struct UnmarshalDynamically< boost::tuples::null_type>{ - static BodyID execute(mpi::RecvBuffer& /*buffer*/, const id_t typeID, const math::AABB& /*domain*/, const math::AABB& /*block*/) - { - WALBERLA_ABORT("UnmarshalDynamically: BodyTypeID " << typeID << " could not be resolved!"); - } -}; - } // namespace communication } // namespace pe } // namespace walberla diff --git a/src/pe/communication/rigidbody/Union.h b/src/pe/communication/rigidbody/Union.h index 0850d0231..69c2d6bb1 100644 --- a/src/pe/communication/rigidbody/Union.h +++ b/src/pe/communication/rigidbody/Union.h @@ -37,11 +37,11 @@ namespace communication { //forward declaration template < typename BodyTypeTuple > -struct MarshalDynamically; +class MarshalDynamically; //forward declaration template < typename BodyTypeTuple > -struct UnmarshalDynamically; +class UnmarshalDynamically; struct UnionParameters : public GeomPrimitiveParameters { real_t m_; diff --git a/src/pe/collision/Collide.h b/src/pe/fcd/AnalyticCollisionDetection.h similarity index 95% rename from src/pe/collision/Collide.h rename to src/pe/fcd/AnalyticCollisionDetection.h index 1baf317cc..477779436 100644 --- a/src/pe/collision/Collide.h +++ b/src/pe/fcd/AnalyticCollisionDetection.h @@ -23,14 +23,13 @@ #pragma once #include "pe/Types.h" +#include "pe/contact/Contact.h" #include "pe/rigidbody/Box.h" #include "pe/rigidbody/Capsule.h" #include "pe/rigidbody/Plane.h" #include "pe/rigidbody/Sphere.h" #include "pe/rigidbody/Union.h" -#include "pe/contact/Contact.h" - -#include "GJKEPAHelper.h" +#include "pe/utility/BodyCast.h" #include "core/debug/Debug.h" #include "core/math/RotationMatrix.h" @@ -41,12 +40,107 @@ namespace walberla { namespace pe { - namespace fcd { -//Forward Declaration -template < typename BodyTypeTuple, typename BaseT > -struct DoubleDispatch; -} +namespace analytic { + +template <typename Container> +inline +bool collide( GeomID bd1, GeomID bd2, Container& container ); + +template <typename Container> +inline +bool collide( SphereID s1, SphereID s2, Container& container ); + +template <typename Container> +inline +bool collide( SphereID s, PlaneID p, Container& container ); + +template <typename Container> +inline +bool collide( PlaneID p, SphereID s, Container& container ); +template <typename Container> +inline +bool collide( SphereID s, BoxID b, Container& container ); + +template <typename Container> +inline +bool collide( BoxID b, SphereID s, Container& container ); +template <typename Container> +inline +bool collide( BoxID b1, BoxID b2, Container& container ); +template <typename Container> +inline +bool collide( BoxID b, PlaneID p, Container& container ); + +template <typename Container> +inline +bool collide( PlaneID p, BoxID b, Container& container ); +template <typename Container> +inline +bool collide( CapsuleID c1, CapsuleID c2, Container& container ); +template <typename Container> +inline +bool collide( CapsuleID c, PlaneID p, Container& container ); + +template <typename Container> +inline +bool collide( PlaneID p, CapsuleID c, Container& container ); + +template <typename Container> +inline +bool collide( SphereID s, CapsuleID c, Container& container ); + +template <typename Container> +inline +bool collide( CapsuleID c, SphereID s, Container& container ); + + +template <typename Container> +inline +bool collide( BoxID b, CapsuleID c, Container& container ); + +template <typename Container> +inline +bool collide( CapsuleID c, BoxID b, Container& container ); + +template <typename BodyTypeTuple, typename BodyB, typename Container> +inline +bool collide( Union<BodyTypeTuple>* bd1, BodyB* bd2, Container& container ); + +template <typename BodyA, typename BodyTypeTuple, typename Container> +inline +bool collide( BodyA* bd1, Union<BodyTypeTuple>* bd2, Container& container ); + +template <typename BodyTypeTupleA, typename BodyTypeTupleB, typename Container> +inline +bool collide( Union<BodyTypeTupleA>* bd1, Union<BodyTypeTupleB>* bd2, Container& container ); + +} //namespace analytic + +template <typename Container> +struct AnalyticCollideFunctor +{ + Container& contacts_; + + AnalyticCollideFunctor(Container& contacts) : contacts_(contacts) {} + + template< typename BodyType1, typename BodyType2 > + bool operator()( BodyType1* bd1, BodyType2* bd2) { using namespace analytic; return collide( bd1, bd2, contacts_); } +}; + +template <typename BodyType1, typename Container> +struct AnalyticSingleCollideFunctor +{ + BodyType1* bd1_; + Container& contacts_; + + AnalyticSingleCollideFunctor(BodyType1* bd1, Container& contacts) : bd1_(bd1), contacts_(contacts) {} + + template< typename BodyType2 > + bool operator()( BodyType2* bd2) { using namespace analytic; return collide( bd1_, bd2, contacts_); } +}; + +namespace analytic { //************************************************************************************************* /*!\brief Contact generation between two colliding rigid bodies. @@ -60,21 +154,9 @@ struct DoubleDispatch; */ template <typename Container> inline -bool collide( GeomID bd1, GeomID bd2, Container& container ) +bool collide( GeomID /*bd1*/, GeomID /*bd2*/, Container& /*container*/ ) { WALBERLA_ABORT("UNSUPPORTED COLLISION!"); - Vec3 contactPoint; - Vec3 contactNormal; - real_t penetrationDepth; - - bool collision = collideGJK(bd1, bd2, contactPoint, contactNormal, penetrationDepth); - - if (collision) - { - container.push_back( Contact(bd1, bd2, contactPoint, contactNormal, penetrationDepth) ); - return true; - } - return false; } @@ -2002,10 +2084,11 @@ template <typename BodyTypeTuple, typename BodyB, typename Container> inline bool collide( Union<BodyTypeTuple>* bd1, BodyB* bd2, Container& container ) { + AnalyticSingleCollideFunctor<BodyB, Container> func(bd2, container); bool collision = false; for( auto it=bd1->begin(); it!=bd1->end(); ++it ) { - collision |= fcd::DoubleDispatch< BodyTypeTuple, boost::tuple<BodyB> >::execute(*it, bd2, container); + collision |= SingleCast<BodyTypeTuple, AnalyticSingleCollideFunctor<BodyB, Container>, bool>::execute(*it, func); } return collision; } @@ -2021,16 +2104,19 @@ template <typename BodyTypeTupleA, typename BodyTypeTupleB, typename Container> inline bool collide( Union<BodyTypeTupleA>* bd1, Union<BodyTypeTupleB>* bd2, Container& container ) { + AnalyticCollideFunctor<Container> func(container); bool collision = false; for( auto it1=bd1->begin(); it1!=bd1->end(); ++it1 ) { for( auto it2=bd2->begin(); it2!=bd2->end(); ++it2 ) { - collision |= fcd::DoubleDispatch< BodyTypeTupleA, BodyTypeTupleB >::execute(*it1, *it2, container); + collision |= DoubleCast<BodyTypeTupleA, BodyTypeTupleB, AnalyticCollideFunctor<Container>, bool>::execute(*it1, *it2, func); } } return collision; } -} -} +} //namespace analytic +} //namespace fcd +} //namespace pe +} //namespace walberla diff --git a/src/pe/fcd/GenericFCD.h b/src/pe/fcd/GenericFCD.h new file mode 100644 index 000000000..27a311f3c --- /dev/null +++ b/src/pe/fcd/GenericFCD.h @@ -0,0 +1,59 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GenericFCD.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "IFCD.h" + +#include "pe/utility/BodyCast.h" + +#include "blockforest/BlockDataHandling.h" + +namespace walberla{ +namespace pe{ +namespace fcd { + +/// +/// \brief Uses CollideFunctor to call collide function without additional namespace inclusion. +/// +template <typename BodyTypeTuple, template <typename Container> class CollisionFunctor > +class GenericFCD : public IFCD{ +public: + virtual Contacts& generateContacts(PossibleContacts& possibleContacts) + { + contacts_.clear(); + CollisionFunctor<decltype(contacts_)> func(contacts_); + for (auto it = possibleContacts.begin(); it != possibleContacts.end(); ++it) + { + DoubleCast<BodyTypeTuple, BodyTypeTuple, CollisionFunctor<decltype(contacts_)>, bool>::execute(it->first, it->second, func); + } + return contacts_; + } +}; + +template <typename BodyTypeTuple, template <typename Container> class CollisionFunctor> +shared_ptr< blockforest::AlwaysCreateBlockDataHandling<GenericFCD<BodyTypeTuple, CollisionFunctor> > > createGenericFCDDataHandling() +{ + return make_shared< blockforest::AlwaysCreateBlockDataHandling<GenericFCD<BodyTypeTuple, CollisionFunctor> > >( ); +} + +} +} +} diff --git a/src/pe/fcd/SimpleFCD.h b/src/pe/fcd/SimpleFCD.h index 456d9b73b..ba5e45316 100644 --- a/src/pe/fcd/SimpleFCD.h +++ b/src/pe/fcd/SimpleFCD.h @@ -20,9 +20,8 @@ #pragma once -#include "IFCD.h" - -#include "pe/collision/Collide.h" +#include "AnalyticCollisionDetection.h" +#include "GenericFCD.h" #include <boost/type_traits/is_base_of.hpp> #include <boost/tuple/tuple.hpp> @@ -31,68 +30,10 @@ namespace walberla{ namespace pe{ namespace fcd { -template < typename TypeA, typename TypeListB > -struct SingleDispatch{ - static bool execute(RigidBody* a, RigidBody* b, Contacts& contacts){ - static_assert(boost::is_base_of<RigidBody, typename TypeListB::head_type>::value, "only downcasting allowed!"); - if (TypeListB::head_type::getStaticTypeID() == b->getTypeID()) - { - typedef typename TypeListB::head_type TypeB; - - auto bd1 = static_cast<TypeA *>(a); - auto bd2 = static_cast<TypeB *>(b); - - return collide(bd1, bd2, contacts); - } else - { - return SingleDispatch<TypeA, typename TypeListB::tail_type>::execute(a, b, contacts); - } - } -}; - -template < typename TypeA > -struct SingleDispatch< TypeA, boost::tuples::null_type >{ - static bool execute(RigidBody* /*a*/, RigidBody* b, Contacts& /*contacts*/){ - WALBERLA_ABORT("SingleDispatch: Type of body " << b->getSystemID() << " could not be determined (" << b->getTypeID() << ")"); - return false; - } -}; - -template < typename TypeListA, typename TypeListB = TypeListA> -struct DoubleDispatch{ - static bool execute(RigidBody* a, RigidBody* b, Contacts& contacts){ - // Force a defined order of collision detection across processes - if( b->getSystemID() < a->getSystemID() ) - std::swap( a, b ); - static_assert(boost::is_base_of<RigidBody, typename TypeListA::head_type>::value, "only downcasting allowed!"); - if (TypeListA::head_type::getStaticTypeID() == a->getTypeID()) { - return SingleDispatch<typename TypeListA::head_type, TypeListB>::execute(a, b, contacts); - } else { - return DoubleDispatch<typename TypeListA::tail_type, TypeListB>::execute(a, b, contacts); - } - } -}; - -template < typename TypeListB> -struct DoubleDispatch< boost::tuples::null_type, TypeListB>{ - static bool execute(RigidBody* /*a*/, RigidBody* /*b*/, Contacts& /*contacts*/){ - WALBERLA_ABORT("DoubleDispatch: Type could not be determined"); - return false; - } -}; - template <typename BodyTypeTuple> -class SimpleFCD : public IFCD{ +class SimpleFCD : public GenericFCD<BodyTypeTuple, AnalyticCollideFunctor>{ public: - virtual Contacts& generateContacts(PossibleContacts& possibleContacts) - { - contacts_.clear(); - for (auto it = possibleContacts.begin(); it != possibleContacts.end(); ++it) - { - DoubleDispatch<BodyTypeTuple>::execute(it->first, it->second, contacts_); - } - return contacts_; - } + virtual ~SimpleFCD(){} }; } diff --git a/src/pe/utility/BodyCast.h b/src/pe/utility/BodyCast.h new file mode 100644 index 000000000..93c14befb --- /dev/null +++ b/src/pe/utility/BodyCast.h @@ -0,0 +1,162 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BodyCast.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <core/DataTypes.h> +#include <pe/rigidbody/RigidBody.h> + +#include <boost/tuple/tuple.hpp> + +namespace walberla { +namespace pe { + +template < typename TypeList, typename Functor, typename ReturnType > +class SingleCast +{ +public: + static ReturnType execute(const id_t typeID, Functor& func){ + static_assert(boost::is_base_of<RigidBody, typename TypeList::head_type>::value, "only downcasting allowed!"); + if (TypeList::head_type::getStaticTypeID() == typeID) + { + typedef typename TypeList::head_type CastBodyType; + CastBodyType* bd = NULL; + return func( static_cast<CastBodyType *>( bd ) ); + } else + { + return SingleCast<typename TypeList::tail_type, Functor, ReturnType>::execute(typeID, func); + } + } + + static ReturnType execute(RigidBody* bd, Functor& func){ + static_assert(boost::is_base_of<RigidBody, typename TypeList::head_type>::value, "only downcasting allowed!"); + if (TypeList::head_type::getStaticTypeID() == bd->getTypeID()) + { + typedef typename TypeList::head_type CastBodyType; + return func( static_cast<CastBodyType *>(bd) ); + } else + { + return SingleCast<typename TypeList::tail_type, Functor, ReturnType>::execute(bd, func); + } + } + + static ReturnType execute(const RigidBody* bd, Functor& func){ + static_assert(boost::is_base_of<RigidBody, typename TypeList::head_type>::value, "only downcasting allowed!"); + if (TypeList::head_type::getStaticTypeID() == bd->getTypeID()) + { + typedef typename TypeList::head_type CastBodyType; + return func( static_cast<const CastBodyType *>(bd) ); + } else + { + return SingleCast<typename TypeList::tail_type, Functor, ReturnType>::execute(bd, func); + } + } +}; + +template < typename Functor, typename ReturnType > +struct SingleCast< boost::tuples::null_type, Functor, ReturnType >{ + static ReturnType execute(const id_t typeID, Functor& /*func*/) + { + WALBERLA_ABORT("SingleCast: BodyType could not be determined (" << typeID << ")"); + return ReturnType(); + } + + static ReturnType execute(RigidBody* bd, Functor& /*func*/) + { + WALBERLA_ABORT("SingleCast: Type of body " << bd->getSystemID() << " could not be determined (" << bd->getTypeID() << ")"); + return ReturnType(); + } + static ReturnType execute(const RigidBody* bd, Functor& /*func*/) + { + WALBERLA_ABORT("SingleCast: Type of body " << bd->getSystemID() << " could not be determined (" << bd->getTypeID() << ")"); + return ReturnType(); + } +}; + +template < typename TypeListA, typename TypeListB, typename Functor, typename ReturnType > +class DoubleCast +{ +private: + template< typename BodyType1 > + struct SingleCastFunctor + { + BodyType1* a_; + Functor& func_; + + SingleCastFunctor(BodyType1* a, Functor& func) : a_(a), func_(func) {} + + template< typename BodyType2 > + ReturnType operator()( BodyType2* bd) { return func_( a_, bd); } + }; + template< typename BodyType1 > + struct SingleCastConstFunctor + { + BodyType1 const * a_; + Functor& func_; + + SingleCastConstFunctor(BodyType1 const * a, Functor& func) : a_(a), func_(func) {} + + template< typename BodyType2 > + ReturnType operator()( BodyType2 const * bd) { return func_( a_, bd); } + }; +public: + static ReturnType execute(RigidBody* a, RigidBody* b, Functor& func){ + static_assert(boost::is_base_of<RigidBody, typename TypeListA::head_type>::value, "only downcasting allowed!"); + if (TypeListA::head_type::getStaticTypeID() == a->getTypeID()) + { + typedef typename TypeListA::head_type CastBodyType; + SingleCastFunctor<CastBodyType> singleFunc( static_cast<CastBodyType *>(a), func); + return SingleCast<TypeListB, SingleCastFunctor<CastBodyType>, ReturnType>::execute(b, singleFunc ); + } else + { + return DoubleCast<typename TypeListA::tail_type, TypeListB, Functor, ReturnType>::execute(a, b, func); + } + } + + static ReturnType execute(const RigidBody* a, const RigidBody* b, Functor& func){ + static_assert(boost::is_base_of<RigidBody, typename TypeListA::head_type>::value, "only downcasting allowed!"); + if (TypeListA::head_type::getStaticTypeID() == a->getTypeID()) + { + typedef typename TypeListA::head_type CastBodyType; + SingleCastConstFunctor<CastBodyType> singleFunc( static_cast<CastBodyType *>(a), func); + return SingleCast<TypeListB, SingleCastConstFunctor<CastBodyType>, ReturnType>::execute(b, singleFunc ); + } else + { + return DoubleCast<typename TypeListA::tail_type, TypeListB, Functor, ReturnType>::execute(a, b, func); + } + } +}; + +template < typename TypeListB, typename Functor, typename ReturnType > +struct DoubleCast< boost::tuples::null_type, TypeListB, Functor, ReturnType >{ + static ReturnType execute(RigidBody* a, RigidBody* /*b*/, Functor& /*func*/) + { + WALBERLA_ABORT("DoubleCast: Type of body " << a->getSystemID() << " could not be determined (" << a->getTypeID() << ")"); + return ReturnType(); + } + static ReturnType execute(const RigidBody* a, const RigidBody* b, Functor& /*func*/) + { + WALBERLA_ABORT("DoubleCast: Type of body " << a->getSystemID() << " could not be determined (" << a->getTypeID() << ")"); + return ReturnType(); + } +}; + +} // namespace pe +} // namespace walberla diff --git a/src/pe/utility/BodyDispatcher.h b/src/pe/utility/BodyDispatcher.h deleted file mode 100644 index f2c66b51f..000000000 --- a/src/pe/utility/BodyDispatcher.h +++ /dev/null @@ -1,94 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla is free software: you can -// redistribute it and/or modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation, either version 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file BodyDispatcher.h -//! \author Sebastian Eibl <sebastian.eibl@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include <core/DataTypes.h> -#include <pe/rigidbody/RigidBody.h> - -#include <boost/tuple/tuple.hpp> - -namespace walberla { -namespace pe { - -template < typename TypeList, typename Functor, typename ReturnType > -class SingleDispatch -{ -public: - static ReturnType execute(const id_t typeID, Functor& func){ - static_assert(boost::is_base_of<RigidBody, typename TypeList::head_type>::value, "only downcasting allowed!"); - if (TypeList::head_type::getStaticTypeID() == typeID) - { - typedef typename TypeList::head_type BodyType; - BodyType* bd = NULL; - return func( static_cast<BodyType *>( bd ) ); - } else - { - return SingleDispatch<typename TypeList::tail_type, Functor, ReturnType>::execute(typeID, func); - } - } - - static ReturnType execute(RigidBody* bd, Functor& func){ - static_assert(boost::is_base_of<RigidBody, typename TypeList::head_type>::value, "only downcasting allowed!"); - if (TypeList::head_type::getStaticTypeID() == bd->getTypeID()) - { - typedef typename TypeList::head_type BodyType; - return func( static_cast<BodyType *>(bd) ); - } else - { - return SingleDispatch<typename TypeList::tail_type, Functor, ReturnType>::execute(bd, func); - } - } - - static ReturnType execute(const RigidBody* bd, Functor& func){ - static_assert(boost::is_base_of<RigidBody, typename TypeList::head_type>::value, "only downcasting allowed!"); - if (TypeList::head_type::getStaticTypeID() == bd->getTypeID()) - { - typedef typename TypeList::head_type BodyType; - return func( static_cast<const BodyType *>(bd) ); - } else - { - return SingleDispatch<typename TypeList::tail_type, Functor, ReturnType>::execute(bd, func); - } - } -}; - -template < typename Functor, typename ReturnType > -struct SingleDispatch< boost::tuples::null_type, Functor, ReturnType >{ - static ReturnType execute(const id_t typeID, Functor& /*func*/) - { - WALBERLA_ABORT("SingleDispatch: BodyType could not be determined (" << typeID << ")"); - return ReturnType(); - } - - static ReturnType execute(RigidBody* bd, Functor& /*func*/) - { - WALBERLA_ABORT("SingleDispatch: Type of body " << bd->getSystemID() << " could not be determined (" << bd->getTypeID() << ")"); - return ReturnType(); - } - static ReturnType execute(const RigidBody* bd, Functor& /*func*/) - { - WALBERLA_ABORT("SingleDispatch: Type of body " << bd->getSystemID() << " could not be determined (" << bd->getTypeID() << ")"); - return ReturnType(); - } -}; - -} // namespace pe -} // namespace walberla diff --git a/tests/pe/Collision.cpp b/tests/pe/Collision.cpp index faa5a5f42..600534e8a 100644 --- a/tests/pe/Collision.cpp +++ b/tests/pe/Collision.cpp @@ -18,8 +18,9 @@ // //====================================================================================================================== -#include "pe/collision/Collide.h" #include "pe/collision/GJKEPAHelper.h" +#include "pe/fcd/AnalyticCollisionDetection.h" +#include "pe/utility/BodyCast.h" #include "pe/contact/Contact.h" #include "pe/fcd/SimpleFCD.h" @@ -40,6 +41,7 @@ using namespace walberla; using namespace walberla::pe; +using walberla::pe::fcd::analytic::collide; void checkContact(const Contact& c1, const Contact& c2) { @@ -256,9 +258,12 @@ void UnionTest() std::vector<Contact> contacts; + using namespace walberla::pe::fcd; // SPHERE <-> SPHERE WALBERLA_LOG_INFO("UNION <-> UNION"); - fcd::DoubleDispatch< boost::tuple<UnionT, Sphere> >::execute(&un1, &un2, contacts); + AnalyticCollideFunctor< std::vector<Contact> > func(contacts); + DoubleCast<boost::tuple<UnionT, Sphere>, boost::tuple<UnionT, Sphere>, AnalyticCollideFunctor< std::vector<Contact> >, bool>::execute(&un1, &un2, func); + checkContact( contacts.at(0), Contact( sp1, sp2, Vec3(real_t(0.75), 0, 0), Vec3(-1, 0, 0), real_t(-0.5)) ); } diff --git a/tests/pe/SetBodyTypeIDs.cpp b/tests/pe/SetBodyTypeIDs.cpp index dee15759d..9e99059b2 100644 --- a/tests/pe/SetBodyTypeIDs.cpp +++ b/tests/pe/SetBodyTypeIDs.cpp @@ -20,6 +20,8 @@ #include "core/debug/TestSubsystem.h" +#include "pe/Materials.h" + #include "pe/rigidbody/SetBodyTypeIDs.h" #include "pe/rigidbody/Box.h" @@ -28,6 +30,8 @@ #include "pe/rigidbody/Sphere.h" #include "pe/rigidbody/Union.h" +#include "pe/utility/BodyCast.h" + namespace walberla { namespace pe { @@ -85,6 +89,25 @@ id_t C::staticTypeID_ = 100; using namespace walberla::pe; +struct SingleTypeFunctor +{ + std::vector<walberla::id_t> ids_; + + void operator()( const BodyID /*bd*/) { } + void operator()( const SphereID /*bd*/) { ids_.push_back(Sphere::getStaticTypeID()); } + void operator()( const BoxID /*bd*/) { ids_.push_back(Box::getStaticTypeID()); } + void operator()( const CapsuleID /*bd*/) { ids_.push_back(Capsule::getStaticTypeID()); } +}; + +struct DoubleTypeFunctor +{ + std::vector<walberla::id_t> ids_; + + void operator()( const BodyID /*bd1*/, const BodyID /*bd2*/) { } + void operator()( const BoxID /*bd1*/, const CapsuleID /*bd2*/) { ids_.push_back(Box::getStaticTypeID()); ids_.push_back(Capsule::getStaticTypeID()); } + void operator()( const CapsuleID /*bd1*/, const CapsuleID /*bd2*/) { ids_.push_back(5); } +}; + int main( int argc, char** argv ) { walberla::debug::enterTestMode(); @@ -108,5 +131,30 @@ int main( int argc, char** argv ) WALBERLA_CHECK_UNEQUAL(Plane::getStaticTypeID(), Box::getStaticTypeID()); WALBERLA_CHECK_UNEQUAL(Plane::getStaticTypeID(), Capsule::getStaticTypeID()); + SingleTypeFunctor singleFunc; + Box bx (0, 0, Vec3(0), Vec3(0), Quat(), Vec3(1), Material::find("iron"), false, false, false); + Capsule cap(0, 0, Vec3(0), Vec3(0), Quat(), 1, 1, Material::find("iron"), false, false, false); + + SingleCast<BodyTuple2, SingleTypeFunctor, void>::execute(Box::getStaticTypeID(), singleFunc); + SingleCast<BodyTuple2, SingleTypeFunctor, void>::execute(Capsule::getStaticTypeID(), singleFunc); + WALBERLA_CHECK_EQUAL( singleFunc.ids_.size(), 2); + WALBERLA_CHECK_EQUAL( singleFunc.ids_[0], Box::getStaticTypeID()); + WALBERLA_CHECK_EQUAL( singleFunc.ids_[1], Capsule::getStaticTypeID()); + + singleFunc.ids_.clear(); + SingleCast<BodyTuple2, SingleTypeFunctor, void>::execute(&bx, singleFunc); + SingleCast<BodyTuple2, SingleTypeFunctor, void>::execute(&cap, singleFunc); + WALBERLA_CHECK_EQUAL( singleFunc.ids_.size(), 2); + WALBERLA_CHECK_EQUAL( singleFunc.ids_[0], Box::getStaticTypeID()); + WALBERLA_CHECK_EQUAL( singleFunc.ids_[1], Capsule::getStaticTypeID()); + + DoubleTypeFunctor doubleFunc; + DoubleCast<BodyTuple2, BodyTuple2, DoubleTypeFunctor, void>::execute(&bx, &cap, doubleFunc); + DoubleCast<BodyTuple2, BodyTuple2, DoubleTypeFunctor, void>::execute(&cap, &cap, doubleFunc); + WALBERLA_CHECK_EQUAL( doubleFunc.ids_.size(), 3); + WALBERLA_CHECK_EQUAL( doubleFunc.ids_[0], Box::getStaticTypeID()); + WALBERLA_CHECK_EQUAL( doubleFunc.ids_[1], Capsule::getStaticTypeID());; + WALBERLA_CHECK_EQUAL( doubleFunc.ids_[2], 5);; + return EXIT_SUCCESS; } -- GitLab