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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef INCLUDED_IMATHBOXALGO_H
00038 #define INCLUDED_IMATHBOXALGO_H
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 #include "ImathBox.h"
00073 #include "ImathMatrix.h"
00074 #include "ImathLineAlgo.h"
00075 #include "ImathPlane.h"
00076
00077 namespace Imath {
00078
00079
00080 template <class T>
00081 inline T
00082 clip (const T &p, const Box<T> &box)
00083 {
00084
00085
00086
00087
00088
00089 T q;
00090
00091 for (int i = 0; i < int (box.min.dimensions()); i++)
00092 {
00093 if (p[i] < box.min[i])
00094 q[i] = box.min[i];
00095 else if (p[i] > box.max[i])
00096 q[i] = box.max[i];
00097 else
00098 q[i] = p[i];
00099 }
00100
00101 return q;
00102 }
00103
00104
00105 template <class T>
00106 inline T
00107 closestPointInBox (const T &p, const Box<T> &box)
00108 {
00109 return clip (p, box);
00110 }
00111
00112
00113 template <class T>
00114 Vec3<T>
00115 closestPointOnBox (const Vec3<T> &p, const Box< Vec3<T> > &box)
00116 {
00117
00118
00119
00120
00121
00122
00123
00124 if (box.isEmpty())
00125 return p;
00126
00127 Vec3<T> q = closestPointInBox (p, box);
00128
00129 if (q == p)
00130 {
00131 Vec3<T> d1 = p - box.min;
00132 Vec3<T> d2 = box.max - p;
00133
00134 Vec3<T> d ((d1.x < d2.x)? d1.x: d2.x,
00135 (d1.y < d2.y)? d1.y: d2.y,
00136 (d1.z < d2.z)? d1.z: d2.z);
00137
00138 if (d.x < d.y && d.x < d.z)
00139 {
00140 q.x = (d1.x < d2.x)? box.min.x: box.max.x;
00141 }
00142 else if (d.y < d.z)
00143 {
00144 q.y = (d1.y < d2.y)? box.min.y: box.max.y;
00145 }
00146 else
00147 {
00148 q.z = (d1.z < d2.z)? box.min.z: box.max.z;
00149 }
00150 }
00151
00152 return q;
00153 }
00154
00155
00156 template <class S, class T>
00157 Box< Vec3<S> >
00158 transform (const Box< Vec3<S> > &box, const Matrix44<T> &m)
00159 {
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 if (box.isEmpty())
00174 return box;
00175
00176
00177
00178
00179
00180
00181 if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
00182 {
00183 Box< Vec3<S> > newBox;
00184
00185 for (int i = 0; i < 3; i++)
00186 {
00187 newBox.min[i] = newBox.max[i] = (S) m[3][i];
00188
00189 for (int j = 0; j < 3; j++)
00190 {
00191 float a, b;
00192
00193 a = (S) m[j][i] * box.min[j];
00194 b = (S) m[j][i] * box.max[j];
00195
00196 if (a < b)
00197 {
00198 newBox.min[i] += a;
00199 newBox.max[i] += b;
00200 }
00201 else
00202 {
00203 newBox.min[i] += b;
00204 newBox.max[i] += a;
00205 }
00206 }
00207 }
00208
00209 return newBox;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 Vec3<S> points[8];
00219
00220 points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
00221 points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
00222
00223 points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
00224 points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
00225
00226 points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
00227 points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
00228
00229 Box< Vec3<S> > newBox;
00230
00231 for (int i = 0; i < 8; i++)
00232 newBox.extendBy (points[i] * m);
00233
00234 return newBox;
00235 }
00236
00237
00238 template <class S, class T>
00239 Box< Vec3<S> >
00240 affineTransform (const Box< Vec3<S> > &box, const Matrix44<T> &m)
00241 {
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 if (box.isEmpty())
00252 {
00253
00254
00255
00256
00257 return box;
00258 }
00259
00260 Box< Vec3<S> > newBox;
00261
00262 for (int i = 0; i < 3; i++)
00263 {
00264 newBox.min[i] = newBox.max[i] = (S) m[3][i];
00265
00266 for (int j = 0; j < 3; j++)
00267 {
00268 float a, b;
00269
00270 a = (S) m[j][i] * box.min[j];
00271 b = (S) m[j][i] * box.max[j];
00272
00273 if (a < b)
00274 {
00275 newBox.min[i] += a;
00276 newBox.max[i] += b;
00277 }
00278 else
00279 {
00280 newBox.min[i] += b;
00281 newBox.max[i] += a;
00282 }
00283 }
00284 }
00285
00286 return newBox;
00287 }
00288
00289
00290 template <class T>
00291 bool
00292 findEntryAndExitPoints (const Line3<T> &r,
00293 const Box<Vec3<T> > &b,
00294 Vec3<T> &entry,
00295 Vec3<T> &exit)
00296 {
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 if (b.isEmpty())
00320 {
00321
00322
00323
00324
00325 return false;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 const T TMAX = limits<T>::max();
00347
00348 T tFrontMax = -TMAX;
00349 T tBackMin = TMAX;
00350
00351
00352
00353
00354
00355 if (r.dir.x >= 0)
00356 {
00357 T d1 = b.max.x - r.pos.x;
00358 T d2 = b.min.x - r.pos.x;
00359
00360 if (r.dir.x > 1 ||
00361 (abs (d1) < TMAX * r.dir.x &&
00362 abs (d2) < TMAX * r.dir.x))
00363 {
00364 T t1 = d1 / r.dir.x;
00365 T t2 = d2 / r.dir.x;
00366
00367 if (tBackMin > t1)
00368 {
00369 tBackMin = t1;
00370
00371 exit.x = b.max.x;
00372 exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
00373 exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
00374 }
00375
00376 if (tFrontMax < t2)
00377 {
00378 tFrontMax = t2;
00379
00380 entry.x = b.min.x;
00381 entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
00382 entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
00383 }
00384 }
00385 else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
00386 {
00387 return false;
00388 }
00389 }
00390 else
00391 {
00392 T d1 = b.min.x - r.pos.x;
00393 T d2 = b.max.x - r.pos.x;
00394
00395 if (r.dir.x < -1 ||
00396 (abs (d1) < -TMAX * r.dir.x &&
00397 abs (d2) < -TMAX * r.dir.x))
00398 {
00399 T t1 = d1 / r.dir.x;
00400 T t2 = d2 / r.dir.x;
00401
00402 if (tBackMin > t1)
00403 {
00404 tBackMin = t1;
00405
00406 exit.x = b.min.x;
00407 exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
00408 exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
00409 }
00410
00411 if (tFrontMax < t2)
00412 {
00413 tFrontMax = t2;
00414
00415 entry.x = b.max.x;
00416 entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
00417 entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
00418 }
00419 }
00420 else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
00421 {
00422 return false;
00423 }
00424 }
00425
00426
00427
00428
00429
00430 if (r.dir.y >= 0)
00431 {
00432 T d1 = b.max.y - r.pos.y;
00433 T d2 = b.min.y - r.pos.y;
00434
00435 if (r.dir.y > 1 ||
00436 (abs (d1) < TMAX * r.dir.y &&
00437 abs (d2) < TMAX * r.dir.y))
00438 {
00439 T t1 = d1 / r.dir.y;
00440 T t2 = d2 / r.dir.y;
00441
00442 if (tBackMin > t1)
00443 {
00444 tBackMin = t1;
00445
00446 exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
00447 exit.y = b.max.y;
00448 exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
00449 }
00450
00451 if (tFrontMax < t2)
00452 {
00453 tFrontMax = t2;
00454
00455 entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
00456 entry.y = b.min.y;
00457 entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
00458 }
00459 }
00460 else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
00461 {
00462 return false;
00463 }
00464 }
00465 else
00466 {
00467 T d1 = b.min.y - r.pos.y;
00468 T d2 = b.max.y - r.pos.y;
00469
00470 if (r.dir.y < -1 ||
00471 (abs (d1) < -TMAX * r.dir.y &&
00472 abs (d2) < -TMAX * r.dir.y))
00473 {
00474 T t1 = d1 / r.dir.y;
00475 T t2 = d2 / r.dir.y;
00476
00477 if (tBackMin > t1)
00478 {
00479 tBackMin = t1;
00480
00481 exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
00482 exit.y = b.min.y;
00483 exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
00484 }
00485
00486 if (tFrontMax < t2)
00487 {
00488 tFrontMax = t2;
00489
00490 entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
00491 entry.y = b.max.y;
00492 entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
00493 }
00494 }
00495 else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
00496 {
00497 return false;
00498 }
00499 }
00500
00501
00502
00503
00504
00505 if (r.dir.z >= 0)
00506 {
00507 T d1 = b.max.z - r.pos.z;
00508 T d2 = b.min.z - r.pos.z;
00509
00510 if (r.dir.z > 1 ||
00511 (abs (d1) < TMAX * r.dir.z &&
00512 abs (d2) < TMAX * r.dir.z))
00513 {
00514 T t1 = d1 / r.dir.z;
00515 T t2 = d2 / r.dir.z;
00516
00517 if (tBackMin > t1)
00518 {
00519 tBackMin = t1;
00520
00521 exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
00522 exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
00523 exit.z = b.max.z;
00524 }
00525
00526 if (tFrontMax < t2)
00527 {
00528 tFrontMax = t2;
00529
00530 entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
00531 entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
00532 entry.z = b.min.z;
00533 }
00534 }
00535 else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
00536 {
00537 return false;
00538 }
00539 }
00540 else
00541 {
00542 T d1 = b.min.z - r.pos.z;
00543 T d2 = b.max.z - r.pos.z;
00544
00545 if (r.dir.z < -1 ||
00546 (abs (d1) < -TMAX * r.dir.z &&
00547 abs (d2) < -TMAX * r.dir.z))
00548 {
00549 T t1 = d1 / r.dir.z;
00550 T t2 = d2 / r.dir.z;
00551
00552 if (tBackMin > t1)
00553 {
00554 tBackMin = t1;
00555
00556 exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
00557 exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
00558 exit.z = b.min.z;
00559 }
00560
00561 if (tFrontMax < t2)
00562 {
00563 tFrontMax = t2;
00564
00565 entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
00566 entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
00567 entry.z = b.max.z;
00568 }
00569 }
00570 else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
00571 {
00572 return false;
00573 }
00574 }
00575
00576 return tFrontMax <= tBackMin;
00577 }
00578
00579
00580 template<class T>
00581 bool
00582 intersects (const Box< Vec3<T> > &b, const Line3<T> &r, Vec3<T> &ip)
00583 {
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 if (b.isEmpty())
00609 {
00610
00611
00612
00613
00614 return false;
00615 }
00616
00617 if (b.intersects (r.pos))
00618 {
00619
00620
00621
00622
00623 ip = r.pos;
00624 return true;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 const T TMAX = limits<T>::max();
00641
00642 T tFrontMax = -1;
00643 T tBackMin = TMAX;
00644
00645
00646
00647
00648
00649 if (r.dir.x > 0)
00650 {
00651 if (r.pos.x > b.max.x)
00652 return false;
00653
00654 T d = b.max.x - r.pos.x;
00655
00656 if (r.dir.x > 1 || d < TMAX * r.dir.x)
00657 {
00658 T t = d / r.dir.x;
00659
00660 if (tBackMin > t)
00661 tBackMin = t;
00662 }
00663
00664 if (r.pos.x <= b.min.x)
00665 {
00666 T d = b.min.x - r.pos.x;
00667 T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX;
00668
00669 if (tFrontMax < t)
00670 {
00671 tFrontMax = t;
00672
00673 ip.x = b.min.x;
00674 ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
00675 ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
00676 }
00677 }
00678 }
00679 else if (r.dir.x < 0)
00680 {
00681 if (r.pos.x < b.min.x)
00682 return false;
00683
00684 T d = b.min.x - r.pos.x;
00685
00686 if (r.dir.x < -1 || d > TMAX * r.dir.x)
00687 {
00688 T t = d / r.dir.x;
00689
00690 if (tBackMin > t)
00691 tBackMin = t;
00692 }
00693
00694 if (r.pos.x >= b.max.x)
00695 {
00696 T d = b.max.x - r.pos.x;
00697 T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX;
00698
00699 if (tFrontMax < t)
00700 {
00701 tFrontMax = t;
00702
00703 ip.x = b.max.x;
00704 ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
00705 ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
00706 }
00707 }
00708 }
00709 else
00710 {
00711 if (r.pos.x < b.min.x || r.pos.x > b.max.x)
00712 return false;
00713 }
00714
00715
00716
00717
00718
00719 if (r.dir.y > 0)
00720 {
00721 if (r.pos.y > b.max.y)
00722 return false;
00723
00724 T d = b.max.y - r.pos.y;
00725
00726 if (r.dir.y > 1 || d < TMAX * r.dir.y)
00727 {
00728 T t = d / r.dir.y;
00729
00730 if (tBackMin > t)
00731 tBackMin = t;
00732 }
00733
00734 if (r.pos.y <= b.min.y)
00735 {
00736 T d = b.min.y - r.pos.y;
00737 T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX;
00738
00739 if (tFrontMax < t)
00740 {
00741 tFrontMax = t;
00742
00743 ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
00744 ip.y = b.min.y;
00745 ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
00746 }
00747 }
00748 }
00749 else if (r.dir.y < 0)
00750 {
00751 if (r.pos.y < b.min.y)
00752 return false;
00753
00754 T d = b.min.y - r.pos.y;
00755
00756 if (r.dir.y < -1 || d > TMAX * r.dir.y)
00757 {
00758 T t = d / r.dir.y;
00759
00760 if (tBackMin > t)
00761 tBackMin = t;
00762 }
00763
00764 if (r.pos.y >= b.max.y)
00765 {
00766 T d = b.max.y - r.pos.y;
00767 T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX;
00768
00769 if (tFrontMax < t)
00770 {
00771 tFrontMax = t;
00772
00773 ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
00774 ip.y = b.max.y;
00775 ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
00776 }
00777 }
00778 }
00779 else
00780 {
00781 if (r.pos.y < b.min.y || r.pos.y > b.max.y)
00782 return false;
00783 }
00784
00785
00786
00787
00788
00789 if (r.dir.z > 0)
00790 {
00791 if (r.pos.z > b.max.z)
00792 return false;
00793
00794 T d = b.max.z - r.pos.z;
00795
00796 if (r.dir.z > 1 || d < TMAX * r.dir.z)
00797 {
00798 T t = d / r.dir.z;
00799
00800 if (tBackMin > t)
00801 tBackMin = t;
00802 }
00803
00804 if (r.pos.z <= b.min.z)
00805 {
00806 T d = b.min.z - r.pos.z;
00807 T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX;
00808
00809 if (tFrontMax < t)
00810 {
00811 tFrontMax = t;
00812
00813 ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
00814 ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
00815 ip.z = b.min.z;
00816 }
00817 }
00818 }
00819 else if (r.dir.z < 0)
00820 {
00821 if (r.pos.z < b.min.z)
00822 return false;
00823
00824 T d = b.min.z - r.pos.z;
00825
00826 if (r.dir.z < -1 || d > TMAX * r.dir.z)
00827 {
00828 T t = d / r.dir.z;
00829
00830 if (tBackMin > t)
00831 tBackMin = t;
00832 }
00833
00834 if (r.pos.z >= b.max.z)
00835 {
00836 T d = b.max.z - r.pos.z;
00837 T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX;
00838
00839 if (tFrontMax < t)
00840 {
00841 tFrontMax = t;
00842
00843 ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
00844 ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
00845 ip.z = b.max.z;
00846 }
00847 }
00848 }
00849 else
00850 {
00851 if (r.pos.z < b.min.z || r.pos.z > b.max.z)
00852 return false;
00853 }
00854
00855 return tFrontMax <= tBackMin;
00856 }
00857
00858
00859 template<class T>
00860 bool
00861 intersects (const Box< Vec3<T> > &box, const Line3<T> &ray)
00862 {
00863 Vec3<T> ignored;
00864 return intersects (box, ray, ignored);
00865 }
00866
00867
00868 }
00869
00870 #endif