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 #include <sofa/component/collision/ContinuousTriangleIntersection.h>
00026 #include <sofa/helper/rmath.h>
00027
00028 namespace sofa
00029 {
00030
00031 namespace component
00032 {
00033
00034 namespace collision
00035 {
00036
00037 bool ContinuousTriangleIntersection::isCollision(void)
00038 {
00039 SReal t[3], u[3], v[3];
00040 double dt = 0.01;
00041
00042
00043
00044
00045 if (intersectPointTriangle(t[0], u[0], v[0], tr2.p1(), tr2.v1(), tr1.p1(), tr1.v1(), tr1.p2(), tr1.v2(), tr1.p3(), tr1.v3(), dt))
00046 {
00047
00048 return true;
00049 }
00050
00051 if (intersectPointTriangle(t[1], u[1], v[1], tr2.p2(), tr2.v2(), tr1.p1(), tr1.v1(), tr1.p2(), tr1.v2(), tr1.p3(), tr1.v3(), dt))
00052 {
00053
00054 return true;
00055 }
00056
00057 if (intersectPointTriangle(t[2], u[2], v[2], tr2.p3(), tr2.v3(), tr1.p1(), tr1.v1(), tr1.p2(), tr1.v2(), tr1.p3(), tr1.v3(), dt))
00058 {
00059
00060 return true;
00061 }
00062
00063 if (intersectPointTriangle(t[0], u[0], v[0], tr1.p1(), tr1.v1(), tr2.p1(), tr2.v1(), tr2.p2(), tr2.v2(), tr2.p3(), tr2.v3(), dt))
00064 {
00065
00066 return true;
00067 }
00068
00069 if (intersectPointTriangle(t[1], u[1], v[1], tr1.p2(), tr1.v2(), tr2.p1(), tr2.v1(), tr2.p2(), tr2.v2(), tr2.p3(), tr2.v3(), dt))
00070 {
00071
00072 return true;
00073 }
00074
00075 if (intersectPointTriangle(t[2], u[2], v[2], tr1.p3(), tr1.v3(), tr2.p1(), tr2.v1(), tr2.p2(), tr2.v2(), tr2.p3(), tr2.v3(), dt))
00076 {
00077
00078 return true;
00079 }
00080
00081 if (intersectEdgeEdge(t[0], u[0], v[0], tr1.p1(), tr1.p2(), tr1.v1(), tr1.v2(), tr2.p1(), tr2.p2(), tr2.v1(), tr2.v2(), dt))
00082 {
00083
00084 return true;
00085 }
00086
00087 if (intersectEdgeEdge(t[1], u[1], v[1], tr1.p1(), tr1.p3(), tr1.v1(), tr1.v3(), tr2.p1(), tr2.p2(), tr2.v1(), tr2.v2(), dt))
00088 {
00089
00090 return true;
00091 }
00092
00093 if (intersectEdgeEdge(t[2], u[2], v[2], tr1.p2(), tr1.p3(), tr1.v2(), tr1.v3(), tr2.p1(), tr2.p2(), tr2.v1(), tr2.v2(), dt))
00094 {
00095
00096 return true;
00097 }
00098
00099 if (intersectEdgeEdge(t[0], u[0], v[0], tr1.p1(), tr1.p2(), tr1.v1(), tr1.v2(), tr2.p1(), tr2.p3(), tr2.v1(), tr2.v3(), dt))
00100 {
00101
00102 return true;
00103 }
00104
00105 if (intersectEdgeEdge(t[1], u[1], v[1], tr1.p1(), tr1.p3(), tr1.v1(), tr1.v3(), tr2.p1(), tr2.p3(), tr2.v1(), tr2.v3(), dt))
00106 {
00107
00108 return true;
00109 }
00110
00111 if (intersectEdgeEdge(t[2], u[2], v[2], tr1.p2(), tr1.p3(), tr1.v2(), tr1.v3(), tr2.p1(), tr2.p3(), tr2.v1(), tr2.v3(), dt))
00112 {
00113
00114 return true;
00115 }
00116
00117 if (intersectEdgeEdge(t[0], u[0], v[0], tr1.p1(), tr1.p2(), tr1.v1(), tr1.v2(), tr2.p2(), tr2.p3(), tr2.v2(), tr2.v3(), dt))
00118 {
00119
00120 return true;
00121 }
00122
00123 if (intersectEdgeEdge(t[1], u[1], v[1], tr1.p1(), tr1.p3(), tr1.v1(), tr1.v3(), tr2.p2(), tr2.p3(), tr2.v2(), tr2.v3(), dt))
00124 {
00125
00126 return true;
00127 }
00128
00129 if (intersectEdgeEdge(t[2], u[2], v[2], tr1.p2(), tr1.p3(), tr1.v2(), tr1.v3(), tr2.p2(), tr2.p3(), tr2.v2(), tr2.v3(), dt))
00130 {
00131
00132 return true;
00133 }
00134
00135 return false;
00136
00137 }
00138
00139 core::componentmodel::collision::DetectionOutput* ContinuousTriangleIntersection::computeDetectionOutput (void)
00140 {
00141 SReal t[3], u[3], v[3];
00142 double dt = 0.01;
00143
00144 for (int i = 0; i < 3; i++)
00145 t[i] = u[i] = v[i] = 0.0;
00146
00147 intersectPointTriangle(t[0], u[0], v[0], tr2.p1(), tr2.v1(), tr1.p1(), tr1.v1(), tr1.p2(), tr1.v2(), tr1.p3(), tr1.v3(), dt);
00148 intersectPointTriangle(t[1], u[1], v[1], tr2.p2(), tr2.v2(), tr1.p1(), tr1.v1(), tr1.p2(), tr1.v2(), tr1.p3(), tr1.v3(), dt);
00149 intersectPointTriangle(t[2], u[2], v[2], tr2.p3(), tr2.v3(), tr1.p1(), tr1.v1(), tr1.p2(), tr1.v2(), tr1.p3(), tr1.v3(), dt);
00150
00151
00152
00153 intersectPointTriangle(t[0], u[0], v[0], tr1.p1(), tr1.v1(), tr2.p1(), tr2.v1(), tr2.p2(), tr2.v2(), tr2.p3(), tr2.v3(), dt);
00154 intersectPointTriangle(t[1], u[1], v[1], tr1.p2(), tr1.v2(), tr2.p1(), tr2.v1(), tr2.p2(), tr2.v2(), tr2.p3(), tr2.v3(), dt);
00155 intersectPointTriangle(t[2], u[2], v[2], tr1.p3(), tr1.v3(), tr2.p1(), tr2.v1(), tr2.p2(), tr2.v2(), tr2.p3(), tr2.v3(), dt);
00156
00157
00158
00159 intersectEdgeEdge(t[0], u[0], v[0], tr1.p1(), tr1.p2(), tr1.v1(), tr1.v2(), tr2.p1(), tr2.p2(), tr2.v1(), tr2.v2(), dt);
00160 intersectEdgeEdge(t[1], u[1], v[1], tr1.p1(), tr1.p3(), tr1.v1(), tr1.v3(), tr2.p1(), tr2.p2(), tr2.v1(), tr2.v2(), dt);
00161 intersectEdgeEdge(t[2], u[2], v[2], tr1.p2(), tr1.p3(), tr1.v2(), tr1.v3(), tr2.p1(), tr2.p2(), tr2.v1(), tr2.v2(), dt);
00162
00163
00164
00165 intersectEdgeEdge(t[0], u[0], v[0], tr1.p1(), tr1.p2(), tr1.v1(), tr1.v2(), tr2.p1(), tr2.p3(), tr2.v1(), tr2.v3(), dt);
00166 intersectEdgeEdge(t[1], u[1], v[1], tr1.p1(), tr1.p3(), tr1.v1(), tr1.v3(), tr2.p1(), tr2.p3(), tr2.v1(), tr2.v3(), dt);
00167 intersectEdgeEdge(t[2], u[2], v[2], tr1.p2(), tr1.p3(), tr1.v2(), tr1.v3(), tr2.p1(), tr2.p3(), tr2.v1(), tr2.v3(), dt);
00168
00169
00170
00171 intersectEdgeEdge(t[0], u[0], v[0], tr1.p1(), tr1.p2(), tr1.v1(), tr1.v2(), tr2.p2(), tr2.p3(), tr2.v2(), tr2.v3(), dt);
00172 intersectEdgeEdge(t[1], u[1], v[1], tr1.p1(), tr1.p3(), tr1.v1(), tr1.v3(), tr2.p2(), tr2.p3(), tr2.v2(), tr2.v3(), dt);
00173 intersectEdgeEdge(t[2], u[2], v[2], tr1.p2(), tr1.p3(), tr1.v2(), tr1.v3(), tr2.p2(), tr2.p3(), tr2.v2(), tr2.v3(), dt);
00174
00175
00176 core::componentmodel::collision::DetectionOutput *detectionOutput = new core::componentmodel::collision::DetectionOutput();
00177 detectionOutput->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(tr1, tr2);
00178
00179 return detectionOutput;
00180 }
00181
00182 ContinuousTriangleIntersection::ContinuousTriangleIntersection(Triangle& t1, Triangle &t2):tr1(t1), tr2(t2),m_tolerance((SReal)(1e-6))
00183 {
00184 m_tolmin = -m_tolerance;
00185 m_tolmax = (SReal)1.0 + m_tolerance;
00186 }
00187
00189 ContinuousTriangleIntersection::~ContinuousTriangleIntersection()
00190 {
00191
00192 }
00193
00203 int ContinuousTriangleIntersection::intersectEdgeEdge (SReal& t, SReal& u, SReal& v,
00204 const Vector3& p1, const Vector3& p2,
00205 const Vector3& v1, const Vector3& v2,
00206 const Vector3& p3, const Vector3& p4,
00207 const Vector3& v3, const Vector3& v4,
00208 double dt)
00209 {
00210 Vector3 d12, d13, d34, x12, x13, x34;
00211 SReal N1x, N1y, N1z, N2x, N2y, N2z, N3x, N3y, N3z;
00212 SReal C[4];
00213 Vector3 roots(-10,-10,-10);
00214 int numRoots;
00215
00216 d12 = (v2 - v1)*dt;
00217 d34 = (v4 - v3)*dt;
00218 d13 = (v3 - v1)*dt;
00219 x12 = p2 - p1;
00220 x13 = p3 - p1;
00221 x34 = p4 - p3;
00222
00230
00231 N1x = d12[1]*d34[2] - d12[2]*d34[1];
00232 N2x = x12[1]*d34[2] + d12[1]*x34[2] - x12[2]*d34[1] - x34[1]*d12[2];
00233 N3x = x12[1]*x34[2] - x12[2]*x34[1];
00234
00235 N1y = d12[2]*d34[0] - d12[0]*d34[2];
00236 N2y = x12[2]*d34[0] + d12[2]*x34[0] - x12[0]*d34[2] - x34[2]*d12[0];
00237 N3y = x12[2]*x34[0] - x12[0]*x34[2];
00238
00239 N1z = d12[0]*d34[1] - d12[1]*d34[0];
00240 N2z = x12[0]*d34[1] + d12[0]*x34[1] - x12[1]*d34[0] - x34[0]*d12[1];
00241 N3z = x12[0]*x34[1] - x12[1]*x34[0];
00242
00247
00248 C[3] = d13[0]*N1x + d13[1]*N1y + d13[2]*N1z;
00249 C[2] = x13[0]*N1x + d13[0]*N2x + x13[1]*N1y + d13[1]*N2y + x13[2]*N1z + d13[2]*N2z;
00250 C[1] = x13[0]*N2x + d13[0]*N3x + x13[1]*N2y + d13[1]*N3y + x13[2]*N2z + d13[2]*N3z;
00251 C[0] = x13[0]*N3x + x13[1]*N3y + x13[2]*N3z;
00252
00254 if (C[3] < -EPSILON || C[3] > EPSILON)
00255 numRoots = solveCubic( roots, C );
00257 else
00258 numRoots = solveQuadratic(roots[0], roots[1], C[2], C[1], C[0]);
00259
00261 bool isCorrectTime = checkValidRoots (t,
00262 numRoots,
00263 roots,
00264 m_tolmin,
00265 m_tolmax);
00266
00267 if (!isCorrectTime)
00268 return 0;
00269
00273 x12 += d12*t;
00274 x34 += d34*t;
00275 x13 += d13*t;
00276
00278
00279 SReal det = dot(x12, x12) * dot(x34, x34) - dot(x12, x34) * dot(x12, x34);
00280
00281 if (det > -EPSILON && det < EPSILON)
00282 {
00283 std::cerr << "~ContinuousTriangleIntersection::intersectEdgeEdge: POSSIBLY PARALLEL EDGES, CANNOT FIND DETERMINANT" << std::endl;
00284
00285 return 0;
00286 }
00287
00288 SReal inv_det = (SReal)1.0/det;
00289 u = inv_det*(dot(x12, x13) * dot(x34,x34) - dot(x12, x34) * dot(x13, x34));
00290
00291 if (u < m_tolmin || u > m_tolmax)
00292 return 0;
00293
00294 v = inv_det*(dot(x12, x34) * dot(x12, x13) - dot(x12, x12) * dot(x13, x34) );
00295
00296 if (v < m_tolmin || v > m_tolmax)
00297 return 0;
00298
00299 return 1;
00300 }
00301
00310 int ContinuousTriangleIntersection::intersectPointTriangle (SReal& t, SReal& u, SReal& v,
00311 const Vector3& p0, const Vector3& v0,
00312 const Vector3& p1, const Vector3& v1,
00313 const Vector3& p2, const Vector3& v2,
00314 const Vector3& p3, const Vector3& v3,
00315 double dt)
00316 {
00317 Vector3 p12, v12, p13, v13, p01, v01;
00318 SReal N1x, N1y, N1z, N2x, N2y, N2z, N3x, N3y, N3z;
00319 SReal C[4];
00320 Vector3 roots(-10,-10,-10);
00321
00329
00330 p12 = p2 - p1;
00331 p13 = p3 - p1;
00332 p01 = p1 - p0;
00333
00334 v12 = (v2 - v1) * dt;
00335 v13 = (v3 - v1) * dt;
00336 v01 = (v1 - v0) * dt;
00337
00338 N1x = v12[1]*v13[2] - v12[2]*v13[1];
00339 N2x = p12[1]*v13[2] + v12[1]*p13[2] - p12[2]*v13[1] - p13[1]*v12[2];
00340 N3x = p12[1]*p13[2] - p12[2]*p13[1];
00341
00342 N1y = v12[2]*v13[0] - v12[0]*v13[2];
00343 N2y = p12[2]*v13[0] + v12[2]*p13[0] - p12[0]*v13[2] - p13[2]*v12[0];
00344 N3y = p12[2]*p13[0] - p12[0]*p13[2];
00345
00346 N1z = v12[0]*v13[1] - v12[1]*v13[0];
00347 N2z = p12[0]*v13[1] + v12[0]*p13[1] - p12[1]*v13[0] - p13[0]*v12[1];
00348 N3z = p12[0]*p13[1] - p12[1]*p13[0];
00349
00354
00355 C[3] = v01[0]*N1x + v01[1]*N1y + v01[2]*N1z;
00356 C[2] = p01[0]*N1x + v01[0]*N2x + p01[1]*N1y + v01[1]*N2y + p01[2]*N1z + v01[2]*N2z;
00357 C[1] = p01[0]*N2x + v01[0]*N3x + p01[1]*N2y + v01[1]*N3y + p01[2]*N2z + v01[2]*N3z;
00358 C[0] = p01[0]*N3x + p01[1]*N3y + p01[2]*N3z;
00359
00360 int numRoots;
00361
00363 if (C[3] < -EPSILON || C[3] > EPSILON)
00364 numRoots = solveCubic (roots, C);
00366 else
00367 numRoots = solveQuadratic (roots[0], roots[1], C[2], C[1], C[0]);
00368
00370 bool isCorrectTime = checkValidRoots (t, numRoots, roots, m_tolmin, m_tolmax);
00371
00372 if (!isCorrectTime)
00373 return 0;
00374
00378
00379 Vector3 x4 = p0 + v0*t*dt;
00380 Vector3 x1 = p1 + v1*t*dt;
00381 Vector3 x2 = p2 + v2*t*dt;
00382 Vector3 x3 = p3 + v3*t*dt;
00383
00384 Vector3 x43 = x3 - x4;
00385 Vector3 x13 = x3 - x1;
00386 Vector3 x23 = x3 - x2;
00387
00389 SReal det = dot (x13, x13) * dot(x23, x23) - dot(x13, x23) * dot(x13, x23);
00390
00391 if (det > -EPSILON && det < EPSILON)
00392 {
00393 std::cerr << "ContinousTriangleIntersection::intersectPointTriangle: POSSIBLY POINT IS PARALLEL TO PLANE, CANNOT FIND DETERMINANT" << std::endl;
00394 return 0;
00395 }
00396
00398 SReal inv_det = (SReal)1./det;
00399 u = inv_det * ( dot (x13, x43) * dot(x23, x23) - dot(x13, x23) * dot (x23, x43) );
00400
00401 if (u < m_tolmin || u > m_tolmax)
00402 {
00403 t = -10;
00404 return 0;
00405 }
00406
00407 v = inv_det * ( dot(x13, x13) * dot(x23, x43) - dot(x13, x23) * dot(x13, x43) );
00408
00409 if (v < m_tolmin || u + v > m_tolmax)
00410 {
00411 t = -10;
00412 return 0;
00413 }
00414
00415 return 1;
00416 }
00417
00423 int ContinuousTriangleIntersection::solveCubic (Vector3& s, SReal c[4] )
00424 {
00425 int i, num;
00426 SReal sub;
00427 SReal A, B, C;
00428 SReal sq_A, p, q;
00429 SReal cb_p, D;
00430
00432
00433 A = c[ 2 ] / c[ 3 ];
00434 B = c[ 1 ] / c[ 3 ];
00435 C = c[ 0 ] / c[ 3 ];
00436
00439
00440 sq_A = A * A;
00441 p = (SReal)1.0/3 * ((SReal)(-1.0/3) * sq_A + B);
00442 q = (SReal)1.0/2 * ((SReal)(2.0/27) * A * sq_A - (SReal)(1.0/3) * A * B + C);
00443
00445
00446 cb_p = p * p * p;
00447 D = q * q + cb_p;
00448
00449 if (IsZero(D))
00450 {
00451 if (IsZero(q))
00452 {
00453 s[ 0 ] = 0;
00454 num = 1;
00455 }
00456 else
00457 {
00458 SReal u = cbrt(-q);
00459 s[ 0 ] = 2 * u;
00460 s[ 1 ] = - u;
00461 num = 2;
00462 }
00463 }
00464 else if (D < 0)
00465 {
00466 SReal phi = (SReal)1.0/3 * acos(-q / sqrt(-cb_p));
00467 SReal t = 2 * sqrt(-p);
00468
00469 s[ 0 ] = t * cos(phi);
00470 s[ 1 ] = - t * cos(phi + (SReal)R_PI / 3);
00471 s[ 2 ] = - t * cos(phi - (SReal)R_PI / 3);
00472 num = 3;
00473 }
00474 else
00475 {
00476 SReal sqrt_D = sqrt(D);
00477 SReal u = cbrt(sqrt_D - q);
00478 SReal v = - cbrt(sqrt_D + q);
00479
00480 s[ 0 ] = u + v;
00481 num = 1;
00482 }
00483
00485
00486 sub = (SReal)1.0/3 * A;
00487
00488 for (i = 0; i < num; ++i)
00489 s[ i ] -= sub;
00490
00491 return num;
00492 }
00493
00494
00501 int ContinuousTriangleIntersection::solveQuadratic (SReal& t1, SReal& t2, const SReal& a,
00502 const SReal& b, const SReal& c)
00503 {
00504 int numRoots=0;
00505 SReal delta = b*b - (SReal)4.0*a*c;
00506 if (delta < 0.0)
00507 return 0;
00508
00509 SReal sqrt_delta = sqrt(delta);
00510
00511 SReal sgn_b;
00512 if (b<0.0)
00513 sgn_b=-1.0;
00514 else
00515 sgn_b=1.0;
00516
00517 SReal q = (SReal)(-0.5)*(b+sgn_b*sqrt_delta);
00518
00519 if (a < -EPSILON || a > EPSILON)
00520 {
00521 t2 = q/a;
00522 numRoots++;
00523 }
00524
00525 if (q < -EPSILON || q > EPSILON)
00526 {
00527 t1 = c/q;
00528
00529 numRoots++;
00530 }
00531
00532
00533
00534
00535 return numRoots;
00536 }
00537
00542 bool ContinuousTriangleIntersection::checkValidRoots(SReal& validRoot,
00543 const int& numRoots,
00544 const Vector3& roots,
00545 const SReal& rootMin,
00546 const SReal& rootMax)
00547 {
00548 validRoot=-10;
00549
00551 if ((numRoots == 1) && checkRange (roots[0], rootMin, rootMax))
00552 {
00553 validRoot = roots[0];
00554 return true;
00555 }
00557 else if (numRoots == 2)
00558 {
00559 if (checkRange(roots[0], rootMin, rootMax) && checkRange(roots[1], rootMin, rootMax))
00560 {
00561 validRoot = getMinVal(roots[0], roots[1]);
00562 return true;
00563 }
00564 else if (checkRange (roots[0], rootMin, rootMax))
00565 {
00566 validRoot = roots[0];
00567 return true;
00568 }
00569 else if (checkRange (roots[1], rootMin, rootMax))
00570 {
00571 validRoot = roots[1];
00572 return true;
00573 }
00574 else
00575 return false;
00576 }
00578 else if (numRoots == 3)
00579 {
00580 if (checkRange (roots[0], rootMin, rootMax) &&
00581 checkRange (roots[1], rootMin, rootMax) &&
00582 checkRange (roots[2], rootMin, rootMax))
00583 {
00584 validRoot = getMinVal(roots[0], roots[1], roots[2]);
00585 return true;
00586 }
00587 else if (checkRange (roots[0], rootMin, rootMax) &&
00588 checkRange (roots[1], rootMin, rootMax))
00589 {
00590 validRoot = getMinVal(roots[0], roots[1]);
00591 return true;
00592 }
00593 else if (checkRange (roots[1], rootMin, rootMax) &&
00594 checkRange (roots[2], rootMin, rootMax))
00595 {
00596 validRoot = getMinVal(roots[1], roots[2]);
00597 return true;
00598 }
00599 else if (checkRange (roots[0], rootMin, rootMax) &&
00600 checkRange (roots[2], rootMin, rootMax))
00601 {
00602 validRoot = getMinVal(roots[0], roots[2]);
00603 return true;
00604 }
00605 else if (checkRange (roots[0], rootMin, rootMax))
00606 {
00607 validRoot = roots[0];
00608 return true;
00609 }
00610 else if (checkRange (roots[1], rootMin, rootMax))
00611 {
00612 validRoot = roots[1];
00613 return true;
00614 }
00615 else if (checkRange (roots[2], rootMin, rootMax))
00616 {
00617 validRoot = roots[2];
00618 return true;
00619 }
00620 else
00621 return false;
00622 }
00623 else
00624 return false;
00625 }
00626
00627 }
00628
00629 }
00630
00631 }
00632