00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef SGIntersect_HXX
00019 #define SGIntersect_HXX
00020
00021 template<typename T>
00022 inline bool
00023 intersects(const SGSphere<T>& s1, const SGSphere<T>& s2)
00024 {
00025 if (s1.empty())
00026 return false;
00027 if (s2.empty())
00028 return false;
00029
00030 T dist = s1.getRadius() + s2.getRadius();
00031 return distSqr(s1.getCenter(), s2.getCenter()) <= dist*dist;
00032 }
00033
00034
00035 template<typename T1, typename T2>
00036 inline bool
00037 intersects(const SGBox<T1>& box, const SGSphere<T2>& sphere)
00038 {
00039 if (sphere.empty())
00040 return false;
00041
00042
00043
00044
00045 if (sphere.getCenter().x() < box.getMin().x() - sphere.getRadius())
00046 return false;
00047 if (sphere.getCenter().y() < box.getMin().y() - sphere.getRadius())
00048 return false;
00049 if (sphere.getCenter().z() < box.getMin().z() - sphere.getRadius())
00050 return false;
00051
00052 if (box.getMax().x() + sphere.getRadius() < sphere.getCenter().x())
00053 return false;
00054 if (box.getMax().y() + sphere.getRadius() < sphere.getCenter().y())
00055 return false;
00056 if (box.getMax().z() + sphere.getRadius() < sphere.getCenter().z())
00057 return false;
00058
00059 return true;
00060 }
00061
00062 template<typename T1, typename T2>
00063 inline bool
00064 intersects(const SGSphere<T1>& sphere, const SGBox<T2>& box)
00065 { return intersects(box, sphere); }
00066
00067
00068 template<typename T1, typename T2>
00069 inline bool
00070 intersects(const SGVec3<T1>& v, const SGBox<T2>& box)
00071 {
00072 if (v[0] < box.getMin()[0])
00073 return false;
00074 if (box.getMax()[0] < v[0])
00075 return false;
00076 if (v[1] < box.getMin()[1])
00077 return false;
00078 if (box.getMax()[1] < v[1])
00079 return false;
00080 if (v[2] < box.getMin()[2])
00081 return false;
00082 if (box.getMax()[2] < v[2])
00083 return false;
00084 return true;
00085 }
00086 template<typename T1, typename T2>
00087 inline bool
00088 intersects(const SGBox<T1>& box, const SGVec3<T2>& v)
00089 { return intersects(v, box); }
00090
00091
00092 template<typename T>
00093 inline bool
00094 intersects(const SGRay<T>& ray, const SGPlane<T>& plane)
00095 {
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 T num = plane.getPositiveDist();
00112 num -= dot(plane.getNormal(), ray.getOrigin());
00113
00114
00115 if (fabs(num) <= SGLimits<T>::min())
00116 return true;
00117
00118
00119 T den = dot(plane.getNormal(), ray.getDirection());
00120
00121
00122
00123
00124 if (fabs(den) <= SGLimits<T>::min())
00125 return false;
00126
00127
00128
00129
00130 T alphaDen = copysign(1, den)*num;
00131 if (alphaDen < 0)
00132 return false;
00133
00134 return true;
00135 }
00136
00137 template<typename T>
00138 inline bool
00139 intersects(const SGPlane<T>& plane, const SGRay<T>& ray)
00140 { return intersects(ray, plane); }
00141
00142 template<typename T>
00143 inline bool
00144 intersects(SGVec3<T>& dst, const SGRay<T>& ray, const SGPlane<T>& plane)
00145 {
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 T num = plane.getPositiveDist();
00162 num -= dot(plane.getNormal(), ray.getOrigin());
00163
00164
00165 if (fabs(num) <= SGLimits<T>::min()) {
00166 dst = ray.getOrigin();
00167 return true;
00168 }
00169
00170
00171 T den = dot(plane.getNormal(), ray.getDirection());
00172
00173
00174
00175
00176 if (fabs(den) <= SGLimits<T>::min())
00177 return false;
00178
00179
00180
00181
00182 T alpha = num/den;
00183 if (alpha < 0)
00184 return false;
00185
00186 dst = ray.getOrigin() + alpha*ray.getDirection();
00187 return true;
00188 }
00189
00190 template<typename T>
00191 inline bool
00192 intersects(SGVec3<T>& dst, const SGPlane<T>& plane, const SGRay<T>& ray)
00193 { return intersects(dst, ray, plane); }
00194
00195 template<typename T>
00196 inline bool
00197 intersects(const SGLineSegment<T>& lineSegment, const SGPlane<T>& plane)
00198 {
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 T num = plane.getPositiveDist();
00215 num -= dot(plane.getNormal(), lineSegment.getOrigin());
00216
00217
00218 if (fabs(num) <= SGLimits<T>::min())
00219 return true;
00220
00221
00222 T den = dot(plane.getNormal(), lineSegment.getDirection());
00223
00224
00225
00226
00227 if (fabs(den) <= SGLimits<T>::min())
00228 return false;
00229
00230
00231
00232
00233
00234 T alphaDen = copysign(1, den)*num;
00235 if (alphaDen < 0)
00236 return false;
00237 if (den < alphaDen)
00238 return false;
00239
00240 return true;
00241 }
00242
00243 template<typename T>
00244 inline bool
00245 intersects(const SGPlane<T>& plane, const SGLineSegment<T>& lineSegment)
00246 { return intersects(lineSegment, plane); }
00247
00248 template<typename T>
00249 inline bool
00250 intersects(SGVec3<T>& dst, const SGLineSegment<T>& lineSegment, const SGPlane<T>& plane)
00251 {
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 T num = plane.getPositiveDist();
00268 num -= dot(plane.getNormal(), lineSegment.getOrigin());
00269
00270
00271 if (fabs(num) <= SGLimits<T>::min()) {
00272 dst = lineSegment.getOrigin();
00273 return true;
00274 }
00275
00276
00277 T den = dot(plane.getNormal(), lineSegment.getDirection());
00278
00279
00280
00281
00282 if (fabs(den) <= SGLimits<T>::min())
00283 return false;
00284
00285
00286
00287
00288 T alpha = num/den;
00289 if (alpha < 0)
00290 return false;
00291 if (1 < alpha)
00292 return false;
00293
00294 dst = lineSegment.getOrigin() + alpha*lineSegment.getDirection();
00295 return true;
00296 }
00297
00298 template<typename T>
00299 inline bool
00300 intersects(SGVec3<T>& dst, const SGPlane<T>& plane, const SGLineSegment<T>& lineSegment)
00301 { return intersects(dst, lineSegment, plane); }
00302
00303
00304
00305 template<typename T>
00306 inline T
00307 distSqr(const SGLineSegment<T>& lineSeg, const SGVec3<T>& p)
00308 {
00309 SGVec3<T> ps = p - lineSeg.getStart();
00310
00311 T psdotdir = dot(ps, lineSeg.getDirection());
00312 if (psdotdir <= 0)
00313 return dot(ps, ps);
00314
00315 SGVec3<T> pe = p - lineSeg.getEnd();
00316 if (0 <= dot(pe, lineSeg.getDirection()))
00317 return dot(pe, pe);
00318
00319 return dot(ps, ps) - psdotdir*psdotdir/dot(lineSeg.getDirection(), lineSeg.getDirection());
00320 }
00321
00322 template<typename T>
00323 inline T
00324 distSqr(const SGVec3<T>& p, const SGLineSegment<T>& lineSeg)
00325 { return distSqr(lineSeg, p); }
00326
00327 template<typename T>
00328 inline T
00329 dist(const SGVec3<T>& p, const SGLineSegment<T>& lineSeg)
00330 { return sqrt(distSqr(lineSeg, p)); }
00331 template<typename T>
00332 inline T
00333 dist(const SGLineSegment<T>& lineSeg, const SGVec3<T>& p)
00334 { return sqrt(distSqr(lineSeg, p)); }
00335
00336 template<typename T>
00337 inline bool
00338 intersects(const SGRay<T>& ray, const SGSphere<T>& sphere)
00339 {
00340
00341
00342 SGVec3<T> l = sphere.getCenter() - ray.getOrigin();
00343 T s = dot(l, ray.getDirection());
00344 T l2 = dot(l, l);
00345
00346 T r2 = sphere.getRadius2();
00347 if (s < 0 && l2 > r2)
00348 return false;
00349
00350 T d2 = dot(ray.getDirection(), ray.getDirection());
00351
00352
00353
00354
00355
00356 T m2 = d2*l2 - s*s;
00357 if (m2 > d2*r2)
00358 return false;
00359
00360 return true;
00361 }
00362
00363 template<typename T>
00364 inline bool
00365 intersects(const SGSphere<T>& sphere, const SGRay<T>& ray)
00366 { return intersects(ray, sphere); }
00367
00368 template<typename T>
00369 inline bool
00370 intersects(const SGLineSegment<T>& lineSegment, const SGSphere<T>& sphere)
00371 {
00372
00373
00374 SGVec3<T> l = sphere.getCenter() - lineSegment.getStart();
00375 T ld = length(lineSegment.getDirection());
00376 T s = dot(l, lineSegment.getDirection())/ld;
00377 T l2 = dot(l, l);
00378
00379 T r2 = sphere.getRadius2();
00380 if (s < 0 && l2 > r2)
00381 return false;
00382
00383 T m2 = l2 - s*s;
00384 if (m2 > r2)
00385 return false;
00386
00387 T q = sqrt(r2 - m2);
00388 T t = s - q;
00389 if (ld < t)
00390 return false;
00391
00392 return true;
00393 }
00394
00395 template<typename T>
00396 inline bool
00397 intersects(const SGSphere<T>& sphere, const SGLineSegment<T>& lineSegment)
00398 { return intersects(lineSegment, sphere); }
00399
00400
00401 template<typename T>
00402 inline bool
00403
00404 intersects(SGVec3<T>& x, const SGTriangle<T>& tri, const SGRay<T>& ray, T eps = 0)
00405 {
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 SGVec3<T> p = cross(ray.getDirection(), tri.getEdge(1));
00416
00417 T denom = dot(p, tri.getEdge(0));
00418 T signDenom = copysign(1, denom);
00419
00420 SGVec3<T> s = ray.getOrigin() - tri.getBaseVertex();
00421 SGVec3<T> q = cross(s, tri.getEdge(0));
00422
00423
00424
00425 T tDenom = signDenom*dot(q, tri.getEdge(1));
00426 if (tDenom < 0)
00427 return false;
00428
00429
00430
00431
00432
00433
00434
00435 T absDenom = fabs(denom);
00436 T absDenomEps = absDenom*eps;
00437
00438
00439 T u = signDenom*dot(p, s);
00440 if (u < -absDenomEps)
00441 return false;
00442
00443
00444
00445 T v = signDenom*dot(q, ray.getDirection());
00446 if (v < -absDenomEps)
00447 return false;
00448
00449 if (u + v > absDenom + absDenomEps)
00450 return false;
00451
00452
00453
00454 if (absDenom <= SGLimits<T>::min())
00455 return false;
00456
00457 x = ray.getOrigin();
00458
00459
00460 if (SGLimitsd::min() < absDenom)
00461 x += (tDenom/absDenom)*ray.getDirection();
00462
00463 return true;
00464 }
00465
00466 template<typename T>
00467 inline bool
00468 intersects(const SGTriangle<T>& tri, const SGRay<T>& ray, T eps = 0)
00469 {
00470
00471
00472 SGVec3<T> dummy;
00473 return intersects(dummy, tri, ray, eps);
00474 }
00475
00476 template<typename T>
00477 inline bool
00478
00479 intersects(SGVec3<T>& x, const SGTriangle<T>& tri, const SGLineSegment<T>& lineSegment, T eps = 0)
00480 {
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 SGVec3<T> p = cross(lineSegment.getDirection(), tri.getEdge(1));
00491
00492 T denom = dot(p, tri.getEdge(0));
00493 T signDenom = copysign(1, denom);
00494
00495 SGVec3<T> s = lineSegment.getStart() - tri.getBaseVertex();
00496 SGVec3<T> q = cross(s, tri.getEdge(0));
00497
00498
00499
00500 T tDenom = signDenom*dot(q, tri.getEdge(1));
00501 if (tDenom < 0)
00502 return false;
00503
00504
00505
00506
00507 T absDenom = fabs(denom);
00508 if (absDenom < tDenom)
00509 return false;
00510
00511
00512 T absDenomEps = absDenom*eps;
00513
00514
00515 T u = signDenom*dot(p, s);
00516 if (u < -absDenomEps)
00517 return false;
00518
00519
00520
00521 T v = signDenom*dot(q, lineSegment.getDirection());
00522 if (v < -absDenomEps)
00523 return false;
00524
00525 if (u + v > absDenom + absDenomEps)
00526 return false;
00527
00528
00529
00530 if (absDenom <= SGLimits<T>::min())
00531 return false;
00532
00533 x = lineSegment.getStart();
00534
00535
00536 if (SGLimitsd::min() < absDenom)
00537 x += (tDenom/absDenom)*lineSegment.getDirection();
00538
00539 return true;
00540 }
00541
00542 template<typename T>
00543 inline bool
00544 intersects(const SGTriangle<T>& tri, const SGLineSegment<T>& lineSegment, T eps = 0)
00545 {
00546
00547
00548 SGVec3<T> dummy;
00549 return intersects(dummy, tri, lineSegment, eps);
00550 }
00551
00552
00553 template<typename T>
00554 inline SGVec3<T>
00555 closestPoint(const SGTriangle<T>& tri, const SGVec3<T>& p)
00556 {
00557
00558
00559
00560
00561
00562
00563 SGVec3<T> off = tri.getBaseVertex() - p;
00564 T a = dot(tri.getEdge(0), tri.getEdge(0));
00565 T b = dot(tri.getEdge(0), tri.getEdge(1));
00566 T c = dot(tri.getEdge(1), tri.getEdge(1));
00567 T d = dot(tri.getEdge(0), off);
00568 T e = dot(tri.getEdge(1), off);
00569
00570 T det = a*c - b*b;
00571
00572 T u = b*e - c*d;
00573 T v = b*d - a*e;
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 if (u + v <= det) {
00586 if (u < 0) {
00587 if (v < 0) {
00588
00589 if (d < 0) {
00590 if (a <= -d) {
00591
00592
00593 return tri.getBaseVertex() + tri.getEdge(0);
00594 } else {
00595 u = -d/a;
00596
00597 return tri.getBaseVertex() + u*tri.getEdge(0);
00598 }
00599 } else {
00600 if (0 < e) {
00601
00602
00603 return tri.getBaseVertex();
00604 } else if (c <= -e) {
00605
00606
00607 return tri.getBaseVertex() + tri.getEdge(1);
00608 } else {
00609
00610 v = -e/c;
00611 return tri.getBaseVertex() + v*tri.getEdge(1);
00612 }
00613 }
00614 } else {
00615
00616 if (0 <= e) {
00617
00618
00619 return tri.getBaseVertex();
00620 } else if (c <= -e) {
00621
00622
00623 return tri.getBaseVertex() + tri.getEdge(1);
00624 } else {
00625
00626 v = -e/c;
00627 return tri.getBaseVertex() + v*tri.getEdge(1);
00628 }
00629 }
00630 } else if (v < 0) {
00631
00632 if (0 <= d) {
00633
00634
00635 return tri.getBaseVertex();
00636 } else if (a <= -d) {
00637
00638
00639 return tri.getBaseVertex() + tri.getEdge(0);
00640 } else {
00641 u = -d/a;
00642
00643 return tri.getBaseVertex() + u*tri.getEdge(0);
00644 }
00645 } else {
00646
00647 if (det <= SGLimits<T>::min()) {
00648 u = 0;
00649 v = 0;
00650 return tri.getBaseVertex();
00651 } else {
00652 T invDet = 1/det;
00653 u *= invDet;
00654 v *= invDet;
00655 return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
00656 }
00657 }
00658 } else {
00659 if (u < 0) {
00660
00661 T tmp0 = b + d;
00662 T tmp1 = c + e;
00663 if (tmp0 < tmp1) {
00664 T numer = tmp1 - tmp0;
00665 T denom = a - 2*b + c;
00666 if (denom <= numer) {
00667
00668
00669 return tri.getBaseVertex() + tri.getEdge(0);
00670 } else {
00671 u = numer/denom;
00672 v = 1 - u;
00673 return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
00674 }
00675 } else {
00676 if (tmp1 <= 0) {
00677
00678
00679 return tri.getBaseVertex() + tri.getEdge(1);
00680 } else if (0 <= e) {
00681
00682
00683 return tri.getBaseVertex();
00684 } else {
00685
00686 v = -e/c;
00687 return tri.getBaseVertex() + v*tri.getEdge(1);
00688 }
00689 }
00690 } else if (v < 0) {
00691
00692 T tmp0 = b + e;
00693 T tmp1 = a + d;
00694 if (tmp0 < tmp1) {
00695 T numer = tmp1 - tmp0;
00696 T denom = a - 2*b + c;
00697 if (denom <= numer) {
00698
00699
00700 return tri.getBaseVertex() + tri.getEdge(1);
00701 } else {
00702 v = numer/denom;
00703 u = 1 - v;
00704 return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
00705 }
00706 } else {
00707 if (tmp1 < 0) {
00708
00709
00710 return tri.getBaseVertex() + tri.getEdge(0);
00711 } else if (0 <= d) {
00712
00713
00714 return tri.getBaseVertex();
00715 } else {
00716 u = -d/a;
00717
00718 return tri.getBaseVertex() + u*tri.getEdge(0);
00719 }
00720 }
00721 } else {
00722
00723 T numer = c + e - b - d;
00724 if (numer <= 0) {
00725
00726
00727 return tri.getVertex(2);
00728 } else {
00729 T denom = a - 2*b + c;
00730 if (denom <= numer) {
00731
00732
00733 return tri.getBaseVertex() + tri.getEdge(0);
00734 } else {
00735 u = numer/denom;
00736 v = 1 - u;
00737 return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
00738 }
00739 }
00740 }
00741 }
00742 }
00743 template<typename T>
00744 inline SGVec3<T>
00745 closestPoint(const SGVec3<T>& p, const SGTriangle<T>& tri)
00746 { return closestPoint(tri, p); }
00747
00748 template<typename T, typename T2>
00749 inline bool
00750 intersects(const SGTriangle<T>& tri, const SGSphere<T2>& sphere)
00751 {
00752
00753
00754
00755
00756
00757
00758 SGVec3<T> off = tri.getBaseVertex() - SGVec3<T>(sphere.getCenter());
00759 T baseDist2 = dot(off, off);
00760 T a = dot(tri.getEdge(0), tri.getEdge(0));
00761 T b = dot(tri.getEdge(0), tri.getEdge(1));
00762 T c = dot(tri.getEdge(1), tri.getEdge(1));
00763 T d = dot(tri.getEdge(0), off);
00764 T e = dot(tri.getEdge(1), off);
00765
00766 T det = a*c - b*b;
00767
00768 T u = b*e - c*d;
00769 T v = b*d - a*e;
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 if (u + v <= det) {
00782 if (u < 0) {
00783 if (v < 0) {
00784
00785 if (d < 0) {
00786 if (a <= -d) {
00787
00788
00789 T sqrDist = a + 2*d + baseDist2;
00790 return sqrDist <= sphere.getRadius2();
00791 } else {
00792 u = -d/a;
00793
00794 T sqrDist = d*u + baseDist2;
00795 return sqrDist <= sphere.getRadius2();
00796 }
00797 } else {
00798 if (0 < e) {
00799
00800
00801 return baseDist2 <= sphere.getRadius2();
00802 } else if (c <= -e) {
00803
00804
00805 T sqrDist = c + 2*e + baseDist2;
00806 return sqrDist <= sphere.getRadius2();
00807 } else {
00808
00809 v = -e/c;
00810 T sqrDist = e*v + baseDist2;
00811 return sqrDist <= sphere.getRadius2();
00812 }
00813 }
00814 } else {
00815
00816 if (0 <= e) {
00817
00818
00819 return baseDist2 <= sphere.getRadius2();
00820 } else if (c <= -e) {
00821
00822
00823 T sqrDist = c + 2*e + baseDist2;
00824 return sqrDist <= sphere.getRadius2();
00825 } else {
00826
00827 v = -e/c;
00828 T sqrDist = e*v + baseDist2;
00829 return sqrDist <= sphere.getRadius2();
00830 }
00831 }
00832 } else if (v < 0) {
00833
00834 if (0 <= d) {
00835
00836
00837 return baseDist2 <= sphere.getRadius2();
00838 } else if (a <= -d) {
00839
00840
00841 T sqrDist = a + 2*d + baseDist2;
00842 return sqrDist <= sphere.getRadius2();
00843 } else {
00844 u = -d/a;
00845
00846 T sqrDist = d*u + baseDist2;
00847 return sqrDist <= sphere.getRadius2();
00848 }
00849 } else {
00850
00851 if (det <= SGLimits<T>::min()) {
00852
00853 u = 0;
00854 v = 0;
00855 return baseDist2 <= sphere.getRadius2();
00856 } else {
00857 T invDet = 1/det;
00858 u *= invDet;
00859 v *= invDet;
00860 T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
00861 return sqrDist <= sphere.getRadius2();
00862 }
00863 }
00864 } else {
00865 if (u < 0) {
00866
00867 T tmp0 = b + d;
00868 T tmp1 = c + e;
00869 if (tmp0 < tmp1) {
00870 T numer = tmp1 - tmp0;
00871 T denom = a - 2*b + c;
00872 if (denom <= numer) {
00873
00874
00875 T sqrDist = a + 2*d + baseDist2;
00876 return sqrDist <= sphere.getRadius2();
00877 } else {
00878 u = numer/denom;
00879 v = 1 - u;
00880 T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
00881 return sqrDist <= sphere.getRadius2();
00882 }
00883 } else {
00884 if (tmp1 <= 0) {
00885
00886
00887 T sqrDist = c + 2*e + baseDist2;
00888 return sqrDist <= sphere.getRadius2();
00889 } else if (0 <= e) {
00890
00891
00892 return baseDist2 <= sphere.getRadius2();
00893 } else {
00894
00895 v = -e/c;
00896 T sqrDist = e*v + baseDist2;
00897 return sqrDist <= sphere.getRadius2();
00898 }
00899 }
00900 } else if (v < 0) {
00901
00902 T tmp0 = b + e;
00903 T tmp1 = a + d;
00904 if (tmp0 < tmp1) {
00905 T numer = tmp1 - tmp0;
00906 T denom = a - 2*b + c;
00907 if (denom <= numer) {
00908
00909
00910 T sqrDist = c + 2*e + baseDist2;
00911 return sqrDist <= sphere.getRadius2();
00912 } else {
00913 v = numer/denom;
00914 u = 1 - v;
00915 T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e)+baseDist2;
00916 return sqrDist <= sphere.getRadius2();
00917 }
00918 } else {
00919 if (tmp1 < 0) {
00920
00921
00922 T sqrDist = a + 2*d + baseDist2;
00923 return sqrDist <= sphere.getRadius2();
00924 } else if (0 <= d) {
00925
00926
00927
00928 return baseDist2 <= sphere.getRadius2();
00929 } else {
00930 u = -d/a;
00931
00932 T sqrDist = d*u + baseDist2;
00933 return sqrDist <= sphere.getRadius2();
00934 }
00935 }
00936 } else {
00937
00938 T numer = c + e - b - d;
00939 if (numer <= 0) {
00940
00941
00942 T sqrDist = c + 2*e + baseDist2;
00943 return sqrDist <= sphere.getRadius2();
00944 } else {
00945 T denom = a - 2*b + c;
00946 if (denom <= numer) {
00947
00948
00949 T sqrDist = a + 2*d + baseDist2;
00950 return sqrDist <= sphere.getRadius2();
00951 } else {
00952 u = numer/denom;
00953 v = 1 - u;
00954 T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
00955 return sqrDist <= sphere.getRadius2();
00956 }
00957 }
00958 }
00959 }
00960 }
00961 template<typename T1, typename T2>
00962 inline bool
00963 intersects(const SGSphere<T1>& sphere, const SGTriangle<T2>& tri)
00964 { return intersects(tri, sphere); }
00965
00966
00967 template<typename T>
00968 inline bool
00969 intersects(const SGVec3<T>& v, const SGSphere<T>& sphere)
00970 {
00971 if (sphere.empty())
00972 return false;
00973 return distSqr(v, sphere.getCenter()) <= sphere.getRadius2();
00974 }
00975 template<typename T>
00976 inline bool
00977 intersects(const SGSphere<T>& sphere, const SGVec3<T>& v)
00978 { return intersects(v, sphere); }
00979
00980
00981 template<typename T>
00982 inline bool
00983 intersects(const SGBox<T>& box, const SGLineSegment<T>& lineSegment)
00984 {
00985
00986
00987 SGVec3<T> c = lineSegment.getCenter() - box.getCenter();
00988 SGVec3<T> w = T(0.5)*lineSegment.getDirection();
00989 SGVec3<T> v(fabs(w.x()), fabs(w.y()), fabs(w.z()));
00990 SGVec3<T> h = T(0.5)*box.getSize();
00991
00992 if (fabs(c[0]) > v[0] + h[0])
00993 return false;
00994 if (fabs(c[1]) > v[1] + h[1])
00995 return false;
00996 if (fabs(c[2]) > v[2] + h[2])
00997 return false;
00998
00999 if (fabs(c[1]*w[2] - c[2]*w[1]) > h[1]*v[2] + h[2]*v[1])
01000 return false;
01001 if (fabs(c[0]*w[2] - c[2]*w[0]) > h[0]*v[2] + h[2]*v[0])
01002 return false;
01003 if (fabs(c[0]*w[1] - c[1]*w[0]) > h[0]*v[1] + h[1]*v[0])
01004 return false;
01005
01006 return true;
01007 }
01008 template<typename T>
01009 inline bool
01010 intersects(const SGLineSegment<T>& lineSegment, const SGBox<T>& box)
01011 { return intersects(box, lineSegment); }
01012
01013 template<typename T>
01014 inline bool
01015 intersects(const SGBox<T>& box, const SGRay<T>& ray)
01016 {
01017
01018
01019 for (unsigned i = 0; i < 3; ++i) {
01020 T cMin = box.getMin()[i];
01021 T cMax = box.getMax()[i];
01022
01023 T cOrigin = ray.getOrigin()[i];
01024
01025 T cDir = ray.getDirection()[i];
01026 if (fabs(cDir) <= SGLimits<T>::min()) {
01027 if (cOrigin < cMin)
01028 return false;
01029 if (cMax < cOrigin)
01030 return false;
01031 }
01032
01033 T nearr = - SGLimits<T>::max();
01034 T farr = SGLimits<T>::max();
01035
01036 T T1 = (cMin - cOrigin) / cDir;
01037 T T2 = (cMax - cOrigin) / cDir;
01038 if (T1 > T2) std::swap (T1, T2);
01039 if (T1 > nearr) nearr = T1;
01040 if (T2 < farr) farr = T2;
01041 if (nearr > farr)
01042 return false;
01043 if (farr < 0)
01044 return false;
01045 }
01046
01047 return true;
01048 }
01049
01050 template<typename T>
01051 inline bool
01052 intersects(const SGRay<T>& ray, const SGBox<T>& box)
01053 { return intersects(box, ray); }
01054
01055 template<typename T1, typename T2>
01056 inline bool
01057 intersects(const SGBox<T1>& box1, const SGBox<T2>& box2)
01058 {
01059 if (box2.getMax()[0] < box1.getMin()[0])
01060 return false;
01061 if (box1.getMax()[0] < box2.getMin()[0])
01062 return false;
01063
01064 if (box2.getMax()[1] < box1.getMin()[1])
01065 return false;
01066 if (box1.getMax()[1] < box2.getMin()[1])
01067 return false;
01068
01069 if (box2.getMax()[2] < box1.getMin()[2])
01070 return false;
01071 if (box1.getMax()[2] < box2.getMin()[2])
01072 return false;
01073
01074 return true;
01075 }
01076
01077 #endif