DefaultPipeline.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/collision/DefaultPipeline.h>
00026 #include <sofa/core/CollisionModel.h>
00027 #include <sofa/simulation/tree/GNode.h>
00028 #include <sofa/core/ObjectFactory.h>
00029 
00030 #include <sofa/helper/system/gl.h>
00031 
00032 #define VERBOSE(a) if (bVerbose.getValue()) a; else {}
00033 
00034 namespace sofa
00035 {
00036 
00037 namespace component
00038 {
00039 
00040 namespace collision
00041 {
00042 
00043 using namespace core;
00044 using namespace core::objectmodel;
00045 using namespace core::componentmodel::collision;
00046 using namespace sofa::defaulttype;
00047 
00048 SOFA_DECL_CLASS(DefaultPipeline)
00049 
00050 int DefaultPipelineClass = core::RegisterObject("The default collision detection and modeling pipeline")
00051 .add< DefaultPipeline >()
00052 .addAlias("CollisionPipeline")
00053 ;
00054 
00055 DefaultPipeline::DefaultPipeline()
00056 : bVerbose(initData(&bVerbose, false, "verbose","Display current step information"))
00057 , bDraw(initData(&bDraw, false, "draw","Draw detected collisions"))
00058 , depth(initData(&depth, 6, "depth","Max depth of bounding trees"))
00059 {
00060 }
00061 
00062 typedef simulation::tree::GNode::ctime_t ctime_t;
00063 
00064 void DefaultPipeline::doCollisionReset()
00065 {
00066     core::objectmodel::BaseContext* scene = getContext();
00067     simulation::tree::GNode* node = dynamic_cast<simulation::tree::GNode*>(scene);
00068     if (node && !node->getLogTime()) node=NULL; // Only use node for time logging
00069     ctime_t t0 = 0;
00070     const std::string category = "collision";
00071     
00072     VERBOSE(std::cout << "DefaultPipeline::doCollisionReset, Reset collisions"<<std::endl);
00073     // clear all contacts
00074     if (contactManager!=NULL)
00075     {
00076         const sofa::helper::vector<Contact*>& contacts = contactManager->getContacts();
00077         for (sofa::helper::vector<Contact*>::const_iterator it = contacts.begin(); it!=contacts.end(); it++)
00078         {
00079             (*it)->removeResponse();
00080         }
00081     }
00082     // clear all collision groups
00083     if (groupManager!=NULL)
00084     {
00085         if (node) t0 = node->startTime();
00086         groupManager->clearGroups(scene);
00087         if (node) t0 = node->endTime(t0, category, groupManager, this);
00088     }
00089 }
00090 
00091 void DefaultPipeline::doCollisionDetection(const sofa::helper::vector<core::CollisionModel*>& collisionModels)
00092 {
00093     //std::cerr<<"DefaultPipeline::doCollisionDetection"<<std::endl;
00094     
00095     core::objectmodel::BaseContext* scene = getContext();
00096     simulation::Node* node = dynamic_cast<simulation::Node*>(scene);
00097     if (node && !node->getLogTime()) node=NULL; // Only use node for time logging
00098     ctime_t t0 = 0;
00099     const std::string category = "collision";
00100 
00101     VERBOSE(std::cout << "DefaultPipeline::doCollisionDetection, Compute Bounding Trees"<<std::endl);
00102     // First, we compute a bounding volume for the collision model (for example bounding sphere)
00103     // or we have loaded a collision model that knows its other model
00104     
00105     sofa::helper::vector<CollisionModel*> vectBoundingVolume;
00106     {
00107         if (node) t0 = node->startTime();
00108         const bool continuous = intersectionMethod->useContinuous();
00109         const double dt       = getContext()->getDt();
00110 
00111         sofa::helper::vector<CollisionModel*>::const_iterator it = collisionModels.begin();
00112         sofa::helper::vector<CollisionModel*>::const_iterator itEnd = collisionModels.end();
00113         int nActive = 0;
00114         for (; it != itEnd; it++)
00115         {
00116             VERBOSE(std::cout << "DefaultPipeline::doCollisionDetection, consider model "<<(*it)->getName()<<std::endl);
00117             if (!(*it)->isActive()) continue;
00118             if (continuous)
00119                 (*it)->computeContinuousBoundingTree(dt, depth.getValue());
00120             else
00121                 (*it)->computeBoundingTree(depth.getValue());
00122             vectBoundingVolume.push_back ((*it)->getFirst());
00123             ++nActive;
00124         }
00125         if (node) t0 = node->endTime(t0, "collision/bbox", this);
00126         VERBOSE(std::cout << "DefaultPipeline::doCollisionDetection, Computed "<<nActive<<" BBoxs"<<std::endl);
00127     }
00128     // then we start the broad phase
00129     if (broadPhaseDetection==NULL) return; // can't go further
00130     VERBOSE(std::cout << "DefaultPipeline::doCollisionDetection, BroadPhaseDetection "<<broadPhaseDetection->getName()<<std::endl);
00131     if (node) t0 = node->startTime();
00132     broadPhaseDetection->beginBroadPhase();
00133         broadPhaseDetection->addCollisionModels(vectBoundingVolume);  // detection is done there
00134     broadPhaseDetection->endBroadPhase();
00135     if (node) t0 = node->endTime(t0, category, broadPhaseDetection, this);
00136     
00137     // then we start the narrow phase
00138     if (narrowPhaseDetection==NULL) return; // can't go further
00139     VERBOSE(std::cout << "DefaultPipeline::doCollisionDetection, NarrowPhaseDetection "<<narrowPhaseDetection->getName()<<std::endl);
00140     if (node) t0 = node->startTime();
00141     narrowPhaseDetection->beginNarrowPhase();
00142     sofa::helper::vector<std::pair<CollisionModel*, CollisionModel*> >& vectCMPair = broadPhaseDetection->getCollisionModelPairs();
00143     VERBOSE(std::cout << "DefaultPipeline::doCollisionDetection, "<< vectCMPair.size()<<" colliding model pairs"<<std::endl);
00144     narrowPhaseDetection->addCollisionPairs(vectCMPair);
00145     narrowPhaseDetection->endNarrowPhase();
00146     if (node) t0 = node->endTime(t0, category, narrowPhaseDetection, this);
00147 }
00148 
00149 void DefaultPipeline::doCollisionResponse()
00150 {
00151     core::objectmodel::BaseContext* scene = getContext();
00152     simulation::tree::GNode* node = dynamic_cast<simulation::tree::GNode*>(scene);
00153     if (node && !node->getLogTime()) node=NULL; // Only use node for time logging
00154     ctime_t t0 = 0;
00155     const std::string category = "collision";
00156     
00157     // then we start the creation of contacts
00158     if (contactManager==NULL) return; // can't go further
00159     VERBOSE(std::cout << "Create Contacts "<<contactManager->getName()<<std::endl);
00160     if (node) t0 = node->startTime();
00161     contactManager->createContacts(narrowPhaseDetection->getDetectionOutputs());
00162     if (node) t0 = node->endTime(t0, category, contactManager, this);
00163     
00164     // finally we start the creation of collisionGroup
00165 
00166     const sofa::helper::vector<Contact*>& contacts = contactManager->getContacts();
00167 
00168     // First we remove all contacts with non-simulated objects and directly add them
00169     sofa::helper::vector<Contact*> notStaticContacts;
00170 
00171     for (sofa::helper::vector<Contact*>::const_iterator it = contacts.begin(); it!=contacts.end(); it++)
00172     {
00173         Contact* c = *it;
00174         if (!c->getCollisionModels().first->isSimulated())
00175         {
00176             c->createResponse(c->getCollisionModels().second->getContext());
00177         }
00178         else if (!c->getCollisionModels().second->isSimulated())
00179         {
00180             c->createResponse(c->getCollisionModels().first->getContext());
00181         }
00182         else
00183             notStaticContacts.push_back(c);
00184     }
00185 
00186 
00187     if (groupManager==NULL)
00188     {
00189         VERBOSE(std::cout << "Linking all contacts to Scene"<<std::endl);
00190         for (sofa::helper::vector<Contact*>::const_iterator it = notStaticContacts.begin(); it!=notStaticContacts.end(); it++)
00191         {
00192             (*it)->createResponse(scene);
00193         }
00194     }
00195     else
00196     {
00197         VERBOSE(std::cout << "Create Groups "<<groupManager->getName()<<std::endl);
00198         if (node) t0 = node->startTime();
00199         groupManager->createGroups(scene, notStaticContacts);
00200         if (node) t0 = node->endTime(t0, category, groupManager, this);
00201     }
00202 }
00203 
00204 void DefaultPipeline::draw()
00205 {
00206     if (!bDraw.getValue()) return;
00207     if (!narrowPhaseDetection) return;
00208     glDisable(GL_LIGHTING);
00209     glLineWidth(2);
00210     glBegin(GL_LINES);
00211     DetectionOutputMap& outputsMap = narrowPhaseDetection->getDetectionOutputs();
00212     for (DetectionOutputMap::iterator it = outputsMap.begin(); it!=outputsMap.end(); it++)
00213     {
00214         /*
00215         DetectionOutputVector& outputs = it->second;
00216         for (DetectionOutputVector::iterator it2 = outputs.begin(); it2!=outputs.end(); it2++)
00217         {
00218             DetectionOutput* d = &*it2;
00219             if (d->distance<0)
00220                 glColor3f(1.0f,0.5f,0.5f);
00221             else
00222                 glColor3f(0.5f,1.0f,0.5f);
00223             glVertex3dv(d->point[0].ptr());
00224             glVertex3dv(d->point[1].ptr());
00225         }
00226         */
00227     }
00228     glEnd();
00229     glLineWidth(1);
00230 }
00231 } // namespace collision
00232 
00233 } // namespace component
00234 
00235 } // namespace sofa
00236 

Generated on Sun Nov 23 02:33:12 2008 for Sofa by  doxygen 1.5.7.1