00001 #include "collision_detectors.h"
00002
00003 #include <vector>
00004
00005
00006
00007
00008 using namespace CollisionDetectionNamespace;
00009
00010
00012
00013
00014
00016
00017 CollisionReport CollisionDetector::DetectCollision(void *pNode1, void *pNode2, DetectorType type)
00018 {
00019 CollisionReport collisionReport;
00020
00021 Collison_Detector_IFace* pDetector = GetColisionDetector(type);
00022
00023 if (pDetector)
00024 {
00025 collisionReport = pDetector->FindCollision(pNode1, pNode2);
00026 delete pDetector;
00027 }
00028
00029 return collisionReport;
00030 }
00031
00032
00033
00034 Collison_Detector_IFace* CollisionDetector::GetColisionDetector(DetectorType type)
00035 {
00036 Collison_Detector_IFace* pDetector = 0;
00037
00038 switch(type)
00039 {
00040 case DT_AABB:
00041 pDetector = new Collision_detector_AABB();
00042 break;
00043 case DT_Triangle:
00044 pDetector = new Collision_detector_Triangles();
00045 break;
00046 case DT_Triangle_Distance:
00047 pDetector = new Collision_detector_Triangles_Distance();
00048 break;
00049 default:
00050 ;
00051 }
00052
00053 return pDetector;
00054 }
00055
00057
00058
00059
00061
00062 CollisionReport Collision_detector_AABB::FindCollision(void* pNode1, void* pNode2)
00063 {
00064 CollisionReport collisionReport;
00065 collisionReport.bCollide = true;
00066
00067 AABB* a = (AABB*) pNode1;
00068 AABB* b = (AABB*) pNode2;
00069
00070
00071 if ( (a->MaxBound.x < b->MinBound.x || a->MinBound.x > b->MaxBound.x)
00072 || (a->MaxBound.y < b->MinBound.y || a->MinBound.y > b->MaxBound.y)
00073 || (a->MaxBound.z < b->MinBound.z || a->MinBound.z > b->MaxBound.z))
00074 {
00075 collisionReport.bCollide = false;
00076 }
00077
00078 return collisionReport;
00079 }
00080
00081
00083
00084
00085
00087
00088 CollisionReport Collision_detector_Triangles::FindCollision(void* pNode1, void* pNode2)
00089 {
00090 CollisionReport collisionReport;
00091
00092 Triangle* a = (Triangle*) pNode1;
00093 Triangle* b = (Triangle*) pNode2;
00094
00095 VECTOR3 intersectionPoint1, intersectionPoint2, intersectionPoint3,intersectionPoint4, intersectionPoint5, intersectionPoint6;
00096 VECTOR3 finalIntersectionPoint;
00097
00098 int bV1 = (int)intersectSegmentTriangle(a->v1, a->v2, b,intersectionPoint1);
00099 int bV2 = (int)intersectSegmentTriangle(a->v1, a->v3, b,intersectionPoint2);
00100 int bV3 = (int)intersectSegmentTriangle(a->v2, a->v3, b,intersectionPoint3);
00101
00102 int bV4, bV5, bV6;
00103
00104 int bV = bV1 + bV2 + bV3;
00105
00106 switch (bV)
00107 {
00108 case 0:
00109 bV4 = (int)intersectSegmentTriangle(b->v1, b->v2, a,intersectionPoint4);
00110 bV5 = (int)intersectSegmentTriangle(b->v1, b->v3, a,intersectionPoint5);
00111 bV6 = (int)intersectSegmentTriangle(b->v2, b->v3, a,intersectionPoint6);
00112 bV = bV4 + bV5 + bV6;
00113 if (bV == 2)
00114 {
00115 collisionReport.bCollide = true;
00116
00117 if (bV4 == 1 && bV5 == 1)
00118 {
00119 finalIntersectionPoint = intersectionPoint4 + (intersectionPoint5 - intersectionPoint4);
00120 }
00121 else if (bV4 == 1 && bV6 == 1)
00122 {
00123 finalIntersectionPoint = intersectionPoint4 + (intersectionPoint6 - intersectionPoint4);
00124 }
00125 else
00126 {
00127 finalIntersectionPoint = intersectionPoint6 + (intersectionPoint5 - intersectionPoint6);
00128 }
00129
00130 }
00131 break;
00132 case 1:
00133 bV4 = (int)intersectSegmentTriangle(b->v1, b->v2, a,intersectionPoint4);
00134 if (bV4 == 1)
00135 {
00136 collisionReport.bCollide = true;
00137
00138 if (bV1 == 1)
00139 {
00140 finalIntersectionPoint = intersectionPoint1 + (intersectionPoint4 - intersectionPoint1);
00141 }
00142 else if (bV2 == 1)
00143 {
00144 finalIntersectionPoint = intersectionPoint2 + (intersectionPoint4 - intersectionPoint2);
00145 }
00146 else
00147 {
00148 finalIntersectionPoint = intersectionPoint3 + (intersectionPoint4 - intersectionPoint3);
00149 }
00150
00151 break;
00152 }
00153
00154 bV5 = (int)intersectSegmentTriangle(b->v1, b->v3, a,intersectionPoint5);
00155 if (bV5 == 1)
00156 {
00157 collisionReport.bCollide = true;
00158 if (bV1 == 1)
00159 {
00160 finalIntersectionPoint = intersectionPoint1 + (intersectionPoint5 - intersectionPoint1);
00161 }
00162 else if (bV2 == 1)
00163 {
00164 finalIntersectionPoint = intersectionPoint2 + (intersectionPoint5 - intersectionPoint2);
00165 }
00166 else
00167 {
00168 finalIntersectionPoint = intersectionPoint3 + (intersectionPoint5 - intersectionPoint3);
00169 }
00170 break;
00171 }
00172
00173 bV6 = (int)intersectSegmentTriangle(b->v2, b->v3, a,intersectionPoint6);
00174 if (bV6 == 1)
00175 {
00176 collisionReport.bCollide = true;
00177 if (bV1 == 1)
00178 {
00179 finalIntersectionPoint = intersectionPoint1 + (intersectionPoint6 - intersectionPoint1);
00180 }
00181 else if (bV2 == 1)
00182 {
00183 finalIntersectionPoint = intersectionPoint2 + (intersectionPoint6 - intersectionPoint2);
00184 }
00185 else
00186 {
00187 finalIntersectionPoint = intersectionPoint3 + (intersectionPoint6 - intersectionPoint3);
00188 }
00189 }
00190 break;
00191 case 2:
00192 collisionReport.bCollide = true;
00193 if (bV1 == 1 && bV2 == 1)
00194 {
00195 finalIntersectionPoint = intersectionPoint1 + (intersectionPoint2 - intersectionPoint1);
00196 }
00197 else if (bV1 == 1 && bV3 == 1)
00198 {
00199 finalIntersectionPoint = intersectionPoint1 + (intersectionPoint3 - intersectionPoint1);
00200 }
00201 else
00202 {
00203 finalIntersectionPoint = intersectionPoint2 + (intersectionPoint3 - intersectionPoint2);
00204 }
00205
00206
00207 break;
00208 default:
00209 break;
00210 }
00211
00212 if (collisionReport.bCollide)
00213 collisionReport.collisionPoints.push_back(finalIntersectionPoint);
00214
00215 return collisionReport;
00216 }
00217
00218 bool Collision_detector_Triangles::intersectSegmentTriangle(VECTOR3 p, VECTOR3 q, Triangle* triangle, VECTOR3& C)
00219 {
00220 VECTOR3 ab = triangle->v2 - triangle->v1;
00221 VECTOR3 ac = triangle->v3 - triangle->v1;
00222 VECTOR3 qp = p - q;
00223
00224
00225 VECTOR3 n = ab.Cross(ac);
00226
00227 float d = qp.Dot(n);
00228
00229 if (d <= 0.0f)
00230 return false;
00231
00232 VECTOR3 ap = p - triangle->v1;
00233
00234 float t = ap.Dot(n);
00235 if (t < 0.0f || t > d)
00236 return false;
00237
00238 VECTOR3 e = qp.Cross(ap);
00239 float v = ac.Dot(e);
00240 if (v < 0.0f || v > d)
00241 return false;
00242
00243 float w = -ab.Dot(e);
00244 if (w < 0.0f || v + w > d)
00245 return false;
00246
00247
00248
00249
00250 float ood = 1.0f / d;
00251 t *= ood;
00252 v *= ood;
00253 w *= ood;
00254 float u = 1.0f - v -w;
00255
00256 C = p + t*(q-p);
00257
00258
00259
00260 return true;
00261 }
00262
00263
00265
00266
00267
00269
00270
00271 CollisionReport Collision_detector_Triangles_Distance::FindCollision(void* pNode1, void* pNode2)
00272 {
00273 CollisionReport collisionReport;
00274
00275 Triangle* a = (Triangle*) pNode1;
00276 Triangle* b = (Triangle*) pNode2;
00277
00278
00279 VECTOR3 C1, C2;
00280
00281 VECTOR3 closestPt;
00282
00283
00284
00285 collisionReport.fSqueredSeparationDistance = closestPointsSegmentSegment(a->v1,a->v2,b->v1,b->v2,C1,C2);
00286 closestPt = (C1 + (C2 - C1)/2);
00287
00288
00289 float d = closestPointsSegmentSegment(a->v1,a->v2,b->v1,b->v3,C1,C2);
00290 if ( d < collisionReport.fSqueredSeparationDistance)
00291 {
00292 collisionReport.fSqueredSeparationDistance = d;
00293 closestPt = (C1 + (C2 - C1)/2);
00294 }
00295
00296
00297
00298
00299 d = closestPointsSegmentSegment(a->v1,a->v2,b->v2,b->v3,C1,C2);
00300 if ( d < collisionReport.fSqueredSeparationDistance)
00301 {
00302 collisionReport.fSqueredSeparationDistance = d;
00303 closestPt = (C1 + (C2 - C1)/2);
00304 }
00305
00306
00307
00308
00309
00310
00311 d = closestPointsSegmentSegment(a->v1,a->v3,b->v1,b->v2,C1,C2);
00312 if ( d < collisionReport.fSqueredSeparationDistance)
00313 {
00314 collisionReport.fSqueredSeparationDistance = d;
00315 closestPt = (C1 + (C2 - C1)/2);
00316 }
00317
00318
00319
00320
00321
00322
00323 d = closestPointsSegmentSegment(a->v1,a->v3,b->v1,b->v3,C1,C2);
00324 if ( d < collisionReport.fSqueredSeparationDistance)
00325 {
00326 collisionReport.fSqueredSeparationDistance = d;
00327 closestPt = (C1 + (C2 - C1)/2);
00328 }
00329
00330
00331
00332
00333
00334 d = closestPointsSegmentSegment(a->v1,a->v3,b->v2,b->v3,C1,C2);
00335 if ( d < collisionReport.fSqueredSeparationDistance)
00336 {
00337 collisionReport.fSqueredSeparationDistance = d;
00338 closestPt = (C1 + (C2 - C1)/2);
00339 }
00340
00341
00342
00343
00344
00345
00346 d = closestPointsSegmentSegment(a->v2,a->v3,b->v1,b->v2,C1,C2);
00347 if ( d < collisionReport.fSqueredSeparationDistance)
00348 {
00349 collisionReport.fSqueredSeparationDistance = d;
00350 closestPt = (C1 + (C2 - C1)/2);
00351 }
00352
00353
00354
00355
00356
00357
00358 d = closestPointsSegmentSegment(a->v2,a->v3,b->v1,b->v3,C1,C2);
00359 if ( d < collisionReport.fSqueredSeparationDistance)
00360 {
00361 collisionReport.fSqueredSeparationDistance = d;
00362 closestPt = (C1 + (C2 - C1)/2);
00363 }
00364
00365
00366
00367
00368
00369
00370 d = closestPointsSegmentSegment(a->v2,a->v3,b->v2,b->v3,C1,C2);
00371 if ( d < collisionReport.fSqueredSeparationDistance)
00372 {
00373 collisionReport.fSqueredSeparationDistance = d;
00374 closestPt = (C1 + (C2 - C1)/2);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 VECTOR3 pt = closestPointVertexTriangle(a->v1,*b);
00386 VECTOR3 v = (a->v1 - pt);
00387 d = v.Dot(v);
00388 if ( d < collisionReport.fSqueredSeparationDistance)
00389 {
00390 collisionReport.fSqueredSeparationDistance = d;
00391 closestPt = (pt + (v / 2));
00392 }
00393
00394
00395
00396
00397
00398
00399
00400 pt = closestPointVertexTriangle(a->v2,*b);
00401 v = (a->v2 - pt);
00402 d = v.Dot(v);
00403 if ( d < collisionReport.fSqueredSeparationDistance)
00404 {
00405 collisionReport.fSqueredSeparationDistance = d;
00406 closestPt = (pt + (v / 2));
00407 }
00408
00409
00410
00411
00412
00413
00414 pt = closestPointVertexTriangle(a->v3,*b);
00415 v = (a->v3 - pt);
00416 d = v.Dot(v);
00417 if ( d < collisionReport.fSqueredSeparationDistance)
00418 {
00419 collisionReport.fSqueredSeparationDistance = d;
00420 closestPt = (pt + (v / 2));
00421 }
00422
00423
00424
00425
00426
00427
00428 pt = closestPointVertexTriangle(b->v1,*a);
00429 v = (b->v1 - pt);
00430 d = v.Dot(v);
00431 if ( d < collisionReport.fSqueredSeparationDistance)
00432 {
00433 collisionReport.fSqueredSeparationDistance = d;
00434 closestPt = (pt + (v / 2));
00435 }
00436
00437
00438
00439
00440
00441
00442 pt = closestPointVertexTriangle(b->v2,*a);
00443 v = (b->v2 - pt);
00444 d = v.Dot(v);
00445 if ( d < collisionReport.fSqueredSeparationDistance)
00446 {
00447 collisionReport.fSqueredSeparationDistance = d;
00448 closestPt = (pt + (v / 2));
00449 }
00450
00451
00452
00453
00454
00455 pt = closestPointVertexTriangle(b->v3,*a);
00456 v = (b->v3 - pt);
00457 d = v.Dot(v);
00458 if ( d < collisionReport.fSqueredSeparationDistance)
00459 {
00460 collisionReport.fSqueredSeparationDistance = d;
00461 closestPt = (pt + (v / 2));
00462 }
00463
00464 collisionReport.collisionPoints.push_back(closestPt);
00465
00466
00467
00468
00469
00470 return collisionReport;
00471 }
00472
00473
00474 float Collision_detector_Triangles_Distance::closestPointsSegmentSegment(VECTOR3 p1,VECTOR3 q1,VECTOR3 p2,VECTOR3 q2, VECTOR3& C1, VECTOR3& C2)
00475 {
00476 float fDistance = 0;
00477 float s,t;
00478
00479 VECTOR3 d1 = q1 - p1;
00480 VECTOR3 d2 = q2 - p2;
00481
00482 VECTOR3 r = p1 - p2;
00483
00484 float a = d1.Dot(d1);
00485 float e = d2.Dot(d2);
00486
00487 float f = d2.Dot(r);
00488
00489 if (a <= EPSILON && e <= EPSILON)
00490 {
00491
00492 s = t = 0.0f;
00493 }
00494 else if (a <= EPSILON)
00495 {
00496
00497 s = 0.0f;
00498 t = clamp(f/e,0.0f,1.0f);
00499 }
00500 else
00501 {
00502 float c = d1.Dot(r);
00503 if ( e <= EPSILON)
00504 {
00505
00506 t = 0.0f;
00507 s = clamp(-c/a,0.0f,1.0f);
00508 }
00509 else
00510 {
00511 float b = d1.Dot(d2);
00512 float denom = a*e - b*b;
00513
00514
00515
00516 if (denom != 0.0f)
00517 s = clamp((b*f-c*e)/denom,0.0f,1.0f);
00518 else
00519 s = 0.0f;
00520
00521
00522 t = (b*s + f) / e;
00523
00524
00525 if ( t < 0.0f)
00526 {
00527 t = 0.0f;
00528 s = clamp(-c/a,0.0f, 1.0f);
00529 }
00530 else if (t > 1.0f)
00531 {
00532 t = 1.0f;
00533 s = clamp((b-c)/a,0.0f, 1.0f);
00534 }
00535 }
00536 }
00537
00538 C1 = p1 + d1*s;
00539 C2 = p2 + d2*t;
00540
00541 VECTOR3 x = C2-C1;
00542
00543 fDistance = x.Dot(x);
00544
00545 return fDistance;
00546 }
00547
00548
00549 float Collision_detector_Triangles_Distance::distanceSegmentSegment(VECTOR3 p1,VECTOR3 q1,VECTOR3 p2,VECTOR3 q2)
00550 {
00551 float fDistance = 0;
00552 float s,t;
00553
00554 VECTOR3 d1 = q1 - p1;
00555 VECTOR3 d2 = q2 - p2;
00556
00557 VECTOR3 r = p1 - p2;
00558
00559 float a = d1.Dot(d1);
00560 float e = d2.Dot(d2);
00561
00562 float f = d2.Dot(r);
00563
00564 if (a <= EPSILON && e <= EPSILON)
00565 {
00566
00567 s = t = 0.0f;
00568 }
00569 else if (a <= EPSILON)
00570 {
00571
00572 s = 0.0f;
00573 t = clamp(f/e,0.0f,1.0f);
00574 }
00575 else
00576 {
00577 float c = d1.Dot(r);
00578 if ( e <= EPSILON)
00579 {
00580
00581 t = 0.0f;
00582 s = clamp(-c/a,0.0f,1.0f);
00583 }
00584 else
00585 {
00586 float b = d1.Dot(d2);
00587 float denom = a*e - b*b;
00588
00589
00590
00591 if (denom != 0.0f)
00592 s = clamp((b*f-c*e)/denom,0.0f,1.0f);
00593 else
00594 s = 0.0f;
00595
00596
00597 t = (b*s + f) / e;
00598
00599
00600 if ( t < 0.0f)
00601 {
00602 t = 0.0f;
00603 s = clamp(-c/a,0.0f, 1.0f);
00604 }
00605 else if (t > 1.0f)
00606 {
00607 t = 1.0f;
00608 s = clamp((b-c)/a,0.0f, 1.0f);
00609 }
00610 }
00611 }
00612
00613 VECTOR3 c1 = p1 + d1*s;
00614 VECTOR3 c2 = p2 + d2*t;
00615
00616 VECTOR3 x = c2-c1;
00617
00618 fDistance = x.Dot(x);
00619
00620 return fDistance;
00621 }
00622
00623 float Collision_detector_Triangles_Distance::clamp(float n, float min, float max)
00624 {
00625 if (n < min) return min;
00626 if (n > max) return max;
00627 return n;
00628 }
00629
00630 float Collision_detector_Triangles_Distance::distanceVertexTriangle(VECTOR3 p, Triangle triangle)
00631 {
00632 float fDistance = 0;
00633 VECTOR3 closestPoint = closestPointVertexTriangle(p,triangle);
00634
00635
00636 VECTOR3 d = p - closestPoint;
00637
00638
00639 fDistance = d.Dot(d);
00640
00641 return fDistance;
00642 }
00643
00644 VECTOR3 Collision_detector_Triangles_Distance::closestPointVertexTriangle(VECTOR3 p, Triangle triangle)
00645 {
00646 VECTOR3 ab = triangle.v2 - triangle.v1;
00647 VECTOR3 ac = triangle.v3 - triangle.v1;
00648 VECTOR3 ap = p - triangle.v1;
00649
00650 float d1 = ab.Dot(ap);
00651 float d2 = ac.Dot(ap);
00652
00653
00654 if ( d1 <= 0.0f && d2 <= 0.0f)
00655 {
00656 return triangle.v1;
00657 }
00658
00659
00660 VECTOR3 bp = p - triangle.v2;
00661 float d3 = ab.Dot(bp);
00662 float d4 = ac.Dot(bp);
00663
00664 if (d3 >= 0.0f && d4 <= d3)
00665 return triangle.v2;
00666
00667
00668 float vc = d1*d4 - d3*d2;
00669 if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f)
00670 {
00671 float v = d1 / (d1-d3);
00672 return triangle.v1+v*ab;
00673 }
00674
00675
00676 VECTOR3 cp = p - triangle.v3;
00677 float d5 = ab.Dot(cp);
00678 float d6 = ac.Dot(cp);
00679 if (d6 >= 0.0f && d5 <= d6)
00680 return triangle.v3;
00681
00682
00683 float vb = d5*d2 - d1*d6;
00684 if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f)
00685 {
00686 float w = d2 / (d2-d6);
00687 return triangle.v1+w*ac;
00688 }
00689
00690
00691 float va = d3*d6 - d5*d4;
00692 if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f)
00693 {
00694 float w = (d4 - d3) / ((d4-d3)+(d5-d6));
00695 return triangle.v2 + w * (triangle.v3-triangle.v2);
00696 }
00697
00698
00699 float denom = 1.0f / (va +vb +vc);
00700 float v = vb * denom;
00701 float w = vc * denom;
00702
00703 return triangle.v1 + ab*v + ac*w;
00704 }