diff --git a/src/pe/fcd/IterativeCollideFunctor.h b/src/pe/fcd/GJKEPACollideFunctor.h similarity index 85% rename from src/pe/fcd/IterativeCollideFunctor.h rename to src/pe/fcd/GJKEPACollideFunctor.h index afdccd914acbeba8a25b893606647e4dce2d8d4d..84b6d62e4bf58386aae3e2f4b94484647511854c 100644 --- a/src/pe/fcd/IterativeCollideFunctor.h +++ b/src/pe/fcd/GJKEPACollideFunctor.h @@ -13,7 +13,7 @@ // 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 IterativeCollideFunctor.h +//! \file GJKEPACollideFunctor.h //! \author Tobias Leemann //! \author Sebastian Eibl <sebastian.eibl@fau.de> // @@ -33,7 +33,7 @@ namespace walberla{ namespace pe{ namespace fcd { -namespace iterative{ +namespace gjkepa{ //function for all single rigid bodies. template<typename Container> @@ -67,41 +67,41 @@ namespace iterative{ inline bool generateContacts(Plane *a, Union<BodyTupleB> *b, Container& contacts_); } -/* Iterative Collide Functor for contact Generation with iterative collision detection. - * Usage: fcd::GenericFCD<BodyTuple, fcd::IterativeCollideFunctor> testFCD; +/* Iterative Collide Functor for contact Generation with iterative collision detection (GJK and EPA algorithms). + * Usage: fcd::GenericFCD<BodyTuple, fcd::GJKEPACollideFunctor> testFCD; * testFCD.generateContacts(...); */ template <typename Container> -struct IterativeCollideFunctor +struct GJKEPACollideFunctor { Container& contacts_; - IterativeCollideFunctor(Container& contacts) : contacts_(contacts) {} + GJKEPACollideFunctor(Container& contacts) : contacts_(contacts) {} template< typename BodyType1, typename BodyType2 > bool operator()( BodyType1* bd1, BodyType2* bd2) { - using namespace iterative; + using namespace gjkepa; return generateContacts(bd1, bd2, contacts_); } }; template <typename BodyType1, typename Container> -struct IterativeSingleCollideFunctor +struct GJKEPASingleCollideFunctor { BodyType1* bd1_; Container& contacts_; - IterativeSingleCollideFunctor(BodyType1* bd1, Container& contacts) : bd1_(bd1), contacts_(contacts) {} + GJKEPASingleCollideFunctor(BodyType1* bd1, Container& contacts) : bd1_(bd1), contacts_(contacts) {} template< typename BodyType2 > bool operator()( BodyType2* bd2) { - using namespace iterative; + using namespace gjkepa; return generateContacts( bd1_, bd2, contacts_); } }; -namespace iterative{ +namespace gjkepa{ //function for all single rigid bodies. template<typename Container> @@ -164,11 +164,11 @@ namespace iterative{ //Unions template<typename BodyTupleA, typename BodyB, typename Container> inline bool generateContacts(Union<BodyTupleA> *a, BodyB *b, Container& contacts_){ - IterativeSingleCollideFunctor<BodyB, Container> func(b, contacts_); + GJKEPASingleCollideFunctor<BodyB, Container> func(b, contacts_); bool collision = false; for( auto it=a->begin(); it!=a->end(); ++it ) { - collision |= SingleCast<BodyTupleA, IterativeSingleCollideFunctor<BodyB, Container>, bool>::execute(*it, func); + collision |= SingleCast<BodyTupleA, GJKEPASingleCollideFunctor<BodyB, Container>, bool>::execute(*it, func); } return collision; } @@ -180,13 +180,13 @@ namespace iterative{ template<typename BodyTupleA, typename BodyTupleB, typename Container> inline bool generateContacts(Union<BodyTupleA> *a, Union<BodyTupleB> *b, Container& contacts_){ - IterativeCollideFunctor<Container> func(contacts_); + GJKEPACollideFunctor<Container> func(contacts_); bool collision = false; for( auto it1=a->begin(); it1!=a->end(); ++it1 ) { for( auto it2=b->begin(); it2!=b->end(); ++it2 ) { - collision |= DoubleCast<BodyTupleA, BodyTupleB, IterativeCollideFunctor<Container>, bool>::execute(*it1, *it2, func); + collision |= DoubleCast<BodyTupleA, BodyTupleB, GJKEPACollideFunctor<Container>, bool>::execute(*it1, *it2, func); } } return collision; @@ -195,11 +195,11 @@ namespace iterative{ //Union and Plane (these calls are ambigous if not implemented seperatly) template<typename BodyTupleA, typename Container> inline bool generateContacts(Union<BodyTupleA> *a, Plane *b, Container& contacts_){ - IterativeSingleCollideFunctor<Plane, Container> func(b, contacts_); + GJKEPASingleCollideFunctor<Plane, Container> func(b, contacts_); bool collision = false; for( auto it=a->begin(); it!=a->end(); ++it ) { - collision |= SingleCast<BodyTupleA, IterativeSingleCollideFunctor<Plane, Container>, bool>::execute(*it, func); + collision |= SingleCast<BodyTupleA, GJKEPASingleCollideFunctor<Plane, Container>, bool>::execute(*it, func); } return collision; } @@ -210,7 +210,7 @@ namespace iterative{ } -} //namespace iterative +} //namespace gjkepa } //fcd diff --git a/src/pe/fcd/IterativeFCD.h b/src/pe/fcd/IterativeFCD.h deleted file mode 100644 index 61c2195c30107d928dceafc578d43ec98a226ef3..0000000000000000000000000000000000000000 --- a/src/pe/fcd/IterativeFCD.h +++ /dev/null @@ -1,209 +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 IterativeFCD.h -//! \author Tobias Leemann <tobias.leemann@fau.de> -// -//====================================================================================================================== - - -#pragma once - -#include "IFCD.h" -#include "pe/Types.h" -#include "pe/collision/EPA.h" -#include "pe/collision/GJK.h" -#include "pe/rigidbody/Plane.h" -#include "pe/rigidbody/Plane.h" -#include <pe/Thresholds.h> -#include <boost/tuple/tuple.hpp> - -namespace walberla{ -namespace pe{ -namespace fcd { - -/** - * \ingroup pe - * \brief Implementation of the IFCD Interface with an iterative detection. - * - * This Class implements a collision detection compatible with the - * IFCD interface. It detects collisions using an iterative technique which employs - * the GJK and EPA algorithms. - */ -template <typename BodyTypeTuple> -class IterativeFCD : public IFCD { - typedef Union< boost::tuple<BodyTypeTuple>> UnionGenericType; - -private: - /*!\brief This computes a collision between two rigid bodies. - * - * \param a The first body (must not be a Plane or Union). - * \param b The second body (must not be a Plane or Union). - * \param normal Returns the normal vector of the collision. - * \param contactPoint Returns a point of contact btw. the bodies. - * \param penetrationDepth Returns the depth. - * \return True, if the bodies collide. - * - * The Return parameters remain untouched if there is no collision. - * This function performes collision detection with bodies enlarged by a margin for numerical reasons. - * See "Collision detection in interactive 3D environments" by Gino van den Bergen - * for a detailed explanation of the algorithm used. - */ - bool performIterativeDetection(GeomPrimitive &a, GeomPrimitive &b, Vec3& normal, Vec3& contactPoint, real_t& penetrationDepth){ - real_t margin = real_t(1e-4); - GJK gjk; - if(gjk.doGJKmargin(a, b, margin)){ - //2. If collision is possible perform EPA. - EPA epa; - return epa.doEPAmargin(a, b, gjk, normal, contactPoint, penetrationDepth, margin); - }else{ - return false; - } - } - - /*!\brief This computes a collision between a Plane and another body. - * - * \param pl The Plane. - * \param b The second body (must not be a Plane or Union). - * \param normal Returns the normal vector of the collision. - * \param contactPoint Returns a point of contact btw. the bodies. - * \param penetrationDepth Returns the depth. - * \return True, if the Plane and the body collide. - * - * The Return parameters remain untouched if there is no collision. - */ - bool performPlaneDetection(Plane &pl, GeomPrimitive &b, Vec3& normal, Vec3& contactPoint, real_t& penetrationDepth){ - Vec3 support_dir = -pl.getNormal(); - - // We now have a direction facing to the "wall". - // Compute support point of body b in this direction. This will be the furthest point overlapping. - - Vec3 contactp = b.support(support_dir); - //std::cerr << contactp << std::endl; - //std::cerr << pl.getDisplacement() <<std::endl; - real_t pdepth = contactp * pl.getNormal() - pl.getDisplacement(); - if(pdepth < contactThreshold){ //We have a collision - normal = support_dir; - penetrationDepth = pdepth; - contactPoint = contactp + real_t(0.5) * penetrationDepth * normal; - return true; - }else{ //No collision - return false; - } - } - - /*!\brief This function adds contacts for single bodies (not unions) - * - * \param bd1 The first body. - * \param bd2 The second body. - * - * This function is called by generateContactsPair() on all normal (single) - * body pairs and on each single bodys of the union. - * It checks if one of the bodies is a plane and calls the corresponding - * detection function. If collision is detected a Contact is generated and - * added to the vector. - */ - void generateContactsSingle(BodyID bd1, BodyID bd2){ - //Temporary Storage for data - Vec3 normal; - Vec3 contactPoint; - real_t penetrationDepth; - - //Check if one primitive is a plane - if(bd1->getTypeID() == Plane::getStaticTypeID()){ - if(!(bd2->getTypeID() == Plane::getStaticTypeID())){ - //First object is a plane, second is not - Plane* pl = static_cast<Plane*>(bd1); - GeomPrimitive *gb = static_cast<GeomPrimitive*>(bd2); - if (performPlaneDetection(*pl, *gb, normal, contactPoint, penetrationDepth)){ - contacts_.push_back( Contact(pl, gb, contactPoint, normal, penetrationDepth) ); - } - }else{ - return; //Plane plane collisions cannot be handled here. - } - }else if(bd2->getTypeID() == Plane::getStaticTypeID()){ - if(!(bd1->getTypeID() == Plane::getStaticTypeID())){ - //Second object is a plane, first is not - Plane* pl = static_cast<Plane*>(bd2); - GeomPrimitive *ga = static_cast<GeomPrimitive*>(bd1); - if (performPlaneDetection(*pl, *ga, normal, contactPoint, penetrationDepth)){ - contacts_.push_back( Contact(ga, pl, contactPoint, -normal, penetrationDepth) ); - } - } - }else{ // Both objects are geometries. - GeomPrimitive *ga = static_cast<GeomPrimitive*>(bd1); - GeomPrimitive *gb = static_cast<GeomPrimitive*>(bd2); - - if (performIterativeDetection(*ga, *gb, normal, contactPoint, penetrationDepth)){ - contacts_.push_back( Contact(ga, gb, contactPoint, normal, penetrationDepth) ); - } - } - } - - /* Resolve pairs with unions and call generateContacts single for each pair of non-united - * particles. - */ - void generateContactsPair(BodyID bd1, BodyID bd2){ - bool hasSubbodies1 = bd1->hasSubBodies(); - if( hasSubbodies1 ){ - UnionGenericType* u1 = nullptr; - u1= static_cast<UnionGenericType*>(bd1); - //Loop over possible subbodies of first rigid body - auto it1 = u1->begin(); - while(it1 != u1->end()){ - generateContactsPair(*it1, bd2); - it1++; - } - }else{ - //bd1 is a single body - bool hasSubbodies2 = bd2->hasSubBodies(); - if( hasSubbodies2 ){ - UnionGenericType* u2 = nullptr; - u2= static_cast<UnionGenericType*>(bd2); - auto it2 = u2->begin(); - while(it2 != u2->end()){ - generateContactsPair(bd1, *it2); - it2++; - } - }else{ - //bd1 and bd2 are single bodies - generateContactsSingle(bd1, bd2); - } - } - } - -public: - /*!\brief Checks each body pair in the given vector and generates - * a vector of contacts. - * - * \param possibleContacts Vector of body pairs thay may collide. - * \return Vector of contacts with information of all contacts generated. - */ - virtual Contacts& generateContacts(PossibleContacts& possibleContacts) - { - contacts_.clear(); - for (auto it = possibleContacts.begin(); it != possibleContacts.end(); ++it) - { - generateContactsPair(it->first, it->second); - } - return contacts_; - } - -}; - - -} -} -} diff --git a/src/pe/fcd/IterativeFCDDataHandling.h b/src/pe/fcd/IterativeFCDDataHandling.h deleted file mode 100644 index c4bb3e2515f69a0525b493a3c349979e308e3fcd..0000000000000000000000000000000000000000 --- a/src/pe/fcd/IterativeFCDDataHandling.h +++ /dev/null @@ -1,46 +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 IterativeFCDDataHandling.h -//! \author Sebastian Eibl <sebastian.eibl@fau.de> -//! \author Tobias Leemann <tobias.leemann@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "IterativeFCD.h" - -#include "blockforest/BlockDataHandling.h" - -namespace walberla{ -namespace pe{ -namespace fcd { - -template <typename BodyTypeTuple> -class IterativeFCDDataHandling : public blockforest::AlwaysInitializeBlockDataHandling<IterativeFCD<BodyTypeTuple>>{ -public: - IterativeFCD<BodyTypeTuple> * initialize( IBlock * const /*block*/ ) {return new IterativeFCD<BodyTypeTuple>();} -}; - -template <typename BodyTypeTuple> -shared_ptr<IterativeFCDDataHandling<BodyTypeTuple>> createIterativeFCDDataHandling() -{ - return make_shared<IterativeFCDDataHandling<BodyTypeTuple>>( ); -} - -} -} -} diff --git a/tests/pe/CollisionTobiasGJK.cpp b/tests/pe/CollisionTobiasGJK.cpp index af02c7f7a877b46bd32c7fe6b81718630a50aa9b..d4fd8c1f2e6757a223d3ed868a54b893a51b72b5 100644 --- a/tests/pe/CollisionTobiasGJK.cpp +++ b/tests/pe/CollisionTobiasGJK.cpp @@ -21,11 +21,10 @@ #include "pe/contact/Contact.h" -#include "pe/fcd/IFCD.h" +//#include "pe/fcd/IFCD.h" #include "pe/fcd/GenericFCD.h" -#include "pe/fcd/IterativeFCD.h" #include "pe/fcd/AnalyticCollisionDetection.h" -#include "pe/fcd/IterativeCollideFunctor.h" +#include "pe/fcd/GJKEPACollideFunctor.h" #include "pe/Materials.h" #include "pe/rigidbody/Box.h" @@ -288,7 +287,7 @@ void PlaneTest() { WALBERLA_LOG_INFO("PLANE AND INTERFACE TEST"); MaterialID iron = Material::find("iron"); - fcd::GenericFCD<BodyTuple, fcd::IterativeCollideFunctor> testFCD; + fcd::GenericFCD<BodyTuple, fcd::GJKEPACollideFunctor> testFCD; Plane pl(1, 1, Vec3(0, 1, 0), Vec3(0, 1, 0), real_t(1.0), iron ); Sphere sphere(2, 2, Vec3(0, real_t(1.9), 0), Vec3(0,0,0), Quat(), 1, iron, false, true, false); @@ -349,7 +348,7 @@ void PlaneTest() void UnionTest(){ WALBERLA_LOG_INFO("UNION AND INTERFACE TEST"); MaterialID iron = Material::find("iron"); - fcd::GenericFCD<BodyTuple, fcd::IterativeCollideFunctor> testFCD; + fcd::GenericFCD<BodyTuple, fcd::GJKEPACollideFunctor> testFCD; //A recursive union of three spheres is dropped on a box. Box box(179, 179, Vec3(0,0,0), Vec3(0,0,0), Quat(), Vec3(real_t(10),real_t(2), real_t(10)), iron, false, true, false);