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 <math.h>
00026
00027 #include <gfx/Triangle3>
00028 #include <gfx/Plane>
00029
00030 using gfx::Triangle3;
00031 using gfx::Point3;
00032 using gfx::Segment3;
00033 using gfx::Plane;
00034
00035
00036 Real Triangle3::distanceTo(const Point3& p) const
00037 {
00038 return Vector3(p-pointClosestTo(p)).length();
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 Point3 Triangle3::pointClosestTo(const Point3& p) const
00108 {
00109 Real s, t;
00110 Real ds=0;
00111
00112 Point3 tp = p2();
00113 Vector3 e0 = p1() - tp;
00114 Vector3 e1 = p3() - tp;
00115
00116 Vector3 diff = tp - p;
00117 Real a = dot(e0,e0);
00118 Real b = dot(e0,e1);
00119 Real c = dot(e1,e1);
00120 Real d = dot(e0,diff);
00121 Real e = dot(e1,diff);
00122 Real f = dot(diff,diff);
00123 Real det = Math::abs(a * c - Math::sqr(b));
00124 s = b * e - c * d;
00125 t = b * d - a * e;
00126
00127 if (s + t <= det) {
00128 if (s < 0) {
00129 if (t < 0) {
00130
00131
00132
00133
00134
00135 if (d < 0) {
00136
00137
00138
00139
00140 t = 0;
00141 if (-d > a) {
00142 s = 1;
00143 ds = a + 2 * d + f;
00144 }
00145 else {
00146 s = -d / a;
00147 ds = d * s + f;
00148 }
00149 }
00150 else {
00151
00152
00153
00154 s = 0;
00155 if (e >= 0) {
00156 t = 0;
00157 ds = f;
00158 }
00159 else if (-e > c) {
00160 t = 1;
00161 ds = c + 2 * e + f;
00162 }
00163 else {
00164 t = -e / c;
00165 ds = c * t + f;
00166 }
00167 }
00168 }
00169 else {
00170
00171
00172
00173
00174 s = 0;
00175 if (e >= 0) {
00176 t = 0;
00177 ds = f;
00178 }
00179 else if (-e > c) {
00180 t = 1;
00181 ds = c + 2 * e + f;
00182 }
00183 else {
00184 t = -e / c;
00185 ds = c * t + f;
00186 }
00187 }
00188 }
00189 else if (t < 0) {
00190
00191
00192
00193
00194 t = 0;
00195 if (d >= 0) {
00196 s = 0;
00197 ds = f;
00198 }
00199 if (-d > a) {
00200 s = 1;
00201 ds = a + 2 * d + f;
00202 }
00203 else {
00204 s = -d / a;
00205 ds = d * s + f;
00206 }
00207 }
00208 else {
00209
00210
00211
00212 det = 1 / det;
00213 s *= det;
00214 t *= det;
00215 ds = f + s * (a * s + 2 * (b * t + 2 * d)) + t * (c * t + 2 * e);
00216 }
00217 }
00218 else {
00219 if (s < 0) {
00220
00221
00222
00223
00224
00225 Real bd = b + d;
00226 Real ce = c + e;
00227 if (bd < ce) {
00228
00229
00230
00231 Real temp = ce - bd;
00232 Real temp2 = a - 2 * b + c;
00233 if (temp > temp2) {
00234 s = 1;
00235 t = 0;
00236 ds = a + 2 * d + f;
00237 }
00238 else {
00239 s = temp / temp2;
00240 t = 1 - s;
00241 ds = f + s * (a + 2 * (b * t + d)) + t * (c * t + 2 * e);
00242 }
00243 }
00244 else {
00245
00246
00247
00248 s = 0;
00249 if (e >= 0) {
00250 t = 0;
00251 ds = f;
00252 }
00253 else if (-e > c) {
00254 t = 1;
00255 ds = c + 2 * e + f;
00256 }
00257 else {
00258 t = -e / c;
00259 ds = c * t + f;
00260 }
00261 }
00262 }
00263 else if (t < 0) {
00264
00265
00266
00267
00268 Real ad = a + d;
00269 Real be = b + e;
00270 if (be < ad) {
00271
00272
00273
00274 Real temp = ad - be;
00275 Real temp2 = a - 2 * b + c;
00276 if (temp > temp2) {
00277 t = 1;
00278 s = 0;
00279 ds = c + 2 * e + f;
00280 }
00281 else {
00282 t = temp / temp2;
00283 s = 1 - t;
00284 ds = f + s * (a + 2 * (b * t + d)) + t * (c * t + 2 * e);
00285 }
00286 }
00287 else {
00288
00289
00290
00291 t = 0;
00292 if (d >= 0) {
00293 s = 0;
00294 ds = f;
00295 }
00296 if (-d > a) {
00297 s = 1;
00298 ds = a + 2 * d + f;
00299 }
00300 else {
00301 s = -d / a;
00302 ds = d * s + f;
00303 }
00304 }
00305 }
00306 else {
00307
00308
00309
00310
00311 Real temp = c + e - b - d;
00312 if (temp < 0) {
00313 s = 0;
00314 t = 1;
00315 ds = c + 2 * e + f;
00316 }
00317 else {
00318 Real temp2 = a - 2 * b + c;
00319 if (temp > temp2)
00320 {
00321 s = 1;
00322 t = 0;
00323 ds = a + 2 * d + f;
00324 }
00325 else {
00326 s = temp / temp2;
00327 t = 1 - s;
00328 ds = f + s * (a + 2 * (b * t + d)) + t * (c * t + 2 * e);
00329 }
00330 }
00331 }
00332 }
00333
00334
00335 ds = Math::abs(ds);
00336 return tp + s * e0 + t * e1;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 Segment3 Triangle3::shortestSegmentBetween(const Segment3& seg, Real& ds) const
00381 {
00382 Real s, t, r;
00383 ds=0;
00384
00385
00386 Point3 tp = _p2;
00387 Vector3 e0 = _p1 - _p2;
00388 Vector3 e1 = _p3 - _p2;
00389 Vector3 diff = _p2 - seg.s;
00390 Vector3 segdir = seg.e-seg.s;
00391 Point3 p1,p2;
00392 Real a00 = dot(e0,e0);
00393 Real a11 = dot(e1,e1);
00394 Real a22 = dot(segdir,segdir);
00395 Real a01 = dot(e0,e1);
00396 Real a02 = -dot(e0,segdir);
00397 Real a12 = -dot(e1,segdir);
00398 Real b0 = dot(e0,diff);
00399 Real b1 = dot(e1,diff);
00400 Real b2 = -dot(segdir,diff);
00401
00402
00403 Real cf00 = a11 * a22 - a12 * a12;
00404 Real cf01 = a02 * a12 - a22 * a01;
00405 Real cf02 = a01 * a12 - a02 * a11;
00406 Real det = a00 * cf00 + a01 * cf01 + a02 * cf02;
00407
00408 if (Math::abs(det) >= consts::epsilon)
00409 {
00410
00411 Real cf11 = a00 * a22 - a02 * a02;
00412 Real cf12 = a02 * a01 - a00 * a12;
00413 Real cf22 = a00 * a11 - a01 * a01;
00414
00415 det = 1 / det;
00416 s = (-b0 * cf00 - b1 * cf01 - b2 * cf02) * det;
00417 t = (-b0 * cf01 - b1 * cf11 - b2 * cf12) * det;
00418 r = (-b0 * cf02 - b1 * cf12 - b2 * cf22) * det;
00419
00420 if (s + t <= 1) {
00421 if (s < 0) {
00422 if (t < 0) {
00423
00424
00425 Segment3 segment1(_p2, _p1);
00426 Segment3 segment2(_p2, _p3);
00427 Segment3 sb1(segment1.shortestSegmentBetween(seg));
00428 Segment3 sb2(segment2.shortestSegmentBetween(seg));
00429 Real ds1 = sb1.norm();
00430 Real ds2 = sb2.norm();
00431 if (ds1 < ds2) {
00432 ds = ds1;
00433 p1 = sb1.s; p2 = sb1.e;
00434 }
00435 else {
00436 ds = ds2;
00437 p1 = sb2.s; p2 = sb2.e;
00438 }
00439 }
00440 else {
00441
00442
00443 Segment3 sb = seg.shortestSegmentBetween(Segment3(_p2, _p3), ds);
00444 p1 = sb.e; p2 = sb.s;
00445 }
00446 }
00447 else if (t < 0) {
00448
00449
00450 Segment3 sb = seg.shortestSegmentBetween(Segment3(_p2, _p1), ds);
00451 p1 = sb.e; p2 = sb.s;
00452 }
00453 else if (r >= 0 && r <= 1) {
00454
00455 Real c = dot(diff,diff);
00456 ds = s * (a00 * s + 2 * (a01 * t + a02 * r + b0)) +
00457 t * (a11 * t + 2 * (a12 * r + b1)) +
00458 r * (a22 * r + 2 * b2) + c;
00459
00460 p1 = seg.s + r * segdir;
00461 p2 = tp + s * e0 + t * e1;
00462 }
00463 }
00464 else {
00465 if (s < 0) {
00466
00467
00468 Segment3 segment1(_p2, _p3);
00469 Segment3 segment2(_p1, _p3);
00470 Segment3 sb1(segment1.shortestSegmentBetween(seg));
00471 Segment3 sb2(segment1.shortestSegmentBetween(seg));
00472 Real ds1 = sb1.norm();
00473 Real ds2 = sb2.norm();
00474 if (ds1 < ds2) {
00475 ds = ds1;
00476 p1 = sb1.s; p2 = sb1.e;
00477 }
00478 else {
00479 ds = ds2;
00480 p1 = sb2.s; p2 = sb2.e;
00481 }
00482 }
00483 else if (t < 0) {
00484
00485
00486 Segment3 segment1(_p2, _p1);
00487 Segment3 segment2(_p1, _p3);
00488 Segment3 sb1(segment1.shortestSegmentBetween(seg));
00489 Segment3 sb2(segment1.shortestSegmentBetween(seg));
00490 Real ds1 = sb1.norm();
00491 Real ds2 = sb2.norm();
00492 if (ds1 < ds2) {
00493 ds = ds1;
00494 p1 = sb1.s; p2 = sb1.e;
00495 }
00496 else {
00497 ds = ds2;
00498 p1 = sb2.s; p2 = sb2.e;
00499 }
00500 }
00501 else {
00502
00503
00504 Segment3 segment1(_p1, _p3);
00505 Segment3 sb = segment1.shortestSegmentBetween(seg, ds);
00506 p1 = sb.s; p2 = sb.e;
00507 }
00508 }
00509
00510
00511 if (r < 0 || r > 1) {
00512
00513
00514 Point3 p1temp, p2temp;
00515 Real distTemp;
00516 if (r < 0) {
00517 Segment3 sb(pointClosestTo(seg.s), seg.s);
00518 distTemp = sb.norm();
00519 p1temp = sb.s; p2temp = sb.e;
00520 }
00521 else {
00522 Segment3 sb(pointClosestTo(seg.e), seg.e);
00523 distTemp = sb.norm();
00524 p1temp = sb.s; p2temp = sb.e;
00525 }
00526 if (distTemp < ds || (s >= 0 && t >= 0)) {
00527 ds = distTemp;
00528 p1 = p1temp;
00529 p2 = p2temp;
00530 }
00531 }
00532 }
00533 else {
00534
00535
00536 Segment3 segment1(_p2, _p1);
00537 Segment3 segment2(_p2, _p3);
00538 Segment3 segment3(_p1, _p3);
00539 Segment3 sb1(segment1.shortestSegmentBetween(seg));
00540 Segment3 sb2(segment2.shortestSegmentBetween(seg));
00541 Segment3 sb3(segment3.shortestSegmentBetween(seg));
00542 Real ds1 = sb1.norm();
00543 Real ds2 = sb2.norm();
00544 Real ds3 = sb3.norm();
00545 if (ds1 < ds2) {
00546 if (ds1 < ds3) {
00547 ds = ds1;
00548 p1 = sb1.s; p2 = sb1.e;
00549 }
00550 else {
00551 ds = ds3;
00552 p1 = sb3.s; p2 = sb3.e;
00553 }
00554 }
00555 else {
00556 if (ds2 < ds3) {
00557 ds = ds2;
00558 p1 = sb2.s; p2 = sb2.e;
00559 }
00560 else {
00561 ds = ds3;
00562 p1 = sb3.s; p2 = sb3.e;
00563 }
00564 }
00565
00566 Point3 p1temp, p2temp;
00567 Segment3 sbp(pointClosestTo(seg.s), seg.s);
00568 Real distTemp = sbp.norm();
00569 p1temp = sbp.s; p2temp = sbp.e;
00570 if (distTemp < ds) {
00571 ds = distTemp;
00572 p1 = p1temp;
00573 p2 = p2temp;
00574 }
00575 Segment3 sbp2(pointClosestTo(seg.e), seg.e);
00576 distTemp = sbp2.norm();
00577 p1temp = sbp2.s; p2temp = sbp2.e;
00578 if (distTemp < ds) {
00579 ds = distTemp;
00580 p1 = p1temp;
00581 p2 = p2temp;
00582 }
00583 }
00584
00585
00586 ds = Math::abs(ds);
00587
00588
00589
00590
00591 return Segment3(p1,p2);
00592 }
00593
00594
00595
00596 Segment3 Triangle3::shortestSegmentBetween(const Triangle3& t) const
00597 {
00598
00599
00600 Segment3 t11(p1(), p2());
00601 Segment3 t12(p2(), p3());
00602 Segment3 t13(p3(), p1());
00603
00604 Segment3 t21(t.p1(), t.p2());
00605 Segment3 t22(t.p2(), t.p3());
00606 Segment3 t23(t.p3(), t.p1());
00607
00608 Segment3 seg = shortestSegmentBetween(t21);
00609 Segment3 shortest = seg;
00610
00611 seg = shortestSegmentBetween(t22);
00612 if (seg.norm() < shortest.norm()) shortest = seg;
00613
00614 seg = shortestSegmentBetween(t23);
00615 if (seg.norm() < shortest.norm()) shortest = seg;
00616
00617 seg = t.shortestSegmentBetween(t11);
00618 if (seg.norm() < shortest.norm()) shortest = seg;
00619
00620 seg = t.shortestSegmentBetween(t12);
00621 if (seg.norm() < shortest.norm()) shortest = seg;
00622
00623 seg = t.shortestSegmentBetween(t13);
00624 if (seg.norm() < shortest.norm()) shortest = seg;
00625
00626 return shortest;
00627 }
00628
00629
00630 Real Triangle3::distanceTo(const Triangle3& t) const
00631 {
00632 return shortestSegmentBetween(t).length();
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 namespace gfx {
00644
00645 class TriangleDesc : public Triangle3
00646 {
00647 public:
00648 TriangleDesc(const Triangle3& t, const Plane& p)
00649 : Triangle3(t)
00650 {
00651 const Vector3& n=p.normal;
00652 Vector3 a(base::abs(n.x),base::abs(n.y),base::abs(n.z));
00653 if (a.x>a.y) {
00654 if (a.x>a.z) { i1=2; i2=3; }
00655 else { i1=1; i2=2; }
00656 }
00657 else {
00658 if (a.y>a.z) { i1=1; i2=3; }
00659 else { i1=1; i2=2; }
00660 }
00661 }
00662
00663 bool pointInTri(const Vector3& P) const
00664 {
00665 const Point3& v1( (*this)[1] );
00666 const Point3& v2( (*this)[2] );
00667 const Point3& v3( (*this)[3] );
00668 Vector3 u(P[i1]-v1[i1],
00669 v2[i1]-v1[i1],
00670 v3[i1]-v1[i1]);
00671 Vector3 v(P[i2]-v1[i2],
00672 v2[i2]-v1[i2],
00673 v3[i2]-v1[i2]);
00674 Real a,b;
00675 if (u.y==0.0) {
00676 b=u.x/u.z;
00677 if (b>=0.0 && b<=1.0) a=(v.x-b*v.z)/v.y;
00678 else return false;
00679 }
00680 else {
00681 b=(v.x*u.y-u.x*v.y)/(v.z*u.y-u.z*v.y);
00682 if (b>=0.0 && b<=1.0) a=(u.x-b*u.z)/u.y;
00683 else return false;
00684 }
00685 return (a>=0 && (a+b)<=1);
00686 }
00687
00688
00689 const Point3& operator[] (Int i) const throw()
00690 {
00691 SInt zi = i-1;
00692 if (zi<0) zi += 3;
00693 zi = zi%3;
00694
00695 switch (zi) {
00696 case 0: return at(1);
00697 case 1: return at(2);
00698 case 2: return at(3);
00699 default: return at(1);
00700 }
00701 }
00702
00703 Int i1,i2;
00704 };
00705
00706 }
00707
00708 using gfx::TriangleDesc;
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 #define FABS(x) (base::abs(x))
00746
00747
00748
00749
00750
00751 #define USE_EPSILON_TEST TRUE
00752 #define EPSILON 0.000001
00753
00754
00755
00756 #define CROSS(dest,v1,v2) \
00757 dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
00758 dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
00759 dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
00760
00761 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
00762
00763 #define SUB(dest,v1,v2) dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2];
00764
00765 #define ADD(dest,v1,v2) dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2];
00766
00767 #define MULT(dest,v,factor) dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2];
00768
00769 #define SET(dest,src) dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2];
00770
00771
00772 #define SORT(a,b) \
00773 if(a>b) \
00774 { \
00775 Real c; \
00776 c=a; \
00777 a=b; \
00778 b=c; \
00779 }
00780
00781 #define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1) \
00782 isect0=VV0+(VV1-VV0)*D0/(D0-D1); \
00783 isect1=VV0+(VV2-VV0)*D0/(D0-D2);
00784
00785
00786 #define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1) \
00787 if(D0D1>0.0f) \
00788 { \
00789 \
00790 \
00791 ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \
00792 } \
00793 else if(D0D2>0.0f) \
00794 { \
00795 \
00796 ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \
00797 } \
00798 else if(D1*D2>0.0f || D0!=0.0f) \
00799 { \
00800 \
00801 ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1); \
00802 } \
00803 else if(D1!=0.0f) \
00804 { \
00805 ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \
00806 } \
00807 else if(D2!=0.0f) \
00808 { \
00809 ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \
00810 } \
00811 else \
00812 { \
00813 \
00814 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
00815 }
00816
00817
00818
00819
00820
00821
00822 #define EDGE_EDGE_TEST(V0,U0,U1) \
00823 Bx=U0[i0]-U1[i0]; \
00824 By=U0[i1]-U1[i1]; \
00825 Cx=V0[i0]-U0[i0]; \
00826 Cy=V0[i1]-U0[i1]; \
00827 f=Ay*Bx-Ax*By; \
00828 d=By*Cx-Bx*Cy; \
00829 if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \
00830 { \
00831 e=Ax*Cy-Ay*Cx; \
00832 if(f>0) \
00833 { \
00834 if(e>=0 && e<=f) return 1; \
00835 } \
00836 else \
00837 { \
00838 if(e<=0 && e>=f) return 1; \
00839 } \
00840 }
00841
00842 #define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
00843 { \
00844 Real Ax,Ay,Bx,By,Cx,Cy,e,d,f; \
00845 Ax=V1[i0]-V0[i0]; \
00846 Ay=V1[i1]-V0[i1]; \
00847 \
00848 EDGE_EDGE_TEST(V0,U0,U1); \
00849 \
00850 EDGE_EDGE_TEST(V0,U1,U2); \
00851 \
00852 EDGE_EDGE_TEST(V0,U2,U0); \
00853 }
00854
00855 #define POINT_IN_TRI(V0,U0,U1,U2) \
00856 { \
00857 Real a,b,c,d0,d1,d2; \
00858 \
00859 \
00860 a=U1[i1]-U0[i1]; \
00861 b=-(U1[i0]-U0[i0]); \
00862 c=-a*U0[i0]-b*U0[i1]; \
00863 d0=a*V0[i0]+b*V0[i1]+c; \
00864 \
00865 a=U2[i1]-U1[i1]; \
00866 b=-(U2[i0]-U1[i0]); \
00867 c=-a*U1[i0]-b*U1[i1]; \
00868 d1=a*V0[i0]+b*V0[i1]+c; \
00869 \
00870 a=U0[i1]-U2[i1]; \
00871 b=-(U0[i0]-U2[i0]); \
00872 c=-a*U2[i0]-b*U2[i1]; \
00873 d2=a*V0[i0]+b*V0[i1]+c; \
00874 if(d0*d1>0.0) \
00875 { \
00876 if(d0*d2>0.0) return 1; \
00877 } \
00878 }
00879
00880 int coplanar_tri_tri(Real N[3],Real V0[3],Real V1[3],Real V2[3],
00881 Real U0[3],Real U1[3],Real U2[3])
00882 {
00883 Real A[3];
00884 short i0,i1;
00885
00886
00887 A[0]=fabs(N[0]);
00888 A[1]=fabs(N[1]);
00889 A[2]=fabs(N[2]);
00890 if(A[0]>A[1])
00891 {
00892 if(A[0]>A[2])
00893 {
00894 i0=1;
00895 i1=2;
00896 }
00897 else
00898 {
00899 i0=0;
00900 i1=1;
00901 }
00902 }
00903 else
00904 {
00905 if(A[2]>A[1])
00906 {
00907 i0=0;
00908 i1=1;
00909 }
00910 else
00911 {
00912 i0=0;
00913 i1=2;
00914 }
00915 }
00916
00917
00918 EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
00919 EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
00920 EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
00921
00922
00923 POINT_IN_TRI(V0,U0,U1,U2);
00924 POINT_IN_TRI(U0,V0,V1,V2);
00925
00926 return 0;
00927 }
00928
00929
00930 int tri_tri_intersect(Real V0[3],Real V1[3],Real V2[3],
00931 Real U0[3],Real U1[3],Real U2[3])
00932 {
00933 Real E1[3],E2[3];
00934 Real N1[3],N2[3],d1,d2;
00935 Real du0,du1,du2,dv0,dv1,dv2;
00936 Real D[3];
00937 Real isect1[2], isect2[2];
00938 Real du0du1,du0du2,dv0dv1,dv0dv2;
00939 short index;
00940 Real vp0,vp1,vp2;
00941 Real up0,up1,up2;
00942 Real b,c,max;
00943
00944
00945 SUB(E1,V1,V0);
00946 SUB(E2,V2,V0);
00947 CROSS(N1,E1,E2);
00948 d1=-DOT(N1,V0);
00949
00950
00951
00952 du0=DOT(N1,U0)+d1;
00953 du1=DOT(N1,U1)+d1;
00954 du2=DOT(N1,U2)+d1;
00955
00956
00957 #if USE_EPSILON_TEST==TRUE
00958 if(fabs(du0)<EPSILON) du0=0.0;
00959 if(fabs(du1)<EPSILON) du1=0.0;
00960 if(fabs(du2)<EPSILON) du2=0.0;
00961 #endif
00962 du0du1=du0*du1;
00963 du0du2=du0*du2;
00964
00965 if(du0du1>0.0f && du0du2>0.0f)
00966 return 0;
00967
00968
00969 SUB(E1,U1,U0);
00970 SUB(E2,U2,U0);
00971 CROSS(N2,E1,E2);
00972 d2=-DOT(N2,U0);
00973
00974
00975
00976 dv0=DOT(N2,V0)+d2;
00977 dv1=DOT(N2,V1)+d2;
00978 dv2=DOT(N2,V2)+d2;
00979
00980 #if USE_EPSILON_TEST==TRUE
00981 if(fabs(dv0)<EPSILON) dv0=0.0;
00982 if(fabs(dv1)<EPSILON) dv1=0.0;
00983 if(fabs(dv2)<EPSILON) dv2=0.0;
00984 #endif
00985
00986 dv0dv1=dv0*dv1;
00987 dv0dv2=dv0*dv2;
00988
00989 if(dv0dv1>0.0f && dv0dv2>0.0f)
00990 return 0;
00991
00992
00993 CROSS(D,N1,N2);
00994
00995
00996 max=fabs(D[0]);
00997 index=0;
00998 b=fabs(D[1]);
00999 c=fabs(D[2]);
01000 if(b>max) max=b,index=1;
01001 if(c>max) max=c,index=2;
01002
01003
01004 vp0=V0[index];
01005 vp1=V1[index];
01006 vp2=V2[index];
01007
01008 up0=U0[index];
01009 up1=U1[index];
01010 up2=U2[index];
01011
01012
01013 COMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,isect1[0],isect1[1]);
01014
01015
01016 COMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,isect2[0],isect2[1]);
01017
01018 SORT(isect1[0],isect1[1]);
01019 SORT(isect2[0],isect2[1]);
01020
01021 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
01022 return 1;
01023 }
01024
01025
01026 #define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
01027 { \
01028 if(D0D1>0.0f) \
01029 { \
01030 \
01031 \
01032 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
01033 } \
01034 else if(D0D2>0.0f)\
01035 { \
01036 \
01037 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
01038 } \
01039 else if(D1*D2>0.0f || D0!=0.0f) \
01040 { \
01041 \
01042 A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
01043 } \
01044 else if(D1!=0.0f) \
01045 { \
01046 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
01047 } \
01048 else if(D2!=0.0f) \
01049 { \
01050 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
01051 } \
01052 else \
01053 { \
01054 \
01055 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
01056 } \
01057 }
01058
01059
01060
01061 int NoDivTriTriIsect(Real V0[3],Real V1[3],Real V2[3],
01062 Real U0[3],Real U1[3],Real U2[3])
01063 {
01064 Real E1[3],E2[3];
01065 Real N1[3],N2[3],d1,d2;
01066 Real du0,du1,du2,dv0,dv1,dv2;
01067 Real D[3];
01068 Real isect1[2], isect2[2];
01069 Real du0du1,du0du2,dv0dv1,dv0dv2;
01070 short index;
01071 Real vp0,vp1,vp2;
01072 Real up0,up1,up2;
01073 Real bb,cc,max;
01074 Real a,b,c,x0,x1;
01075 Real d,e,f,y0,y1;
01076 Real xx,yy,xxyy,tmp;
01077
01078
01079 SUB(E1,V1,V0);
01080 SUB(E2,V2,V0);
01081 CROSS(N1,E1,E2);
01082 d1=-DOT(N1,V0);
01083
01084
01085
01086 du0=DOT(N1,U0)+d1;
01087 du1=DOT(N1,U1)+d1;
01088 du2=DOT(N1,U2)+d1;
01089
01090
01091 #if USE_EPSILON_TEST==TRUE
01092 if(FABS(du0)<EPSILON) du0=0.0;
01093 if(FABS(du1)<EPSILON) du1=0.0;
01094 if(FABS(du2)<EPSILON) du2=0.0;
01095 #endif
01096 du0du1=du0*du1;
01097 du0du2=du0*du2;
01098
01099 if(du0du1>0.0f && du0du2>0.0f)
01100 return 0;
01101
01102
01103 SUB(E1,U1,U0);
01104 SUB(E2,U2,U0);
01105 CROSS(N2,E1,E2);
01106 d2=-DOT(N2,U0);
01107
01108
01109
01110 dv0=DOT(N2,V0)+d2;
01111 dv1=DOT(N2,V1)+d2;
01112 dv2=DOT(N2,V2)+d2;
01113
01114 #if USE_EPSILON_TEST==TRUE
01115 if(FABS(dv0)<EPSILON) dv0=0.0;
01116 if(FABS(dv1)<EPSILON) dv1=0.0;
01117 if(FABS(dv2)<EPSILON) dv2=0.0;
01118 #endif
01119
01120 dv0dv1=dv0*dv1;
01121 dv0dv2=dv0*dv2;
01122
01123 if(dv0dv1>0.0f && dv0dv2>0.0f)
01124 return 0;
01125
01126
01127 CROSS(D,N1,N2);
01128
01129
01130 max=(Real)FABS(D[0]);
01131 index=0;
01132 bb=(Real)FABS(D[1]);
01133 cc=(Real)FABS(D[2]);
01134 if(bb>max) max=bb,index=1;
01135 if(cc>max) max=cc,index=2;
01136
01137
01138 vp0=V0[index];
01139 vp1=V1[index];
01140 vp2=V2[index];
01141
01142 up0=U0[index];
01143 up1=U1[index];
01144 up2=U2[index];
01145
01146
01147 NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
01148
01149
01150 NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
01151
01152 xx=x0*x1;
01153 yy=y0*y1;
01154 xxyy=xx*yy;
01155
01156 tmp=a*xxyy;
01157 isect1[0]=tmp+b*x1*yy;
01158 isect1[1]=tmp+c*x0*yy;
01159
01160 tmp=d*xxyy;
01161 isect2[0]=tmp+e*xx*y1;
01162 isect2[1]=tmp+f*xx*y0;
01163
01164 SORT(isect1[0],isect1[1]);
01165 SORT(isect2[0],isect2[1]);
01166
01167 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
01168 return 1;
01169 }
01170
01171
01172 #define SORT2(a,b,smallest) \
01173 if(a>b) \
01174 { \
01175 Real c; \
01176 c=a; \
01177 a=b; \
01178 b=c; \
01179 smallest=1; \
01180 } \
01181 else smallest=0;
01182
01183
01184 inline void isect2(Real VTX0[3],Real VTX1[3],Real VTX2[3],Real VV0,Real VV1,Real VV2,
01185 Real D0,Real D1,Real D2,Real *isect0,Real *isect1,Real isectpoint0[3],Real isectpoint1[3])
01186 {
01187 Real tmp=D0/(D0-D1);
01188 Real diff[3];
01189 *isect0=VV0+(VV1-VV0)*tmp;
01190 SUB(diff,VTX1,VTX0);
01191 MULT(diff,diff,tmp);
01192 ADD(isectpoint0,diff,VTX0);
01193 tmp=D0/(D0-D2);
01194 *isect1=VV0+(VV2-VV0)*tmp;
01195 SUB(diff,VTX2,VTX0);
01196 MULT(diff,diff,tmp);
01197 ADD(isectpoint1,VTX0,diff);
01198 }
01199
01200
01201
01202 inline int compute_intervals_isectline(Real VERT0[3],Real VERT1[3],Real VERT2[3],
01203 Real VV0,Real VV1,Real VV2,Real D0,Real D1,Real D2,
01204 Real D0D1,Real D0D2,Real *isect0,Real *isect1,
01205 Real isectpoint0[3],Real isectpoint1[3])
01206 {
01207 if(D0D1>0.0f)
01208 {
01209
01210
01211 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
01212 }
01213 else if(D0D2>0.0f)
01214 {
01215
01216 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
01217 }
01218 else if(D1*D2>0.0f || D0!=0.0f)
01219 {
01220
01221 isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1);
01222 }
01223 else if(D1!=0.0f)
01224 {
01225 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
01226 }
01227 else if(D2!=0.0f)
01228 {
01229 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
01230 }
01231 else
01232 {
01233
01234 return 1;
01235 }
01236 return 0;
01237 }
01238
01239 #define COMPUTE_INTERVALS_ISECTLINE(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1,isectpoint0,isectpoint1) \
01240 if(D0D1>0.0f) \
01241 { \
01242 \
01243 \
01244 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \
01245 }
01246 #if 0
01247 else if(D0D2>0.0f) \
01248 { \
01249 \
01250 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \
01251 } \
01252 else if(D1*D2>0.0f || D0!=0.0f) \
01253 { \
01254 \
01255 isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,&isect0,&isect1,isectpoint0,isectpoint1); \
01256 } \
01257 else if(D1!=0.0f) \
01258 { \
01259 isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \
01260 } \
01261 else if(D2!=0.0f) \
01262 { \
01263 isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \
01264 } \
01265 else \
01266 { \
01267 \
01268 coplanar=1; \
01269 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
01270 }
01271 #endif
01272
01273 int tri_tri_intersect_with_isectline(Real V0[3],Real V1[3],Real V2[3],
01274 Real U0[3],Real U1[3],Real U2[3],int *coplanar,
01275 Real isectpt1[3],Real isectpt2[3])
01276 {
01277 Real E1[3],E2[3];
01278 Real N1[3],N2[3],d1,d2;
01279 Real du0,du1,du2,dv0,dv1,dv2;
01280 Real D[3];
01281 Real isect1[2], isect2[2];
01282 Real isectpointA1[3],isectpointA2[3];
01283 Real isectpointB1[3],isectpointB2[3];
01284 Real du0du1,du0du2,dv0dv1,dv0dv2;
01285 short index;
01286 Real vp0,vp1,vp2;
01287 Real up0,up1,up2;
01288 Real b,c,max;
01289
01290 int smallest1,smallest2;
01291
01292
01293 SUB(E1,V1,V0);
01294 SUB(E2,V2,V0);
01295 CROSS(N1,E1,E2);
01296 d1=-DOT(N1,V0);
01297
01298
01299
01300 du0=DOT(N1,U0)+d1;
01301 du1=DOT(N1,U1)+d1;
01302 du2=DOT(N1,U2)+d1;
01303
01304
01305 #if USE_EPSILON_TEST==TRUE
01306 if(fabs(du0)<EPSILON) du0=0.0;
01307 if(fabs(du1)<EPSILON) du1=0.0;
01308 if(fabs(du2)<EPSILON) du2=0.0;
01309 #endif
01310 du0du1=du0*du1;
01311 du0du2=du0*du2;
01312
01313 if(du0du1>0.0f && du0du2>0.0f)
01314 return 0;
01315
01316
01317 SUB(E1,U1,U0);
01318 SUB(E2,U2,U0);
01319 CROSS(N2,E1,E2);
01320 d2=-DOT(N2,U0);
01321
01322
01323
01324 dv0=DOT(N2,V0)+d2;
01325 dv1=DOT(N2,V1)+d2;
01326 dv2=DOT(N2,V2)+d2;
01327
01328 #if USE_EPSILON_TEST==TRUE
01329 if(fabs(dv0)<EPSILON) dv0=0.0;
01330 if(fabs(dv1)<EPSILON) dv1=0.0;
01331 if(fabs(dv2)<EPSILON) dv2=0.0;
01332 #endif
01333
01334 dv0dv1=dv0*dv1;
01335 dv0dv2=dv0*dv2;
01336
01337 if(dv0dv1>0.0f && dv0dv2>0.0f)
01338 return 0;
01339
01340
01341 CROSS(D,N1,N2);
01342
01343
01344 max=fabs(D[0]);
01345 index=0;
01346 b=fabs(D[1]);
01347 c=fabs(D[2]);
01348 if(b>max) max=b,index=1;
01349 if(c>max) max=c,index=2;
01350
01351
01352 vp0=V0[index];
01353 vp1=V1[index];
01354 vp2=V2[index];
01355
01356 up0=U0[index];
01357 up1=U1[index];
01358 up2=U2[index];
01359
01360
01361 *coplanar=compute_intervals_isectline(V0,V1,V2,vp0,vp1,vp2,dv0,dv1,dv2,
01362 dv0dv1,dv0dv2,&isect1[0],&isect1[1],isectpointA1,isectpointA2);
01363 if(*coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);
01364
01365
01366
01367 compute_intervals_isectline(U0,U1,U2,up0,up1,up2,du0,du1,du2,
01368 du0du1,du0du2,&isect2[0],&isect2[1],isectpointB1,isectpointB2);
01369
01370 SORT2(isect1[0],isect1[1],smallest1);
01371 SORT2(isect2[0],isect2[1],smallest2);
01372
01373 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
01374
01375
01376
01377 if(isect2[0]<isect1[0])
01378 {
01379 if(smallest1==0) { SET(isectpt1,isectpointA1); }
01380 else { SET(isectpt1,isectpointA2); }
01381
01382 if(isect2[1]<isect1[1])
01383 {
01384 if(smallest2==0) { SET(isectpt2,isectpointB2); }
01385 else { SET(isectpt2,isectpointB1); }
01386 }
01387 else
01388 {
01389 if(smallest1==0) { SET(isectpt2,isectpointA2); }
01390 else { SET(isectpt2,isectpointA1); }
01391 }
01392 }
01393 else
01394 {
01395 if(smallest2==0) { SET(isectpt1,isectpointB1); }
01396 else { SET(isectpt1,isectpointB2); }
01397
01398 if(isect2[1]>isect1[1])
01399 {
01400 if(smallest1==0) { SET(isectpt2,isectpointA2); }
01401 else { SET(isectpt2,isectpointA1); }
01402 }
01403 else
01404 {
01405 if(smallest2==0) { SET(isectpt2,isectpointB2); }
01406 else { SET(isectpt2,isectpointB1); }
01407 }
01408 }
01409 return 1;
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 bool Triangle3::intersect(const Triangle3& t) const
01421 {
01422 const Triangle3& t2(*this);
01423
01424
01425 Real* t1p1 = const_cast<Real*>(t.p1().c_array());
01426 Real* t1p2 = const_cast<Real*>(t.p2().c_array());
01427 Real* t1p3 = const_cast<Real*>(t.p3().c_array());
01428 Real* t2p1 = const_cast<Real*>(t2.p1().c_array());
01429 Real* t2p2 = const_cast<Real*>(t2.p2().c_array());
01430 Real* t2p3 = const_cast<Real*>(t2.p3().c_array());
01431
01432 return (bool)NoDivTriTriIsect(t1p1,t1p2,t1p3,
01433 t2p1,t2p2,t2p3);
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 }
01484
01485
01486 bool Triangle3::contact(const Triangle3& t, Contact& contact) const
01487 {
01488 const Triangle3& t2(*this);
01489
01490
01491 Real* t1p1 = const_cast<Real*>(t.p1().c_array());
01492 Real* t1p2 = const_cast<Real*>(t.p2().c_array());
01493 Real* t1p3 = const_cast<Real*>(t.p3().c_array());
01494 Real* t2p1 = const_cast<Real*>(t2.p1().c_array());
01495 Real* t2p2 = const_cast<Real*>(t2.p2().c_array());
01496 Real* t2p3 = const_cast<Real*>(t2.p3().c_array());
01497
01498 int coplanar = 0;
01499 Point3 i1, i2;
01500 int intersected = tri_tri_intersect_with_isectline(t1p1,t1p2,t1p3,
01501 t2p1,t2p2,t2p3,
01502 &coplanar,
01503 i1.c_array(), i2.c_array());
01504 if (!intersected) {
01505 contact.type = Contact::None;
01506 return false;
01507 }
01508
01509 if (!coplanar) {
01510 if (i1.equals(i2)) {
01511 contact.type = Contact::Point;
01512 contact.point = i1;
01513 contact.depth = 0;
01514 }
01515 else {
01516 contact.type = Contact::Segment;
01517 contact.segment = Segment3(i1,i2);
01518
01519 contact.depth = 0;
01520 }
01521 }
01522 else {
01523
01524
01525
01526
01527
01528
01529
01530 }
01531
01532 return true;
01533 }