00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sofa/component/collision/BruteForceDetection.h>
00026 #include <sofa/component/collision/Sphere.h>
00027 #include <sofa/component/collision/Triangle.h>
00028 #include <sofa/component/collision/Line.h>
00029 #include <sofa/component/collision/Point.h>
00030 #include <sofa/helper/FnDispatcher.h>
00031 #include <sofa/core/ObjectFactory.h>
00032 #include <sofa/simulation/common/Node.h>
00033 #include <map>
00034 #include <queue>
00035 #include <stack>
00036
00037 #include <sofa/helper/system/gl.h>
00038 #include <sofa/helper/system/glut.h>
00039
00040 namespace sofa
00041 {
00042
00043 namespace component
00044 {
00045
00046 namespace collision
00047 {
00048
00049 using namespace sofa::defaulttype;
00050 using namespace sofa::helper;
00051 using namespace collision;
00052
00053 SOFA_DECL_CLASS(BruteForce)
00054
00055 int BruteForceDetectionClass = core::RegisterObject("Collision detection using extensive pair-wise tests")
00056 .add< BruteForceDetection >()
00057 ;
00058
00059 using namespace core::objectmodel;
00060
00061 BruteForceDetection::BruteForceDetection()
00062 : bDraw(initData(&bDraw, false, "draw", "enable/disable display of results"))
00063 {
00064 }
00065
00066 void BruteForceDetection::addCollisionModel(core::CollisionModel *cm)
00067 {
00068 if (cm->empty())
00069 return;
00070 if (cm->isSimulated() && cm->getLast()->canCollideWith(cm->getLast()))
00071 {
00072
00073 bool swapModels = false;
00074 core::componentmodel::collision::ElementIntersector* intersector = intersectionMethod->findIntersector(cm, cm, swapModels);
00075 if (intersector != NULL)
00076 if (intersector->canIntersect(cm->begin(), cm->begin()))
00077 {
00078
00079 cmPairs.push_back(std::make_pair(cm, cm));
00080 }
00081 }
00082 for (sofa::helper::vector<core::CollisionModel*>::iterator it = collisionModels.begin(); it != collisionModels.end(); ++it)
00083 {
00084 core::CollisionModel* cm2 = *it;
00085 if (!cm->isSimulated() && !cm2->isSimulated())
00086 continue;
00087 if (!cm->canCollideWith(cm2))
00088 continue;
00089 if (!cm->getLast()->canCollideWith(cm2->getLast()))
00090 continue;
00091 bool swapModels = false;
00092 core::componentmodel::collision::ElementIntersector* intersector = intersectionMethod->findIntersector(cm, cm2, swapModels);
00093 if (intersector == NULL)
00094 continue;
00095
00096 core::CollisionModel* cm1 = (swapModels?cm2:cm);
00097 cm2 = (swapModels?cm:cm2);
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 if (intersector->canIntersect(cm1->begin(), cm2->begin()))
00122 {
00123
00124 cmPairs.push_back(std::make_pair(cm1, cm2));
00125 }
00126 }
00127 collisionModels.push_back(cm);
00128 }
00129
00130 class MirrorIntersector : public core::componentmodel::collision::ElementIntersector
00131 {
00132 public:
00133 core::componentmodel::collision::ElementIntersector* intersector;
00134
00136 virtual bool canIntersect(core::CollisionElementIterator elem1, core::CollisionElementIterator elem2)
00137 {
00138 return intersector->canIntersect(elem2, elem1);
00139 }
00140
00143 virtual int beginIntersect(core::CollisionModel* model1, core::CollisionModel* model2, core::componentmodel::collision::DetectionOutputVector*& contacts)
00144 {
00145 return intersector->beginIntersect(model2, model1, contacts);
00146 }
00147
00149 virtual int intersect(core::CollisionElementIterator elem1, core::CollisionElementIterator elem2, core::componentmodel::collision::DetectionOutputVector* contacts)
00150 {
00151 return intersector->intersect(elem2, elem1, contacts);
00152 }
00153
00155 virtual int endIntersect(core::CollisionModel* model1, core::CollisionModel* model2, core::componentmodel::collision::DetectionOutputVector* contacts)
00156 {
00157 return intersector->endIntersect(model2, model1, contacts);
00158 }
00159
00160 virtual std::string name() const
00161 {
00162 return intersector->name() + std::string("<SWAP>");
00163 }
00164
00165 };
00166
00167 void BruteForceDetection::addCollisionPair(const std::pair<core::CollisionModel*, core::CollisionModel*>& cmPair)
00168 {
00169 typedef std::pair< std::pair<core::CollisionElementIterator,core::CollisionElementIterator>, std::pair<core::CollisionElementIterator,core::CollisionElementIterator> > TestPair;
00170
00171 core::CollisionModel *cm1 = cmPair.first;
00172 core::CollisionModel *cm2 = cmPair.second;
00173
00174
00175
00176
00177 if (!cm1->isSimulated() && !cm2->isSimulated())
00178 return;
00179
00180 if (cm1->empty() || cm2->empty())
00181 return;
00182
00183 core::CollisionModel *finalcm1 = cm1->getLast();
00184 core::CollisionModel *finalcm2 = cm2->getLast();
00185
00186 bool swapModels = false;
00187 core::componentmodel::collision::ElementIntersector* finalintersector = intersectionMethod->findIntersector(finalcm1, finalcm2, swapModels);
00188 if (finalintersector == NULL)
00189 return;
00190 if (swapModels)
00191 {
00192 core::CollisionModel* tmp;
00193 tmp = cm1; cm1 = cm2; cm2 = tmp;
00194 tmp = finalcm1; finalcm1 = finalcm2; finalcm2 = tmp;
00195 }
00196
00197 const bool self = (finalcm1->getContext() == finalcm2->getContext());
00198
00199
00200
00201 sofa::core::componentmodel::collision::DetectionOutputVector*& outputs = outputsMap[std::make_pair(finalcm1, finalcm2)];
00202
00203 finalintersector->beginIntersect(finalcm1, finalcm2, outputs);
00204
00205 if (finalcm1 == cm1 || finalcm2 == cm2)
00206 {
00207
00208 finalcm1 = NULL;
00209 finalcm2 = NULL;
00210 finalintersector = NULL;
00211 }
00212 simulation::Node* node = dynamic_cast<simulation::Node*>(getContext());
00213 if (node && !node->getLogTime()) node=NULL;
00214 simulation::Node::ctime_t t0=0, t=0;
00215 simulation::Node::ctime_t ft=0;
00216
00217 std::queue< TestPair > externalCells;
00218
00219 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> internalChildren1 = cm1->begin().getInternalChildren();
00220 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> internalChildren2 = cm2->begin().getInternalChildren();
00221 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> externalChildren1 = cm1->begin().getExternalChildren();
00222 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> externalChildren2 = cm2->begin().getExternalChildren();
00223 if (internalChildren1.first != internalChildren1.second)
00224 {
00225 if (internalChildren2.first != internalChildren2.second)
00226 externalCells.push(std::make_pair(internalChildren1,internalChildren2));
00227 if (externalChildren2.first != externalChildren2.second)
00228 externalCells.push(std::make_pair(internalChildren1,externalChildren2));
00229 }
00230 if (externalChildren1.first != externalChildren1.second)
00231 {
00232 if (internalChildren2.first != internalChildren2.second)
00233 externalCells.push(std::make_pair(externalChildren1,internalChildren2));
00234 if (externalChildren2.first != externalChildren2.second)
00235 externalCells.push(std::make_pair(externalChildren1,externalChildren2));
00236 }
00237
00238
00239
00240 core::componentmodel::collision::ElementIntersector* intersector = NULL;
00241 MirrorIntersector mirror;
00242 cm1 = NULL;
00243 cm2 = NULL;
00244
00245 while (!externalCells.empty())
00246 {
00247 TestPair root = externalCells.front();
00248 externalCells.pop();
00249
00250 if (cm1 != root.first.first.getCollisionModel() || cm2 != root.second.first.getCollisionModel())
00251 {
00252 cm1 = root.first.first.getCollisionModel();
00253 cm2 = root.second.first.getCollisionModel();
00254 intersector = intersectionMethod->findIntersector(cm1, cm2, swapModels);
00255 if (intersector == NULL)
00256 {
00257 std::cout << "BruteForceDetection: Error finding intersector " << intersectionMethod->getName() << " for "<<gettypename(typeid(*cm1))<<" - "<<gettypename(typeid(*cm2))<<std::endl;
00258 }
00259
00260 if (swapModels)
00261 {
00262 mirror.intersector = intersector; intersector = &mirror;
00263 }
00264 }
00265 if (intersector == NULL)
00266 continue;
00267 std::stack< TestPair > internalCells;
00268 internalCells.push(root);
00269
00270 simulation::Node::ctime_t it=0,it0=0;
00271
00272 if (node) it0 = node->startTime();
00273 while (!internalCells.empty())
00274 {
00275 TestPair current = internalCells.top();
00276 internalCells.pop();
00277
00278 core::CollisionElementIterator begin1 = current.first.first;
00279 core::CollisionElementIterator end1 = current.first.second;
00280 core::CollisionElementIterator begin2 = current.second.first;
00281 core::CollisionElementIterator end2 = current.second.second;
00282
00283 if (begin1.getCollisionModel() == finalcm1 && begin2.getCollisionModel() == finalcm2)
00284 {
00285
00286 if (node) t0 = node->startTime();
00287 for (core::CollisionElementIterator it1 = begin1; it1 != end1; ++it1)
00288 {
00289 for (core::CollisionElementIterator it2 = begin2; it2 != end2; ++it2)
00290 {
00291 if (!self || it1.canCollideWith(it2))
00292 intersector->intersect(it1,it2,outputs);
00293 }
00294 }
00295 }
00296 else
00297 {
00298 for (core::CollisionElementIterator it1 = begin1; it1 != end1; ++it1)
00299 {
00300 for (core::CollisionElementIterator it2 = begin2; it2 != end2; ++it2)
00301 {
00302
00303
00304
00305 bool b = intersector->canIntersect(it1,it2);
00306 if (b)
00307 {
00308
00309
00310
00311 TestPair newInternalTests(it1.getInternalChildren(),it2.getInternalChildren());
00312 TestPair newExternalTests(it1.getExternalChildren(),it2.getExternalChildren());
00313 if (newInternalTests.first.first != newInternalTests.first.second)
00314 {
00315 if (newInternalTests.second.first != newInternalTests.second.second)
00316 {
00317 internalCells.push(newInternalTests);
00318 }
00319 else
00320 {
00321 newInternalTests.second.first = it2;
00322 newInternalTests.second.second = it2;
00323 ++newInternalTests.second.second;
00324 internalCells.push(newInternalTests);
00325 }
00326 }
00327 else
00328 {
00329 if (newInternalTests.second.first != newInternalTests.second.second)
00330 {
00331 newInternalTests.first.first = it1;
00332 newInternalTests.first.second = it1;
00333 ++newInternalTests.first.second;
00334 internalCells.push(newInternalTests);
00335 }
00336 else
00337 {
00338
00339
00340 if (newExternalTests.first.first != newExternalTests.first.second)
00341 {
00342 if (newExternalTests.second.first != newExternalTests.second.second)
00343 {
00344 if (newExternalTests.first.first.getCollisionModel() == finalcm1 && newExternalTests.second.first.getCollisionModel() == finalcm2)
00345 {
00346 core::CollisionElementIterator begin1 = newExternalTests.first.first;
00347 core::CollisionElementIterator end1 = newExternalTests.first.second;
00348 core::CollisionElementIterator begin2 = newExternalTests.second.first;
00349 core::CollisionElementIterator end2 = newExternalTests.second.second;
00350 if (node) t0 = node->startTime();
00351 for (core::CollisionElementIterator it1 = begin1; it1 != end1; ++it1)
00352 {
00353 for (core::CollisionElementIterator it2 = begin2; it2 != end2; ++it2)
00354 {
00355
00356
00357 if (!self || it1.canCollideWith(it2))
00358 finalintersector->intersect(it1,it2,outputs);
00359 }
00360 }
00361 if (node) ft += node->startTime() - t0;
00362 }
00363 else
00364 externalCells.push(newExternalTests);
00365 }
00366 else
00367 {
00368
00369
00370 newExternalTests.second.first = it2;
00371 newExternalTests.second.second = it2;
00372 ++newExternalTests.second.second;
00373 externalCells.push(std::make_pair(newExternalTests.first, newInternalTests.second));
00374 }
00375 }
00376 else if (newExternalTests.second.first != newExternalTests.second.second)
00377 {
00378
00379
00380 newExternalTests.first.first = it1;
00381 newExternalTests.first.second = it1;
00382 ++newExternalTests.first.second;
00383 externalCells.push(std::make_pair(newExternalTests.first, newExternalTests.second));
00384 }
00385 else
00386 {
00387
00388 if (!self || it1.canCollideWith(it2))
00389 intersector->intersect(it1,it2, outputs);
00390 }
00391 }
00392 }
00393 }
00394 }
00395 }
00396 }
00397 }
00398 if (node)
00399 {
00400 it += node->startTime() - it0 - ft;
00401 std::string name = "collision/";
00402 name += intersector->name();
00403 node->addTime(it, name, intersectionMethod);
00404 t += it;
00405 }
00406 }
00407 if (node && finalintersector!=NULL)
00408 {
00409 std::string name = "collision/";
00410 name += finalintersector->name();
00411 node->addTime(ft, name, intersectionMethod);
00412 t += ft;
00413 node->addTime(t, "collision", intersectionMethod, this);
00414 }
00415
00416 }
00417
00418 void BruteForceDetection::draw()
00419 {
00420 if (!bDraw.getValue()) return;
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 }
00442
00443 }
00444
00445 }
00446
00447 }
00448