#include <collision_detectors.h>

Public Member Functions | |
| Collision_detector_Triangles_Distance () | |
| Class constructor. | |
| CollisionReport | FindCollision (void *pNode1, void *pNode2) |
Private Member Functions | |
| float | closestPointsSegmentSegment (VECTOR3 p1, VECTOR3 q1, VECTOR3 p2, VECTOR3 q2, VECTOR3 &C1, VECTOR3 &C2) |
| float | distanceSegmentSegment (VECTOR3 p1, VECTOR3 q1, VECTOR3 p2, VECTOR3 q2) |
| float | distanceVertexTriangle (VECTOR3 P, Triangle triangle) |
| VECTOR3 | closestPointVertexTriangle (VECTOR3 p, Triangle triangle) |
| float | clamp (float n, float min, float max) |
Definition at line 101 of file collision_detectors.h.
| CollisionDetectionNamespace::Collision_detector_Triangles_Distance::Collision_detector_Triangles_Distance | ( | ) | [inline] |
| CollisionReport Collision_detector_Triangles_Distance::FindCollision | ( | void * | pNode1, | |
| void * | pNode2 | |||
| ) | [virtual] |
Detect collision
| [in] | object | 1 |
| [in] | object | 2 |
Implements CollisionDetectionNamespace::Collison_Detector_IFace.
Definition at line 271 of file collision_detectors.cpp.
00272 { 00273 CollisionReport collisionReport; 00274 00275 Triangle* a = (Triangle*) pNode1; 00276 Triangle* b = (Triangle*) pNode2; 00277 00278 //float fDistance = 0; 00279 VECTOR3 C1, C2; 00280 00281 VECTOR3 closestPt; 00282 00283 // test all segments against both triangles 00284 00285 collisionReport.fSqueredSeparationDistance = closestPointsSegmentSegment(a->v1,a->v2,b->v1,b->v2,C1,C2); 00286 closestPt = (C1 + (C2 - C1)/2); 00287 //fDistance = distanceSegmentSegment(a->v1,a->v2,b->v1,b->v2); 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 //float d = distanceSegmentSegment(a->v1,a->v2,b->v1,b->v3); 00296 //if (d < fDistance) 00297 // fDistance = d; 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 //d = distanceSegmentSegment(a->v1,a->v2,b->v2,b->v3); 00307 //if (d < fDistance) 00308 // fDistance = d; 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 //d = distanceSegmentSegment(a->v1,a->v3,b->v1,b->v2); 00319 //if (d < fDistance) 00320 // fDistance = d; 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 //d = distanceSegmentSegment(a->v1,a->v3,b->v1,b->v3); 00331 //if (d < fDistance) 00332 // fDistance = d; 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 //d = distanceSegmentSegment(a->v1,a->v3,b->v2,b->v3); 00342 //if (d < fDistance) 00343 // fDistance = d; 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 //d = distanceSegmentSegment(a->v2,a->v3,b->v1,b->v2); 00354 //if (d < fDistance) 00355 // fDistance = d; 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 //d = distanceSegmentSegment(a->v2,a->v3,b->v1,b->v3); 00366 //if (d < fDistance) 00367 // fDistance = d; 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 //d = distanceSegmentSegment(a->v2,a->v3,b->v2,b->v3); 00378 //if (d < fDistance) 00379 // fDistance = d; 00380 00381 00382 // Test all points against both triangles 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 //d = distanceVertexTriangle(a->v1,*b); 00396 //if (d < fDistance) 00397 // fDistance = d; 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 //d = distanceVertexTriangle(a->v2,*b); 00411 //if (d < fDistance) 00412 // fDistance = d; 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 //d = distanceVertexTriangle(a->v3,*b); 00424 //if (d < fDistance) 00425 // fDistance = d; 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 //d = distanceVertexTriangle(b->v1,*a); 00439 //if (d < fDistance) 00440 // fDistance = d; 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 //d = distanceVertexTriangle(b->v2,*a); 00452 //if (d < fDistance) 00453 // fDistance = d; 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 //d = distanceVertexTriangle(b->v3,*a); 00466 //if (d < fDistance) 00467 // fDistance = d; 00468 00469 00470 return collisionReport; 00471 }
| float Collision_detector_Triangles_Distance::closestPointsSegmentSegment | ( | VECTOR3 | p1, | |
| VECTOR3 | q1, | |||
| VECTOR3 | p2, | |||
| VECTOR3 | q2, | |||
| VECTOR3 & | C1, | |||
| VECTOR3 & | C2 | |||
| ) | [private] |
Closest points test for 2 segments
| [in] | start | point of segment 1 |
| [in] | end | point of segment 1 |
| [in] | start | point of segment 2 |
| [in] | end | point of segment 2 |
| [out] | closest | point on segment 1 |
| [out] | closest | point on segment 2 |
Definition at line 474 of file collision_detectors.cpp.
00475 { 00476 float fDistance = 0; 00477 float s,t; // parameters of closest points 00478 00479 VECTOR3 d1 = q1 - p1; // Direction vector of S1 00480 VECTOR3 d2 = q2 - p2; // Direction vector of S2 00481 00482 VECTOR3 r = p1 - p2; 00483 00484 float a = d1.Dot(d1); // Squered lenght of S1 00485 float e = d2.Dot(d2); // Squered lenght of S2 00486 00487 float f = d2.Dot(r); 00488 00489 if (a <= EPSILON && e <= EPSILON) 00490 { 00491 // Both segments degenerate into points 00492 s = t = 0.0f; 00493 } 00494 else if (a <= EPSILON) 00495 { 00496 // first segment degenerates into point 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 // second segment degenerates into point 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 // if segments not parallel compute closest point on L1 to L2 00515 // and clamp it to segment S1, else pick s 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 // Compute closest point on L2 closest to S1(s) 00522 t = (b*s + f) / e; 00523 00524 // if t in [0,1] done. Else clamp t, recompute s for the new value t 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 }
| float Collision_detector_Triangles_Distance::distanceSegmentSegment | ( | VECTOR3 | p1, | |
| VECTOR3 | q1, | |||
| VECTOR3 | p2, | |||
| VECTOR3 | q2 | |||
| ) | [private] |
Distance test for 2 segments
| [in] | start | point of segment 1 |
| [in] | end | point of segment 1 |
| [in] | start | point of segment 2 |
| [in] | end | point of segment 2 |
Definition at line 549 of file collision_detectors.cpp.
00550 { 00551 float fDistance = 0; 00552 float s,t; // parameters of closest points 00553 00554 VECTOR3 d1 = q1 - p1; // Direction vector of S1 00555 VECTOR3 d2 = q2 - p2; // Direction vector of S2 00556 00557 VECTOR3 r = p1 - p2; 00558 00559 float a = d1.Dot(d1); // Squered lenght of S1 00560 float e = d2.Dot(d2); // Squered lenght of S2 00561 00562 float f = d2.Dot(r); 00563 00564 if (a <= EPSILON && e <= EPSILON) 00565 { 00566 // Both segments degenerate into points 00567 s = t = 0.0f; 00568 } 00569 else if (a <= EPSILON) 00570 { 00571 // first segment degenerates into point 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 // second segment degenerates into point 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 // if segments not parallel compute closest point on L1 to L2 00590 // and clamp it to segment S1, else pick s 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 // Compute closest point on L2 closest to S1(s) 00597 t = (b*s + f) / e; 00598 00599 // if t in [0,1] done. Else clamp t, recompute s for the new value t 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 }
| float Collision_detector_Triangles_Distance::distanceVertexTriangle | ( | VECTOR3 | P, | |
| Triangle | triangle | |||
| ) | [private] |
Distance test for vertex and triangle
| [in] | vertex | |
| [in] | triangle |
Definition at line 630 of file collision_detectors.cpp.
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 }
| VECTOR3 Collision_detector_Triangles_Distance::closestPointVertexTriangle | ( | VECTOR3 | p, | |
| Triangle | triangle | |||
| ) | [private] |
Closest point test for vertex and triangle
| [in] | vertex | |
| [in] | triangle |
Definition at line 644 of file collision_detectors.cpp.
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 // check if p in vertex region outside A 00654 if ( d1 <= 0.0f && d2 <= 0.0f) // Barycentric coordinates (1,0,0) 00655 { 00656 return triangle.v1; 00657 } 00658 00659 // check if p in vertex region outside B 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) // Barycentric coordinates (0,1,0) 00665 return triangle.v2; 00666 00667 // check if p in edge projection of AB 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 // check if p in vertex region outside A 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) // Barycentric coordinates (0,0,1) 00680 return triangle.v3; 00681 00682 // check if p in edge projection of AC 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 // check if p in edge projection of BC 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 // p is inside face region 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 }
| float Collision_detector_Triangles_Distance::clamp | ( | float | n, | |
| float | min, | |||
| float | max | |||
| ) | [private] |
clamp number into an interval
| [in] | number | to clamp |
| [in] | interval | min |
| [in] | interval | max |
Definition at line 623 of file collision_detectors.cpp.
1.5.5