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
00027
00028
00029
00030
00031
00032
00033
00034
00038 #ifndef COLLISION_CHECKING_COLLISION_PRIMITIVE_H
00039 #define COLLISION_CHECKING_COLLISION_PRIMITIVE_H
00040
00041 #include "collision_checking/BVH_defs.h"
00042 #include "collision_checking/intersect.h"
00043 #include "collision_checking/BVH_model.h"
00044 #include "collision_checking/BVH_front.h"
00045
00047 namespace collision_checking
00048 {
00049
00051 struct BVHCollisionPair
00052 {
00054 int id1;
00055
00057 int id2;
00058
00060 BVH_REAL collide_time;
00061
00063 Vec3f normal;
00064
00066 Vec3f contact_point;
00067
00069 BVH_REAL penetration_depth;
00070 };
00071
00073 struct BVH_CollideResult
00074 {
00076 int num_bv_tests;
00077
00079 int num_tri_tests;
00080
00082 int num_vf_tests;
00083
00085 int num_ee_tests;
00086
00088 BVH_REAL query_time_seconds;
00089
00094 int num_max_contacts;
00095
00096 BVH_CollideResult();
00097
00098 ~BVH_CollideResult();
00099
00101 void add(int id1, int id2, BVH_REAL time = 0);
00102
00103 void add(int id1, int id2, Vec3f contact_point, BVH_REAL penetration_depth, const Vec3f& normal, BVH_REAL time = 0);
00104
00106 int colliding() { return (num_pairs > 0); }
00107
00109 void resetRecord()
00110 {
00111 num_pairs = 0;
00112 num_bv_tests = 0;
00113 num_tri_tests = 0;
00114 num_vf_tests = 0;
00115 num_ee_tests = 0;
00116 }
00117
00119 int numPairs() const
00120 {
00121 return num_pairs;
00122 }
00123
00125 int id1(int i) const
00126 {
00127 return pairs[i].id1;
00128 }
00129
00131 int id2(int i) const
00132 {
00133 return pairs[i].id2;
00134 }
00135
00137 BVHCollisionPair* collidePairs()
00138 {
00139 return pairs;
00140 }
00141
00142 private:
00143 int num_pairs_allocated;
00144 int num_pairs;
00145 BVHCollisionPair* pairs;
00146
00147 void sizeTo(int n);
00148 };
00149
00150
00152 template<typename BV>
00153 void collideRecurse(BVNode<BV>* tree1, BVNode<BV>* tree2, int b1, int b2,
00154 Vec3f* vertices1, Vec3f* vertices2,
00155 Triangle* tri_indices1, Triangle* tri_indices2,
00156 BVH_CollideResult* res, BVHFrontList* front_list = NULL)
00157 {
00158 BVNode<BV>* node1 = tree1 + b1;
00159 BVNode<BV>* node2 = tree2 + b2;
00160
00161 bool l1 = node1->isLeaf();
00162 bool l2 = node2->isLeaf();
00163
00164 if(l1 && l2)
00165 {
00166 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00167
00168 res->num_bv_tests++;
00169 if(!node1->overlap(*node2)) return;
00170
00171 res->num_tri_tests++;
00172
00173 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1];
00174 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1];
00175
00176 const Vec3f& p1 = vertices1[tri_id1[0]];
00177 const Vec3f& p2 = vertices1[tri_id1[1]];
00178 const Vec3f& p3 = vertices1[tri_id1[2]];
00179 const Vec3f& q1 = vertices2[tri_id2[0]];
00180 const Vec3f& q2 = vertices2[tri_id2[1]];
00181 const Vec3f& q3 = vertices2[tri_id2[2]];
00182
00183 BVH_REAL penetration;
00184 Vec3f normal;
00185 int n_contacts;
00186 Vec3f contacts[2];
00187
00188
00189 if(res->num_max_contacts == 0)
00190 {
00191 if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3))
00192 {
00193 res->add(-node1->first_child - 1, -node2->first_child - 1);
00194 }
00195 }
00196 else
00197 {
00198 if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3,
00199 contacts,
00200 (unsigned int*)&n_contacts,
00201 &penetration,
00202 &normal))
00203 {
00204 for(int i = 0; i < n_contacts; ++i)
00205 {
00206 if(res->num_max_contacts <= res->numPairs()) break;
00207 res->add(-node1->first_child - 1, -node2->first_child - 1, contacts[i], penetration, normal);
00208 }
00209 }
00210
00211 }
00212
00213 return;
00214 }
00215
00216 res->num_bv_tests++;
00217 if(!node1->overlap(*node2))
00218 {
00219 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00220 return;
00221 }
00222
00223 BVH_REAL sz1 = node1->bv.size();
00224 BVH_REAL sz2 = node2->bv.size();
00225
00226 if(l2 || (!l1 && (sz1 > sz2)))
00227 {
00228 int c1 = node1->first_child;
00229 int c2 = c1 + 1;
00230
00231 collideRecurse(tree1, tree2, c1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00232
00233 if(res->numPairs() > 0 && ((res->num_max_contacts == 0) || (res->num_max_contacts <= res->numPairs()))) return;
00234
00235 collideRecurse(tree1, tree2, c2, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00236 }
00237 else
00238 {
00239 int c1 = node2->first_child;
00240 int c2 = c1 + 1;
00241
00242 collideRecurse(tree1, tree2, b1, c1, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00243
00244 if(res->numPairs() > 0 && ((res->num_max_contacts == 0) || (res->num_max_contacts <= res->numPairs()))) return;
00245
00246 collideRecurse(tree1, tree2, b1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00247 }
00248 }
00249
00251 void collideRecurse(BVNode<OBB>* tree1, BVNode<OBB>* tree2,
00252 const Vec3f R[3], const Vec3f& T,
00253 int b1, int b2,
00254 Vec3f* vertices1, Vec3f* vertices2,
00255 Triangle* tri_indices1, Triangle* tri_indices2,
00256 BVH_CollideResult* res, BVHFrontList* front_list = NULL);
00257
00259 void collideRecurse(BVNode<RSS>* tree1, BVNode<RSS>* tree2,
00260 const Vec3f R[3], const Vec3f& T,
00261 int b1, int b2,
00262 Vec3f* vertices1, Vec3f* vertices2,
00263 Triangle* tri_indices1, Triangle* tri_indices2,
00264 BVH_CollideResult* res, BVHFrontList* front_list = NULL);
00265
00267 template<typename BV>
00268 void selfCollideRecurse(BVNode<BV>* tree, int b,
00269 Vec3f* vertices, Triangle* tri_indices,
00270 BVH_CollideResult* res, BVHFrontList* front_list = NULL)
00271 {
00272 BVNode<BV>* node = tree + b;
00273 bool l = node->isLeaf();
00274
00275 if(l) return;
00276
00277 int c1 = node->first_child;
00278 int c2 = c1 + 1;
00279
00280 selfCollideRecurse(tree, c1, vertices, tri_indices, res, front_list);
00281 selfCollideRecurse(tree, c2, vertices, tri_indices, res, front_list);
00282 collideRecurse<BV>(tree, tree, c1, c2, vertices, vertices, tri_indices, tri_indices, res, front_list);
00283 }
00284
00286 template<typename BV>
00287 void continuousCollideRecurse(BVNode<BV>* tree1, BVNode<BV>* tree2, int b1, int b2,
00288 Vec3f* vertices1, Vec3f* vertices2,
00289 Vec3f* prev_vertices1, Vec3f* prev_vertices2,
00290 Triangle* tri_indices1, Triangle* tri_indices2,
00291 BVH_CollideResult* res, BVHFrontList* front_list = NULL)
00292 {
00293 BVNode<BV>* node1 = tree1 + b1;
00294 BVNode<BV>* node2 = tree2 + b2;
00295
00296 bool l1 = node1->isLeaf();
00297 bool l2 = node2->isLeaf();
00298
00299 if(l1 && l2)
00300 {
00301 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00302
00303 res->num_bv_tests++;
00304 if(!node1->overlap(*node2)) return;
00305
00306
00307 BVH_REAL collide_time = 2;
00308 Vec3f collide_pos;
00309
00310 if(tri_indices1 && tri_indices2)
00311 {
00312 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1];
00313 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1];
00314
00315 Vec3f S0[3];
00316 Vec3f S1[3];
00317 Vec3f T0[3];
00318 Vec3f T1[3];
00319
00320
00321 for(int i = 0; i < 3; ++i)
00322 {
00323 S0[i] = prev_vertices1[tri_id1[i]];
00324 S1[i] = vertices1[tri_id1[i]];
00325 T0[i] = prev_vertices2[tri_id2[i]];
00326 T1[i] = vertices2[tri_id2[i]];
00327 }
00328
00329 BVH_REAL tmp;
00330 Vec3f tmpv;
00331
00332
00333 for(int i = 0; i < 3; ++i)
00334 {
00335 res->num_vf_tests++;
00336 if(Intersect::intersect_VF(S0[0], S0[1], S0[2], T0[i], S1[0], S1[1], S1[2], T1[i], &tmp, &tmpv))
00337 {
00338 if(collide_time > tmp)
00339 {
00340 collide_time = tmp; collide_pos = tmpv;
00341 }
00342 }
00343
00344 res->num_vf_tests++;
00345 if(Intersect::intersect_VF(T0[0], T0[1], T0[2], S0[i], T1[0], T1[1], T1[2], S1[i], &tmp, &tmpv))
00346 {
00347 if(collide_time > tmp)
00348 {
00349 collide_time = tmp; collide_pos = tmpv;
00350 }
00351 }
00352 }
00353
00354
00355 for(int i = 0; i < 3; ++i)
00356 {
00357 int S_id1 = i;
00358 int S_id2 = i + 1;
00359 if(S_id2 == 3) S_id2 = 0;
00360 for(int j = 0; j < 3; ++j)
00361 {
00362 int T_id1 = j;
00363 int T_id2 = j + 1;
00364 if(T_id2 == 3) T_id2 = 0;
00365
00366 res->num_ee_tests++;
00367 if(Intersect::intersect_EE(S0[S_id1], S0[S_id2], T0[T_id1], T0[T_id2], S1[S_id1], S1[S_id2], T1[T_id1], T1[T_id2], &tmp, &tmpv))
00368 {
00369 if(collide_time > tmp)
00370 {
00371 collide_time = tmp; collide_pos = tmpv;
00372 }
00373 }
00374 }
00375 }
00376
00377
00378 }
00379 else if(tri_indices1)
00380 {
00381 BVH_REAL collide_time = 2;
00382 Vec3f collide_pos;
00383
00384 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1];
00385 int vertex_id2 = -node2->first_child - 1;
00386
00387 Vec3f S0[3];
00388 Vec3f S1[3];
00389
00390 for(int i = 0; i < 3; ++i)
00391 {
00392 S0[i] = prev_vertices1[tri_id1[i]];
00393 S1[i] = vertices1[tri_id1[i]];
00394 }
00395 Vec3f& T0 = prev_vertices2[vertex_id2];
00396 Vec3f& T1 = vertices2[vertex_id2];
00397
00398 BVH_REAL tmp;
00399 Vec3f tmpv;
00400
00401
00402 for(int i = 0; i < 3; ++i)
00403 {
00404 res->num_vf_tests++;
00405 if(Intersect::intersect_VF(S0[0], S0[1], S0[2], T0, S1[0], S1[1], S1[2], T1, &tmp, &tmpv))
00406 {
00407 if(collide_time > tmp)
00408 {
00409 collide_time = tmp; collide_pos = tmpv;
00410 }
00411 }
00412 }
00413
00414
00415 }
00416 else if(tri_indices2)
00417 {
00418 BVH_REAL collide_time = 2;
00419 Vec3f collide_pos;
00420
00421 int vertex_id1 = -node1->first_child - 1;
00422 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1];
00423
00424 Vec3f& S0 = prev_vertices1[vertex_id1];
00425 Vec3f& S1 = vertices1[vertex_id1];
00426
00427 Vec3f T0[3];
00428 Vec3f T1[3];
00429 for(int i = 0; i < 3; ++i)
00430 {
00431 T0[i] = prev_vertices2[tri_id2[i]];
00432 T1[i] = vertices2[tri_id2[i]];
00433 }
00434
00435 BVH_REAL tmp;
00436 Vec3f tmpv;
00437
00438
00439 for(int i = 0; i < 3; ++i)
00440 {
00441 res->num_vf_tests++;
00442 if(Intersect::intersect_VF(T0[0], T0[1], T0[2], S0, T1[0], T1[1], T1[2], S1, &tmp, &tmpv))
00443 {
00444 if(collide_time > tmp)
00445 {
00446 collide_time = tmp; collide_pos = tmpv;
00447 }
00448 }
00449 }
00450
00451
00452 }
00453 else
00454 {
00455
00456 }
00457
00458 if(!(collide_time > 1))
00459 {
00460 res->add(-node1->first_child - 1, -node2->first_child - 1, collide_time);
00461 }
00462
00463 return;
00464 }
00465
00466 res->num_bv_tests++;
00467 if(!node1->overlap(*node2))
00468 {
00469 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00470 return;
00471 }
00472
00473 BVH_REAL sz1 = node1->bv.size();
00474 BVH_REAL sz2 = node2->bv.size();
00475
00476 if(l2 || (!l1 && (sz1 > sz2)))
00477 {
00478 int c1 = node1->first_child;
00479 int c2 = c1 + 1;
00480
00481 continuousCollideRecurse(tree1, tree2, c1, b2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, front_list);
00482
00483 continuousCollideRecurse(tree1, tree2, c2, b2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, front_list);
00484 }
00485 else
00486 {
00487 int c1 = node2->first_child;
00488 int c2 = c1 + 1;
00489
00490 continuousCollideRecurse(tree1, tree2, b1, c1, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, front_list);
00491
00492 continuousCollideRecurse(tree1, tree2, b1, c2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, front_list);
00493 }
00494 }
00495
00497 template<typename BV>
00498 void continuousSelfCollideRecurse(BVNode<BV>* tree, int b,
00499 Vec3f* vertices, Vec3f* prev_vertices,
00500 Triangle* tri_indices,
00501 BVH_CollideResult* res, BVHFrontList* front_list = NULL)
00502 {
00503 BVNode<BV>* node = tree + b;
00504 bool l = node->isLeaf();
00505
00506 if(l) return;
00507
00508 int c1 = node->first_child;
00509 int c2 = c1 + 1;
00510
00511 continuousSelfCollideRecurse(tree, c1, vertices, prev_vertices, tri_indices, res, front_list);
00512 continuousSelfCollideRecurse(tree, c2, vertices, prev_vertices, tri_indices, res, front_list);
00513 continuousCollideRecurse<BV>(tree, tree, c1, c2, vertices, vertices, prev_vertices, prev_vertices, tri_indices, tri_indices, res, front_list);
00514 }
00515
00516
00518 template<typename BV>
00519 void propagateBVHFrontList(BVNode<BV>* tree1, BVNode<BV>* tree2,
00520 Vec3f* vertices1, Vec3f* vertices2,
00521 Triangle* tri_indices1, Triangle* tri_indices2,
00522 BVH_CollideResult* res,
00523 BVHFrontList* front_list)
00524 {
00525 BVHFrontList::iterator front_iter;
00526 BVHFrontList append;
00527 for(front_iter = front_list->begin(); front_iter != front_list->end(); ++front_iter)
00528 {
00529 int b1 = front_iter->left;
00530 int b2 = front_iter->right;
00531 BVNode<BV>* node1 = tree1 + b1;
00532 BVNode<BV>* node2 = tree2 + b2;
00533
00534
00535 bool l1 = node1->isLeaf();
00536 bool l2 = node2->isLeaf();
00537
00538 if(l1 & l2)
00539 {
00540 front_iter->valid = false;
00541 collideRecurse(tree1, tree2, b1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00542 }
00543 else
00544 {
00545 res->num_bv_tests++;
00546 if(node1->overlap(*node2))
00547 {
00548 front_iter->valid = false;
00549
00550 BVH_REAL sz1 = node1->bv.size();
00551 BVH_REAL sz2 = node2->bv.size();
00552
00553 if(l2 || (!l1 && (sz1 > sz2)))
00554 {
00555 int c1 = node1->first_child;
00556 int c2 = c1 + 1;
00557
00558 collideRecurse(tree1, tree2, c1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00559
00560 collideRecurse(tree1, tree2, c2, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00561 }
00562 else
00563 {
00564 int c1 = node2->first_child;
00565 int c2 = c1 + 1;
00566
00567 collideRecurse(tree1, tree2, b1, c1, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00568
00569 collideRecurse(tree1, tree2, b1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00570 }
00571 }
00572 }
00573 }
00574
00575
00576
00577 for(front_iter = front_list->begin(); front_iter != front_list->end();)
00578 {
00579 if(!front_iter->valid)
00580 front_iter = front_list->erase(front_iter);
00581 else
00582 ++front_iter;
00583 }
00584
00585 for(front_iter = append.begin(); front_iter != append.end(); ++front_iter)
00586 {
00587 front_list->push_back(*front_iter);
00588 }
00589 }
00590
00592 void propagateBVHFrontList(BVNode<OBB>* tree1, BVNode<OBB>* tree2,
00593 Vec3f R[3], const Vec3f& T,
00594 Vec3f* vertices1, Vec3f* vertices2,
00595 Triangle* tri_indices1, Triangle* tri_indices2,
00596 BVH_CollideResult* res,
00597 BVHFrontList* front_list);
00598
00600 void propagateBVHFrontList(BVNode<RSS>* tree1, BVNode<RSS>* tree2,
00601 Vec3f R[3], const Vec3f& T,
00602 Vec3f* vertices1, Vec3f* vertices2,
00603 Triangle* tri_indices1, Triangle* tri_indices2,
00604 BVH_CollideResult* res,
00605 BVHFrontList* front_list);
00606
00608 template<typename BV>
00609 void continuousPropagateBVHFrontList(BVNode<BV>* tree1, BVNode<BV>* tree2,
00610 Vec3f* vertices1, Vec3f* vertices2,
00611 Vec3f* prev_vertices1, Vec3f* prev_vertices2,
00612 Triangle* tri_indices1, Triangle* tri_indices2,
00613 BVH_CollideResult* res,
00614 BVHFrontList* front_list)
00615 {
00616 BVHFrontList::iterator front_iter;
00617 BVHFrontList append;
00618 for(front_iter = front_list->begin(); front_iter != front_list->end(); ++front_iter)
00619 {
00620 int b1 = front_iter->left;
00621 int b2 = front_iter->right;
00622 BVNode<BV>* node1 = tree1 + b1;
00623 BVNode<BV>* node2 = tree2 + b2;
00624
00625
00626 bool l1 = node1->isLeaf();
00627 bool l2 = node2->isLeaf();
00628
00629 if(l1 & l2)
00630 {
00631 front_iter->valid = false;
00632 continuousCollideRecurse(tree1, tree2, b1, b2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, &append);
00633 }
00634 else
00635 {
00636 res->num_bv_tests++;
00637 if(node1->overlap(*node2))
00638 {
00639 front_iter->valid = false;
00640
00641 BVH_REAL sz1 = node1->bv.size();
00642 BVH_REAL sz2 = node2->bv.size();
00643
00644 if(l2 || (!l1 && (sz1 > sz2)))
00645 {
00646 int c1 = node1->first_child;
00647 int c2 = c1 + 1;
00648
00649 continuousCollideRecurse(tree1, tree2, c1, b2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, &append);
00650
00651 continuousCollideRecurse(tree1, tree2, c2, b2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, &append);
00652 }
00653 else
00654 {
00655 int c1 = node2->first_child;
00656 int c2 = c1 + 1;
00657
00658 continuousCollideRecurse(tree1, tree2, b1, c1, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, &append);
00659
00660 continuousCollideRecurse(tree1, tree2, b1, c2, vertices1, vertices2, prev_vertices1, prev_vertices2, tri_indices1, tri_indices2, res, &append);
00661 }
00662 }
00663 }
00664 }
00665
00666
00667
00668 for(front_iter = front_list->begin(); front_iter != front_list->end();)
00669 {
00670 if(!front_iter->valid)
00671 front_iter = front_list->erase(front_iter);
00672 else
00673 ++front_iter;
00674 }
00675
00676 for(front_iter = append.begin(); front_iter != append.end(); ++front_iter)
00677 {
00678 front_list->push_back(*front_iter);
00679 }
00680 }
00681
00682 }
00683
00684 #endif