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
00037 #include "collision_checking/collision_primitive.h"
00038
00039 namespace collision_checking
00040 {
00041
00042 BVH_CollideResult::BVH_CollideResult()
00043 {
00044 num_bv_tests = 0;
00045 num_tri_tests = 0;
00046 num_vf_tests = 0;
00047 num_ee_tests = 0;
00048
00049 query_time_seconds = 0;
00050
00051 num_pairs = num_pairs_allocated = 0;
00052 pairs = NULL;
00053
00054 num_max_contacts = 0;
00055 }
00056
00057
00058 BVH_CollideResult::~BVH_CollideResult()
00059 {
00060 delete [] pairs;
00061 }
00062
00063
00064 void BVH_CollideResult::sizeTo(int n)
00065 {
00066 BVHCollisionPair* temp;
00067
00068 if(n < num_pairs) return;
00069 temp = new BVHCollisionPair[n];
00070 memcpy(temp, pairs, sizeof(BVHCollisionPair) * num_pairs);
00071 delete [] pairs;
00072 pairs = temp;
00073 num_pairs_allocated = n;
00074 return;
00075 }
00076
00077 void BVH_CollideResult::add(int id1, int id2, BVH_REAL time)
00078 {
00079 if(num_pairs >= num_pairs_allocated)
00080 sizeTo(num_pairs_allocated * 2 + 8);
00081
00082 pairs[num_pairs].id1 = id1;
00083 pairs[num_pairs].id2 = id2;
00084 pairs[num_pairs].collide_time = time;
00085 num_pairs++;
00086 }
00087
00088 void BVH_CollideResult::add(int id1, int id2, Vec3f contact_point, BVH_REAL penetration_depth, const Vec3f& normal, BVH_REAL time)
00089 {
00090 if(num_pairs >= num_pairs_allocated)
00091 sizeTo(num_pairs_allocated * 2 + 8);
00092
00093 pairs[num_pairs].id1 = id1;
00094 pairs[num_pairs].id2 = id2;
00095 pairs[num_pairs].collide_time = time;
00096 pairs[num_pairs].penetration_depth = penetration_depth;
00097 pairs[num_pairs].normal = normal;
00098 pairs[num_pairs].contact_point = contact_point;
00099 num_pairs++;
00100 }
00101
00102
00103 void collideRecurse(BVNode<OBB>* tree1, BVNode<OBB>* tree2,
00104 const Vec3f R[3], const Vec3f& T,
00105 int b1, int b2,
00106 Vec3f* vertices1, Vec3f* vertices2,
00107 Triangle* tri_indices1, Triangle* tri_indices2,
00108 BVH_CollideResult* res, BVHFrontList* front_list)
00109 {
00110 BVNode<OBB>* node1 = tree1 + b1;
00111 BVNode<OBB>* node2 = tree2 + b2;
00112
00113 bool l1 = node1->isLeaf();
00114 bool l2 = node2->isLeaf();
00115
00116 if(l1 && l2)
00117 {
00118 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00119
00120 res->num_bv_tests++;
00121 if(!overlap(R, T, node1->bv, node2->bv)) return;
00122
00123 res->num_tri_tests++;
00124
00125 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1];
00126 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1];
00127
00128 const Vec3f& p1 = vertices1[tri_id1[0]];
00129 const Vec3f& p2 = vertices1[tri_id1[1]];
00130 const Vec3f& p3 = vertices1[tri_id1[2]];
00131
00132 const Vec3f& q1 = vertices2[tri_id2[0]];
00133 const Vec3f& q2 = vertices2[tri_id2[1]];
00134 const Vec3f& q3 = vertices2[tri_id2[2]];
00135
00136 BVH_REAL penetration;
00137 Vec3f normal;
00138 int n_contacts;
00139 Vec3f contacts[2];
00140
00141
00142 if(res->num_max_contacts == 0)
00143 {
00144 if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3,
00145 R, T))
00146 {
00147 res->add(-node1->first_child - 1, -node2->first_child - 1);
00148 }
00149 }
00150 else
00151 {
00152 if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3,
00153 R, T,
00154 contacts,
00155 (unsigned int*)&n_contacts,
00156 &penetration,
00157 &normal))
00158 {
00159 for(int i = 0; i < n_contacts; ++i)
00160 {
00161 if(res->num_max_contacts <= res->numPairs()) break;
00162 res->add(-node1->first_child - 1, -node2->first_child - 1, contacts[i], penetration, normal);
00163 }
00164 }
00165 }
00166
00167
00168
00169 return;
00170 }
00171
00172 res->num_bv_tests++;
00173 if(!overlap(R, T, node1->bv, node2->bv))
00174 {
00175 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00176 return;
00177 }
00178
00179 BVH_REAL sz1 = node1->bv.size();
00180 BVH_REAL sz2 = node2->bv.size();
00181
00182 if(l2 || (!l1 && (sz1 > sz2)))
00183 {
00184 int c1 = node1->first_child;
00185 int c2 = c1 + 1;
00186
00187 collideRecurse(tree1, tree2, R, T, c1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00188
00189 if(res->numPairs() > 0 && ((res->num_max_contacts == 0) || (res->num_max_contacts <= res->numPairs()))) return;
00190
00191 collideRecurse(tree1, tree2, R, T, c2, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00192 }
00193 else
00194 {
00195 int c1 = node2->first_child;
00196 int c2 = c1 + 1;
00197
00198 collideRecurse(tree1, tree2, R, T, b1, c1, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00199
00200 if(res->numPairs() > 0 && ((res->num_max_contacts == 0) || (res->num_max_contacts <= res->numPairs()))) return;
00201
00202 collideRecurse(tree1, tree2, R, T, b1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00203 }
00204 }
00205
00206 void collideRecurse(BVNode<RSS>* tree1, BVNode<RSS>* tree2,
00207 const Vec3f R[3], const Vec3f& T,
00208 int b1, int b2,
00209 Vec3f* vertices1, Vec3f* vertices2,
00210 Triangle* tri_indices1, Triangle* tri_indices2,
00211 BVH_CollideResult* res, BVHFrontList* front_list)
00212 {
00213 BVNode<RSS>* node1 = tree1 + b1;
00214 BVNode<RSS>* node2 = tree2 + b2;
00215
00216 bool l1 = node1->isLeaf();
00217 bool l2 = node2->isLeaf();
00218
00219 if(l1 && l2)
00220 {
00221 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00222
00223 res->num_bv_tests++;
00224 if(!overlap(R, T, node1->bv, node2->bv)) return;
00225
00226 res->num_tri_tests++;
00227
00228 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1];
00229 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1];
00230
00231 const Vec3f& p1 = vertices1[tri_id1[0]];
00232 const Vec3f& p2 = vertices1[tri_id1[1]];
00233 const Vec3f& p3 = vertices1[tri_id1[2]];
00234
00235 const Vec3f& q1 = vertices2[tri_id2[0]];
00236 const Vec3f& q2 = vertices2[tri_id2[1]];
00237 const Vec3f& q3 = vertices2[tri_id2[2]];
00238
00239 BVH_REAL penetration;
00240 Vec3f normal;
00241 int n_contacts;
00242 Vec3f contacts[2];
00243
00244
00245 if(res->num_max_contacts == 0)
00246 {
00247 if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3,
00248 R, T))
00249 {
00250 res->add(-node1->first_child - 1, -node2->first_child - 1);
00251 }
00252 }
00253 else
00254 {
00255 if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3,
00256 R, T,
00257 contacts,
00258 (unsigned int*)&n_contacts,
00259 &penetration,
00260 &normal))
00261 {
00262 for(int i = 0; i < n_contacts; ++i)
00263 {
00264 if(res->num_max_contacts <= res->numPairs()) break;
00265 res->add(-node1->first_child - 1, -node2->first_child - 1, contacts[i], penetration, normal);
00266 }
00267 }
00268 }
00269
00270
00271 return;
00272 }
00273
00274 res->num_bv_tests++;
00275 if(!overlap(R, T, node1->bv, node2->bv))
00276 {
00277 if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
00278 return;
00279 }
00280
00281 BVH_REAL sz1 = node1->bv.size();
00282 BVH_REAL sz2 = node2->bv.size();
00283
00284 if(l2 || (!l1 && (sz1 > sz2)))
00285 {
00286 int c1 = node1->first_child;
00287 int c2 = c1 + 1;
00288
00289 collideRecurse(tree1, tree2, R, T, c1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00290
00291 if(res->numPairs() > 0 && ((res->num_max_contacts == 0) || (res->num_max_contacts <= res->numPairs()))) return;
00292
00293 collideRecurse(tree1, tree2, R, T, c2, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00294 }
00295 else
00296 {
00297 int c1 = node2->first_child;
00298 int c2 = c1 + 1;
00299
00300 collideRecurse(tree1, tree2, R, T, b1, c1, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00301
00302 if(res->numPairs() > 0 && ((res->num_max_contacts == 0) || (res->num_max_contacts <= res->numPairs()))) return;
00303
00304 collideRecurse(tree1, tree2, R, T, b1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list);
00305 }
00306 }
00307
00308 void propagateBVHFrontList(BVNode<OBB>* tree1, BVNode<OBB>* tree2,
00309 Vec3f R[3], const Vec3f& T,
00310 Vec3f* vertices1, Vec3f* vertices2,
00311 Triangle* tri_indices1, Triangle* tri_indices2,
00312 BVH_CollideResult* res,
00313 BVHFrontList* front_list)
00314 {
00315 BVHFrontList::iterator front_iter;
00316 BVHFrontList append;
00317 for(front_iter = front_list->begin(); front_iter != front_list->end(); ++front_iter)
00318 {
00319 int b1 = front_iter->left;
00320 int b2 = front_iter->right;
00321 BVNode<OBB>* node1 = tree1 + b1;
00322 BVNode<OBB>* node2 = tree2 + b2;
00323
00324
00325 bool l1 = node1->isLeaf();
00326 bool l2 = node2->isLeaf();
00327
00328 if(l1 & l2)
00329 {
00330 front_iter->valid = false;
00331 collideRecurse(tree1, tree2, R, T, b1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00332 }
00333 else
00334 {
00335 res->num_bv_tests++;
00336 if(!overlap(R, T, node1->bv, node2->bv))
00337 {
00338 front_iter->valid = false;
00339
00340 BVH_REAL sz1 = node1->bv.size();
00341 BVH_REAL sz2 = node2->bv.size();
00342
00343 if(l2 || (!l1 && (sz1 > sz2)))
00344 {
00345 int c1 = node1->first_child;
00346 int c2 = c1 + 1;
00347
00348 collideRecurse(tree1, tree2, R, T, c1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00349
00350 collideRecurse(tree1, tree2, R, T, c2, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00351 }
00352 else
00353 {
00354 int c1 = node2->first_child;
00355 int c2 = c1 + 1;
00356
00357 collideRecurse(tree1, tree2, R, T, b1, c1, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00358
00359 collideRecurse(tree1, tree2, R, T, b1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00360 }
00361 }
00362 }
00363 }
00364
00365
00366
00367 for(front_iter = front_list->begin(); front_iter != front_list->end();)
00368 {
00369 if(!front_iter->valid)
00370 front_iter = front_list->erase(front_iter);
00371 else
00372 ++front_iter;
00373 }
00374
00375 for(front_iter = append.begin(); front_iter != append.end(); ++front_iter)
00376 {
00377 front_list->push_back(*front_iter);
00378 }
00379 }
00380
00381
00382 void propagateBVHFrontList(BVNode<RSS>* tree1, BVNode<RSS>* tree2,
00383 Vec3f R[3], const Vec3f& T,
00384 Vec3f* vertices1, Vec3f* vertices2,
00385 Triangle* tri_indices1, Triangle* tri_indices2,
00386 BVH_CollideResult* res,
00387 BVHFrontList* front_list)
00388 {
00389 BVHFrontList::iterator front_iter;
00390 BVHFrontList append;
00391 for(front_iter = front_list->begin(); front_iter != front_list->end(); ++front_iter)
00392 {
00393 int b1 = front_iter->left;
00394 int b2 = front_iter->right;
00395 BVNode<RSS>* node1 = tree1 + b1;
00396 BVNode<RSS>* node2 = tree2 + b2;
00397
00398
00399 bool l1 = node1->isLeaf();
00400 bool l2 = node2->isLeaf();
00401
00402 if(l1 & l2)
00403 {
00404 front_iter->valid = false;
00405 collideRecurse(tree1, tree2, R, T, b1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00406 }
00407 else
00408 {
00409 res->num_bv_tests++;
00410 if(!overlap(R, T, node1->bv, node2->bv))
00411 {
00412 front_iter->valid = false;
00413
00414 BVH_REAL sz1 = node1->bv.size();
00415 BVH_REAL sz2 = node2->bv.size();
00416
00417 if(l2 || (!l1 && (sz1 > sz2)))
00418 {
00419 int c1 = node1->first_child;
00420 int c2 = c1 + 1;
00421
00422 collideRecurse(tree1, tree2, R, T, c1, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00423
00424 collideRecurse(tree1, tree2, R, T, c2, b2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00425 }
00426 else
00427 {
00428 int c1 = node2->first_child;
00429 int c2 = c1 + 1;
00430
00431 collideRecurse(tree1, tree2, R, T, b1, c1, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00432
00433 collideRecurse(tree1, tree2, R, T, b1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, &append);
00434 }
00435 }
00436 }
00437 }
00438
00439
00440
00441 for(front_iter = front_list->begin(); front_iter != front_list->end();)
00442 {
00443 if(!front_iter->valid)
00444 front_iter = front_list->erase(front_iter);
00445 else
00446 ++front_iter;
00447 }
00448
00449 for(front_iter = append.begin(); front_iter != append.end(); ++front_iter)
00450 {
00451 front_list->push_back(*front_iter);
00452 }
00453 }
00454
00455 }