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
00026 #include "graspitCollision.h"
00027
00028 #include <algorithm>
00029
00030
00031 #include "debug.h"
00032
00033 #include "body.h"
00034 #include "collisionModel.h"
00035 #include "collisionAlgorithms.h"
00036
00037
00038 #include "profiling.h"
00039
00040 using namespace Collision;
00041
00055 void
00056 GraspitCollision::getActivePairs(std::list<CollisionPair> *activePairs,
00057 const std::set<CollisionModel*> *interestList)
00058 {
00059 int myThread = getThreadId();
00060
00061 std::vector<CollisionModel*>::iterator it1, it2;
00062 for (it1=mModels.begin(); it1!=mModels.end(); it1++) {
00063
00064 if ( !(*it1)->isActive() ) continue;
00065
00066 if ( (*it1)->getThreadId() != myThread && (*it1)->getThreadId() != 0) continue;
00067
00068
00069 std::pair<DisabledIterator, DisabledIterator> range;
00070 range = mDisabledMap.equal_range(*it1);
00071
00072 bool interest1 = true;
00073 if (interestList) {
00074 if (interestList->find(*it1) == interestList->end()) interest1 = false;
00075 }
00076
00077
00078 for (it2 = it1+1; it2!=mModels.end(); it2++) {
00079
00080 if ( !(*it2)->isActive() ) continue;
00081
00082 if ( (*it2)->getThreadId() != myThread && (*it2)->getThreadId() != 0) continue;
00083 if ( myThread != 0 && (*it1)->getThreadId() == 0 && (*it2)->getThreadId() == 0) continue;
00084
00085 DisabledIterator rangeIt;
00086 bool disabled = false;
00087 for (rangeIt = range.first; rangeIt != range.second && !disabled; rangeIt++) {
00088 if (rangeIt->second == *it2) disabled = true;
00089 }
00090
00091 if (disabled) continue;
00092
00093 if (!interest1) {
00094 if (interestList->find(*it2) == interestList->end()) continue;
00095 }
00096
00097 activePairs->push_back( CollisionPair(*it1, *it2) );
00098 }
00099 }
00100 }
00101
00102 void
00103 GraspitCollision::activateBody(const Body* body, bool active)
00104 {
00105 CollisionModel *model = getModel(body);
00106 if (!model) {
00107 DBGA("GCOL: model not found");
00108 return;
00109 }
00110 model->setActive(active);
00111 }
00112
00113 void
00114 GraspitCollision::activatePair(const Body* body1, const Body* body2, bool active)
00115 {
00116 CollisionModel *model1 = getModel(body1);
00117 CollisionModel *model2 = getModel(body2);
00118 if (!model1 || !model2) {
00119 DBGA("GCOL: model not found");
00120 return;
00121 }
00122 if (model2 == model1) {
00123
00124 DBGA("GCOL Warning: insertion collision pair is actually one body");
00125 model1->setActive(active);
00126 return;
00127 }
00128 else if (model2 < model1) {
00129
00130 std::swap(model1, model2);
00131 }
00132 if (!active) {
00133 DBGP("Disable pair: " << model1 << " -- " << model2);
00134 mDisabledMap.insert( std::pair<const CollisionModel*, const CollisionModel*>(model1, model2) );
00135 } else {
00136
00137 }
00138 }
00139
00140 bool
00141 GraspitCollision::isActive(const Body* body1, const Body* body2)
00142 {
00143 CollisionModel *model1 = getModel(body1);
00144 if (!model1) {
00145 DBGA("GCOL: model not found");
00146 return false;
00147 }
00148 if (!body2) return model1->isActive();
00149
00150 CollisionModel *model2 = getModel(body2);
00151 if (!model2) {
00152 DBGA("GCOL: model not found");
00153 return false;
00154 }
00155 if (!model1->isActive() || !model2->isActive()) {
00156 return false;
00157 }
00158 if (model2==model1) {
00159
00160 DBGA("GCOL Warning: collision pair is actually one body");
00161 return model1->isActive();
00162 }
00163 else if (model2 < model1) {
00164
00165 std::swap(model1, model2);
00166 }
00167
00168
00169
00170 std::pair<DisabledIterator, DisabledIterator> range;
00171 range = mDisabledMap.equal_range(model1);
00172
00173 DisabledIterator rangeIt;
00174 bool disabled = false;
00175 for (rangeIt = range.first; rangeIt != range.second && !disabled; rangeIt++) {
00176 if (rangeIt->second == model2) disabled = true;
00177 }
00178 if (disabled) return false;
00179 return true;
00180 }
00181
00182 bool
00183 GraspitCollision::addBody(Body *body, bool ExpectEmpty)
00184 {
00185 if (getModel(body)) {
00186 DBGA("GCOL: body already present");
00187 return false;
00188 }
00189
00190 CollisionModel *model = new CollisionModel(getThreadId());
00191
00192
00193 std::vector<Triangle> triangles;
00194 body->getGeometryTriangles(&triangles);
00195
00196
00197 for (int i=0; i<(int)triangles.size(); i++) {
00198 model->addTriangle(triangles[i]);
00199 }
00200
00201
00202 model->build();
00203
00204
00205 mModelMap[body] = model;
00206 mBodyMap[model] = body;
00207 mModels.push_back(model);
00208
00209
00210
00211 std::sort( mModels.begin(), mModels.end() );
00212
00213 return true;
00214 }
00215
00216 void
00217 GraspitCollision::removeBody(Body *body)
00218 {
00219 CollisionModel *model = getModel(body);
00220 if (!model) {
00221 DBGA("GCOL: model not found");
00222 return;
00223 }
00224
00225 std::vector<CollisionModel*>::iterator it;
00226 for (it=mModels.begin(); it!=mModels.end(); it++){
00227 if ( *it == model ) break;
00228 }
00229 if (it==mModels.end()) {
00230 DBGA("GCOL error: model for deletion not present");
00231 } else {
00232 mModels.erase(it);
00233 }
00234
00235 mModelMap.erase( mModelMap.find(body) );
00236 mBodyMap.erase( mBodyMap.find(model) );
00237 delete model;
00238 }
00239
00240 void
00241 GraspitCollision::cloneBody(Body* clone, const Body* original)
00242 {
00243 CollisionModel *originalModel = getModel(original);
00244 if (!originalModel) {
00245 DBGA("GCOL: model not found");
00246 return;
00247 }
00248 if (getModel(clone) ) {
00249 DBGA("GCOL: clone already in collision detection system");
00250 return;
00251 }
00252 CollisionModel *cloneModel = new CollisionModel(getThreadId());
00253 cloneModel->cloneModel(originalModel);
00254
00255
00256 mModelMap[clone] = cloneModel;
00257 mBodyMap[cloneModel] = clone;
00258 mModels.push_back(cloneModel);
00259
00260
00261
00262 std::sort( mModels.begin(), mModels.end() );
00263 }
00264
00265 void
00266 GraspitCollision::setBodyTransform(Body *body, const transf &t)
00267 {
00268 CollisionModel *model = getModel(body);
00269 if (!model) {
00270 DBGA("GCOL: model not found");
00271 return;
00272 }
00273 model->setTran(t);
00274 }
00275
00276 void
00277 GraspitCollision::convertInterestList(const std::vector<Body*> *inList,
00278 std::set<CollisionModel*> *outSet)
00279 {
00280 for (int i=0; i<(int)inList->size(); i++) {
00281 CollisionModel *model = getModel((*inList)[i]);
00282 if (!model) {
00283 DBGA("GCOL: interest list model not found");
00284 } else {
00285 outSet->insert(model);
00286 }
00287 }
00288 }
00289
00290 int
00291 GraspitCollision::allCollisions(DetectionType type, CollisionReport *report,
00292 const std::vector<Body*> *interestList)
00293 {
00294 int collisions = 0;
00295
00296 std::set<CollisionModel*> *intModelList = NULL;
00297 if (interestList) {
00298 intModelList = new std::set<CollisionModel*>;
00299 convertInterestList(interestList, intModelList);
00300 }
00301
00302 std::list<CollisionPair> activeList;
00303 getActivePairs(&activeList, intModelList);
00304 std::list<CollisionPair>::iterator it;
00305 for (it = activeList.begin(); it!=activeList.end(); it++) {
00306 CollisionCallback cc(it->first, it->second);
00307
00308 startRecursion(it->first, it->second, &cc);
00309 DBGST( cc.printStatistics() );
00310 if ( cc.isCollision() ) {
00311 collisions++;
00312 if (type == FAST_COLLISION) break;
00313 Body *b1 = getBody(it->first);
00314 Body *b2 = getBody(it->second);
00315 assert(b1 && b2);
00316 report->push_back( CollisionData(b1,b2) );
00317 }
00318 }
00319 if (intModelList) delete intModelList;
00320 return collisions;
00321 }
00322
00323 int
00324 GraspitCollision::allContacts(CollisionReport *report, double threshold,
00325 const std::vector<Body*> *interestList)
00326 {
00327 int contacts = 0;
00328
00329 std::set<CollisionModel*> *intModelList = NULL;
00330 if (interestList) {
00331 intModelList = new std::set<CollisionModel*>;
00332 convertInterestList(interestList, intModelList);
00333 }
00334
00335 std::list<CollisionPair> activeList;
00336 getActivePairs(&activeList, intModelList);
00337 std::list<CollisionPair>::iterator it;
00338 for (it = activeList.begin(); it!=activeList.end(); it++) {
00339 ContactCallback cc(threshold, it->first, it->second);
00340
00341 startRecursion(it->first, it->second, &cc);
00342 DBGST( cc.printStatistics() );
00343 if (!cc.getReport().empty()) {
00344 contacts ++;
00345 Body *b1 = getBody(it->first);
00346 Body *b2 = getBody(it->second);
00347 assert(b1 && b2);
00348 report->push_back( CollisionData(b1,b2) );
00349 report->back().contacts = cc.getReport();
00350
00351
00352 DBGP("Body: " << getBody(it->first)->getName().latin1());
00353 DBGP("Before duplicate removal: " << report->back().contacts.size() );
00354 removeContactDuplicates(&(report->back().contacts), CONTACT_DUPLICATE_THRESHOLD);
00355 DBGP("After duplicate removal: " << report->back().contacts.size() );
00356
00357 compactContactSet(&report->back().contacts);
00358 DBGP("After compact set: " << report->back().contacts.size() );
00359 }
00360 }
00361 if (intModelList) delete intModelList;
00362 return contacts;
00363 }
00364
00365 int
00366 GraspitCollision::contact(ContactReport *report, double threshold,
00367 const Body *body1, const Body *body2)
00368 {
00369 CollisionModel *model1 = getModel(body1);
00370 CollisionModel *model2 = getModel(body2);
00371 if (!model1 || !model2) {
00372 DBGA("GCOL: model not found");
00373 return 0;
00374 }
00375
00376 ContactCallback cc(threshold, model1, model2);
00377 startRecursion(model1, model2, &cc);
00378 DBGST( cc.printStatistics() );
00379 if (!cc.getReport().empty()) {
00380 *report = cc.getReport();
00381
00382
00383 DBGP("Before duplicate removal: " << report->size() );
00384 removeContactDuplicates(report, CONTACT_DUPLICATE_THRESHOLD);
00385 DBGP("After duplicate removal: " << report->size() );
00386
00387 compactContactSet(report);
00388 DBGP("After compact set: " << report->size() );
00389 }
00390 return report->size();
00391 }
00392
00393 double
00394 GraspitCollision::pointToBodyDistance(const Body *body1, position point,
00395 position &closestPoint, vec3 &closestNormal)
00396 {
00397 CollisionModel *model = getModel(body1);
00398 if (!model) {
00399 DBGA("GCOL: model not found");
00400 return 0;
00401 }
00402
00403 ClosestPtCallback pc(model, point * body1->getTran().inverse());
00404 startRecursion(model, NULL, &pc);
00405 DBGST( pc.printStatistics() );
00406
00407 closestPoint = pc.getClosestPt() * body1->getTran();
00408
00409
00410
00411
00412 closestNormal = normalise(closestPoint - point);
00413 return pc.getMin();
00414 }
00415
00416 double
00417 GraspitCollision::bodyToBodyDistance(const Body *body1, const Body *body2,
00418 position &p1, position &p2)
00419 {
00420 CollisionModel *model1 = getModel(body1);
00421 CollisionModel *model2 = getModel(body2);
00422 if (!model1 || !model2) {
00423 DBGA("GCOL: model not found");
00424 return 0;
00425 }
00426 DistanceCallback dc(model1, model2);
00427
00428 startRecursion(model1, model2, &dc);
00429 DBGST( dc.printStatistics() );
00430 dc.getClosestPoints(p1, p2);
00431
00432 p1 = p1 * body1->getTran().inverse();
00433 p2 = p2 * body2->getTran().inverse();
00434 return dc.getMin();
00435 }
00436
00437 void
00438 GraspitCollision::bodyRegion(const Body *body, position point, vec3 normal,
00439 double radius, Neighborhood *neighborhood)
00440 {
00441 CollisionModel *model = getModel(body);
00442 if (!model) {
00443 DBGA("GCOL: model not found");
00444 return;
00445 }
00446
00447 RegionCallback rc(model, point, normal, radius);
00448
00449 startRecursion(model, NULL, &rc);
00450 DBGST( rc.printStatistics() );
00451 *neighborhood = rc.getRegion();
00452
00453 neighborhood->push_back(point);
00454 }
00455
00456
00457 void
00458 GraspitCollision::getBoundingVolumes(const Body* body, int depth, std::vector<BoundingBox>* bvs)
00459 {
00460 CollisionModel *model = getModel(body);
00461 if (!model) {
00462 DBGA("GCOL: model not found");
00463 return;
00464 }
00465 model->getBoundingVolumes(depth, bvs);
00466
00467 }