00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef BASE_BOUNDBOX_H
00025 #define BASE_BOUNDBOX_H
00026
00027 #include "Vector3D.h"
00028 #include "Matrix.h"
00029 #include "ViewProj.h"
00030 #include "Tools2D.h"
00031
00032
00033 #define IS_ON_RAY(A,B,K) (((A) <= (K)) && ((B) > (K)))
00034
00035 namespace Base {
00036
00037 class ViewProjMethod;
00038
00040 template <class _Precision>
00041 class BoundBox3
00042 {
00043 public:
00044 typedef _Precision num_type;
00045 typedef float_traits<num_type> traits_type;
00046
00049 _Precision MinX;
00050 _Precision MinY;
00051 _Precision MinZ;
00052 _Precision MaxX;
00053 _Precision MaxY;
00054 _Precision MaxZ;
00056
00058 inline explicit BoundBox3 ( _Precision fMinX = FLOAT_MAX, _Precision fMinY = FLOAT_MAX,
00059 _Precision fMinZ = FLOAT_MAX, _Precision fMaxX = -FLOAT_MAX,
00060 _Precision fMaxY = -FLOAT_MAX, _Precision fMaxZ = -FLOAT_MAX );
00061 BoundBox3 (const BoundBox3<_Precision> &rcBB) { *this = rcBB; }
00063 inline BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt);
00064
00068 BoundBox3 (const Vector3<_Precision> &rcCnt, _Precision fDistance);
00069 ~BoundBox3 ();
00070
00072 inline BoundBox3<_Precision>& operator = (const BoundBox3<_Precision> &rcBound);
00073
00077 inline bool operator && (const BoundBox3<_Precision> &rcBB) const;
00079 inline bool operator && (const BoundBox2D &rcBB) const;
00083 BoundBox3<_Precision> operator & (const BoundBox3<_Precision> &rcBB) const;
00085 inline BoundBox3<_Precision>& operator &= (const Vector3<_Precision> &rclVect);
00087 BoundBox3<_Precision> operator | (const BoundBox3<_Precision> &rcBB) const;
00091 inline void Add (const Vector3<_Precision> &rclVect);
00093 inline void Add (const BoundBox3<_Precision> &rcBB);
00095
00099 inline bool IsInBox (const Vector3<_Precision> &rcVct) const;
00101 inline bool IsInBox (const BoundBox3<_Precision> &rcBB) const;
00103 inline bool IsInBox (const BoundBox2D &rcbb) const;
00105 bool IsValid (void) const;
00107
00108 enum OCTANT {OCT_LDB = 0, OCT_RDB, OCT_LUB, OCT_RUB,
00109 OCT_LDF, OCT_RDF, OCT_LUF, OCT_RUF};
00110 bool GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const;
00111 BoundBox3<_Precision> CalcOctant (typename BoundBox3<_Precision>::OCTANT Octant) const;
00112
00113 enum SIDE { LEFT =0, RIGHT=1, TOP=2, BOTTOM=3, FRONT=4, BACK=5, INVALID=255 };
00114
00122 inline Vector3<_Precision> CalcPoint (unsigned short usPoint) const;
00124 void CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const;
00131 bool CalcDistance (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const;
00136 bool IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const;
00138 bool IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance = 0.0f) const;
00140 inline bool IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const;
00142 bool IntersectWithLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const;
00144 bool IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir,
00145 Vector3<_Precision>& rcP0) const;
00147 typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const;
00149 typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir, Vector3<_Precision>& rcInt) const;
00150
00155 Vector3<_Precision> NearestPoint (const Vector3<_Precision> &rclPt) const;
00157 BoundBox2D ProjectBox(const ViewProjMethod *rclP) const;
00158 BoundBox3<_Precision> Transformed(const Matrix4D& mat) const;
00159
00161 inline Vector3<_Precision> CalcCenter (void) const;
00162 inline _Precision CalcDiagonalLength (void) const;
00163 void Flush (void);
00164
00166 inline void Enlarge (_Precision fLen);
00168 inline void Shrink (_Precision fLen);
00169
00171 inline _Precision LengthX (void) const;
00173 inline _Precision LengthY (void) const;
00175 inline _Precision LengthZ (void) const;
00177 inline void MoveX (_Precision f);
00179 inline void MoveY (_Precision f);
00181 inline void MoveZ (_Precision f);
00183 inline void ScaleX (_Precision f);
00185 inline void ScaleY (_Precision f);
00187 inline void ScaleZ (_Precision f);
00188
00190 void Print (void);
00191 };
00192
00193
00194 template <class _Precision>
00195 inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> &rcVector, _Precision fDistance)
00196 {
00197 MinX = rcVector.x - fDistance;
00198 MaxX = rcVector.x + fDistance;
00199 MinY = rcVector.y - fDistance;
00200 MaxY = rcVector.y + fDistance;
00201 MinZ = rcVector.z - fDistance;
00202 MaxZ = rcVector.z + fDistance;
00203 }
00204
00205 template <class _Precision>
00206 inline BoundBox3<_Precision>::~BoundBox3 ()
00207 {
00208 }
00209
00210 template <class _Precision>
00211 inline BoundBox3<_Precision> BoundBox3<_Precision>::operator & (const BoundBox3<_Precision> &rcBB) const
00212 {
00213 BoundBox3<_Precision> cBBRes;
00214
00215 cBBRes.MinX = std::max<_Precision> (MinX, rcBB.MinX);
00216 cBBRes.MaxX = std::min<_Precision> (MaxX, rcBB.MaxX);
00217 cBBRes.MinY = std::max<_Precision> (MinY, rcBB.MinY);
00218 cBBRes.MaxY = std::min<_Precision> (MaxY, rcBB.MaxY);
00219 cBBRes.MinZ = std::max<_Precision> (MinZ, rcBB.MinZ);
00220 cBBRes.MaxZ = std::min<_Precision> (MaxZ, rcBB.MaxZ);
00221
00222 return cBBRes;
00223 }
00224
00225 template <class _Precision>
00226 inline BoundBox3<_Precision> BoundBox3<_Precision>::operator | (const BoundBox3<_Precision> &rcBB) const
00227 {
00228 BoundBox3<_Precision> cBBRes;
00229
00230 cBBRes.MinX = std::min<_Precision> (MinX, rcBB.MinX);
00231 cBBRes.MaxX = std::max<_Precision> (MaxX, rcBB.MaxX);
00232 cBBRes.MinY = std::min<_Precision> (MinY, rcBB.MinY);
00233 cBBRes.MaxY = std::max<_Precision> (MaxY, rcBB.MaxY);
00234 cBBRes.MinZ = std::min<_Precision> (MinZ, rcBB.MinZ);
00235 cBBRes.MaxZ = std::max<_Precision> (MaxZ, rcBB.MaxZ);
00236
00237 return cBBRes;
00238 }
00239
00240 template <class _Precision>
00241 inline void BoundBox3<_Precision>::Add (const Vector3<_Precision> &rclVect)
00242 {
00243 this->MinX = std::min<_Precision>(this->MinX, rclVect.x);
00244 this->MinY = std::min<_Precision>(this->MinY, rclVect.y);
00245 this->MinZ = std::min<_Precision>(this->MinZ, rclVect.z);
00246 this->MaxX = std::max<_Precision>(this->MaxX, rclVect.x);
00247 this->MaxY = std::max<_Precision>(this->MaxY, rclVect.y);
00248 this->MaxZ = std::max<_Precision>(this->MaxZ, rclVect.z);
00249 }
00250
00251 template <class _Precision>
00252 inline void BoundBox3<_Precision>::Add (const BoundBox3<_Precision> &rcBB)
00253 {
00254 this->MinX = std::min<_Precision> (this->MinX, rcBB.MinX);
00255 this->MaxX = std::max<_Precision> (this->MaxX, rcBB.MaxX);
00256 this->MinY = std::min<_Precision> (this->MinY, rcBB.MinY);
00257 this->MaxY = std::max<_Precision> (this->MaxY, rcBB.MaxY);
00258 this->MinZ = std::min<_Precision> (this->MinZ, rcBB.MinZ);
00259 this->MaxZ = std::max<_Precision> (this->MaxZ, rcBB.MaxZ);
00260 }
00261
00262 template <class _Precision>
00263 inline bool BoundBox3<_Precision>::IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance) const
00264 {
00265 _Precision fDist;
00266
00267
00268
00269
00270
00271
00272
00273 fDist = (rcDir % (CalcCenter() - rcBase)).Length() / rcDir.Length();
00274
00275 if (fDist > (CalcDiagonalLength() + fTolerance))
00276 return false;
00277 else
00278 {
00279 unsigned char i;
00280 Vector3<_Precision> clVectRes;
00281
00282
00283 for (i = 0; i < 6; i++)
00284 {
00285
00286 if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes) == true)
00287 {
00288
00289 switch (i)
00290 {
00291 case 0 :
00292 case 1 :
00293 if ((IS_ON_RAY (MinY - fTolerance, MaxY + fTolerance, clVectRes.y) &&
00294 IS_ON_RAY (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z)) == true)
00295 return true;
00296 break;
00297 case 2 :
00298 case 3 :
00299 if ((IS_ON_RAY (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) &&
00300 IS_ON_RAY (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))== true)
00301 return true;
00302 break;
00303 case 4 :
00304 case 5 :
00305 if ((IS_ON_RAY (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) &&
00306 IS_ON_RAY (MinY - fTolerance, MaxY + fTolerance, clVectRes.y)) == true)
00307 return true;
00308 break;
00309 }
00310 }
00311 }
00312 }
00313
00314 return false;
00315 }
00316
00317 template <class _Precision>
00318 inline bool BoundBox3<_Precision>::IsValid (void) const
00319 {
00320 return ((MinX <= MaxX) && (MinY <= MaxY) && (MinZ <= MaxZ));
00321 }
00322
00323 #define HALF(A,B) ((A)+((B-A)/2))
00324
00325 template <class _Precision>
00326 inline bool BoundBox3<_Precision>::GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const
00327 {
00328 if (!IsInBox (rclVct))
00329 return false;
00330
00331 unsigned short usNdx = 0;
00332 if (IS_ON_RAY (HALF (MinX, MaxX), MaxX, rclVct.x))
00333 usNdx |= 1;
00334 if (IS_ON_RAY (HALF (MinY, MaxY), MaxY, rclVct.y))
00335 usNdx |= 2;
00336 if (IS_ON_RAY (HALF (MinZ, MaxZ), MaxZ, rclVct.z))
00337 usNdx |= 4;
00338 rclOctant = (OCTANT) usNdx;
00339 return true;
00340 }
00341
00342 template <class _Precision>
00343 inline BoundBox3<_Precision> BoundBox3<_Precision>::CalcOctant (typename BoundBox3< _Precision >::OCTANT Octant) const
00344 {
00345 BoundBox3<_Precision> cOct (*this);
00346
00347 switch (Octant)
00348 {
00349 case OCT_LDB:
00350 cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00351 cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00352 cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00353 break;
00354
00355 case OCT_RDB:
00356 cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00357 cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00358 cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00359 break;
00360
00361 case OCT_LUB:
00362 cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00363 cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00364 cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00365 break;
00366
00367 case OCT_RUB:
00368 cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00369 cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00370 cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00371 break;
00372
00373 case OCT_LDF:
00374 cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00375 cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00376 cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00377 break;
00378
00379 case OCT_RDF:
00380 cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00381 cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00382 cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00383 break;
00384
00385 case OCT_LUF:
00386 cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00387 cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00388 cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00389 break;
00390
00391 case OCT_RUF:
00392 cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00393 cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00394 cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00395 break;
00396 }
00397 return cOct;
00398 }
00399
00400 #undef HALF
00401
00402 template <class _Precision>
00403 inline void BoundBox3<_Precision>::CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const
00404 {
00405 switch (usPlane)
00406 {
00407
00408 case 0:
00409 rBase.Set(MinX, MinY, MaxZ);
00410 rNormal.Set(1.0f, 0.0f, 0.0f);
00411 break;
00412
00413
00414 case 1:
00415 rBase.Set(MaxX, MinY, MaxZ);
00416 rNormal.Set(1.0f, 0.0f, 0.0f);
00417 break;
00418
00419
00420 case 2:
00421 rBase.Set(MinX, MaxY, MaxZ);
00422 rNormal.Set(0.0f, 1.0f, 0.0f);
00423 break;
00424
00425
00426 case 3:
00427 rBase.Set(MinX, MinY, MaxZ);
00428 rNormal.Set(0.0f, 1.0f, 0.0f);
00429 break;
00430
00431
00432 case 4:
00433 rBase.Set(MinX, MinY, MaxZ);
00434 rNormal.Set(0.0f, 0.0f, 1.0f);
00435 break;
00436
00437
00438 default:
00439 rBase.Set(MinX, MinY, MinZ);
00440 rNormal.Set(0.0f, 0.0f, 1.0f);
00441 break;
00442 }
00443 }
00444
00445 template <class _Precision>
00446 inline bool BoundBox3<_Precision>::CalcDistance (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const
00447 {
00448 switch (usEdge)
00449 {
00450 case 0:
00451 rcP0 = CalcPoint(0);
00452 rcP1 = CalcPoint(1);
00453 break;
00454 case 1:
00455 rcP0 = CalcPoint(1);
00456 rcP1 = CalcPoint(2);
00457 break;
00458 case 2:
00459 rcP0 = CalcPoint(2);
00460 rcP1 = CalcPoint(3);
00461 break;
00462 case 3:
00463 rcP0 = CalcPoint(3);
00464 rcP1 = CalcPoint(0);
00465 break;
00466 case 4:
00467 rcP0 = CalcPoint(4);
00468 rcP1 = CalcPoint(5);
00469 break;
00470 case 5:
00471 rcP0 = CalcPoint(5);
00472 rcP1 = CalcPoint(6);
00473 break;
00474 case 6:
00475 rcP0 = CalcPoint(6);
00476 rcP1 = CalcPoint(7);
00477 break;
00478 case 7:
00479 rcP0 = CalcPoint(7);
00480 rcP1 = CalcPoint(4);
00481 break;
00482 case 8:
00483 rcP0 = CalcPoint(0);
00484 rcP1 = CalcPoint(4);
00485 break;
00486 case 9:
00487 rcP0 = CalcPoint(1);
00488 rcP1 = CalcPoint(5);
00489 break;
00490 case 10:
00491 rcP0 = CalcPoint(2);
00492 rcP1 = CalcPoint(6);
00493 break;
00494 case 11:
00495 rcP0 = CalcPoint(3);
00496 rcP1 = CalcPoint(7);
00497 break;
00498 default:
00499 return false;
00500 }
00501
00502 return true;
00503 }
00504
00505 template <class _Precision>
00506 inline bool BoundBox3<_Precision>::IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const
00507 {
00508 bool rc=false;
00509 BoundBox3<_Precision> cCmpBound(*this);
00510 unsigned short i;
00511
00512
00513 cCmpBound.Enlarge(epsilon);
00514
00515
00516 if (cCmpBound.IsInBox (rcVct)) {
00517
00518 for (i = 0; (i < 6) && (!rc); i++) {
00519 rc = IntersectPlaneWithLine(i, rcVct, rcVctDir, cVctRes);
00520 if (!cCmpBound.IsInBox(cVctRes))
00521 rc = false;
00522 if (rc == true) {
00523
00524
00525
00526 rc = ((cVctRes - rcVct) * rcVctDir) >= (_Precision)0.0;
00527 }
00528 }
00529 }
00530
00531 return rc;
00532 }
00533
00534 template <class _Precision>
00535 inline bool BoundBox3<_Precision>::IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase,
00536 const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0) const
00537 {
00538 _Precision k;
00539 Vector3<_Precision> cBase, cNormal;
00540 Vector3<_Precision> cDir(rcDir);
00541 CalcPlane(usSide, cBase, cNormal);
00542
00543 if ((cNormal * cDir) == 0.0f)
00544 return false;
00545 else
00546 {
00547 k = (cNormal * (cBase - rcBase)) / (cNormal * cDir);
00548 cDir.Scale(k, k, k);
00549 rcP0 = rcBase + cDir;
00550
00551 return true;
00552 }
00553 }
00554
00555 template <class _Precision>
00556 inline bool BoundBox3<_Precision>::IntersectWithLine ( const Vector3<_Precision> & rcBase, const Vector3<_Precision>& rcDir,
00557 Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1 ) const
00558 {
00559 Vector3<_Precision> clVectRes, clVect[6];
00560 unsigned short i, j;
00561
00562 j = 0;
00563
00564 for (i = 0; i < 6; i++)
00565 {
00566
00567 if ( IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes ) )
00568 {
00569
00570 switch (i)
00571 {
00572 case 0 :
00573 case 1 :
00574 if ((IS_ON_RAY(MinY, MaxY, clVectRes.y) &&
00575 IS_ON_RAY(MinZ, MaxZ, clVectRes.z)) == true)
00576 {
00577 clVect[j] = clVectRes;
00578 j++;
00579 }
00580 break;
00581 case 2 :
00582 case 3 :
00583 if ((IS_ON_RAY(MinX, MaxX, clVectRes.x) &&
00584 IS_ON_RAY(MinZ, MaxZ, clVectRes.z))== true)
00585 {
00586 clVect[j] = clVectRes;
00587 j++;
00588 }
00589 break;
00590 case 4 :
00591 case 5 :
00592 if ((IS_ON_RAY(MinX, MaxX, clVectRes.x) &&
00593 IS_ON_RAY(MinY, MaxY, clVectRes.y)) == true)
00594 {
00595 clVect[j] = clVectRes;
00596 j++;
00597 }
00598 break;
00599 }
00600 }
00601 }
00602
00603 if (j == 2)
00604 {
00605 rcP0 = clVect[0];
00606 rcP1 = clVect[1];
00607 return true;
00608 }
00609 else if (j > 2)
00610 {
00611 for (i = 1; i < j; i++)
00612 {
00613 if (clVect[i] != clVect[0])
00614 {
00615 rcP0 = clVect[0];
00616 rcP1 = clVect[i];
00617 return true;
00618 }
00619 }
00620 }
00621
00622 return false;
00623 }
00624
00625 template <class _Precision>
00626 inline typename BoundBox3<_Precision>::SIDE BoundBox3<_Precision>::GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const
00627 {
00628 Vector3<_Precision> cIntersection;
00629 return GetSideFromRay( rclPt, rclDir, cIntersection);
00630 }
00631
00632 template <class _Precision>
00633 inline typename BoundBox3<_Precision>::SIDE BoundBox3<_Precision>::GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir,
00634 Vector3<_Precision>& rcInt) const
00635 {
00636 Vector3<_Precision> cP0, cP1;
00637 if ( IntersectWithLine(rclPt, rclDir, cP0, cP1) == false )
00638 return INVALID;
00639
00640 Vector3<_Precision> cOut;
00641
00642 if ( (cP1-cP0)*rclDir > 0.0f )
00643 cOut = cP1;
00644 else
00645 cOut = cP0;
00646
00647 rcInt = cOut;
00648
00649 _Precision fMax = 1.0e-3f;
00650 SIDE tSide = INVALID;
00651
00652 if (fabs(cOut.x - MinX) < fMax)
00653 {
00654 fMax = _Precision(fabs(cOut.x - MinX));
00655 tSide = LEFT;
00656 }
00657
00658 if (fabs(cOut.x - MaxX) < fMax)
00659 {
00660 fMax = _Precision(fabs(cOut.x - MaxX));
00661 tSide = RIGHT;
00662 }
00663
00664 if (fabs(cOut.y - MinY) < fMax)
00665 {
00666 fMax = _Precision(fabs(cOut.y - MinY));
00667 tSide = BOTTOM;
00668 }
00669
00670 if (fabs(cOut.y - MaxY) < fMax)
00671 {
00672 fMax = _Precision(fabs(cOut.y - MaxY));
00673 tSide = TOP;
00674 }
00675
00676 if (fabs(cOut.z - MinZ) < fMax)
00677 {
00678 fMax = _Precision(fabs(cOut.z - MinZ));
00679 tSide = FRONT;
00680 }
00681
00682 if (fabs(cOut.z - MaxZ) < fMax)
00683 {
00684 fMax = _Precision(fabs(cOut.z - MaxZ));
00685 tSide = BACK;
00686 }
00687
00688 return tSide;
00689 }
00690
00691 template <class _Precision>
00692 inline void BoundBox3<_Precision>::Flush (void)
00693 {
00694 MinX = MinY = MinZ = FLOAT_MAX;
00695 MaxX = MaxY = MaxZ = -FLOAT_MAX;
00696 }
00697
00698 template <class _Precision>
00699 inline void BoundBox3<_Precision>::Print (void)
00700 {
00701 printf ("X1 : %5.2f Y1 : %5.2f Z1 : %5.2f\n", MinX, MinY, MinZ);
00702 printf ("X2 : %5.2f Y2 : %5.2f Z2 : %5.2f\n", MaxX, MaxY, MaxZ);
00703 }
00704
00705 template <class _Precision>
00706 inline BoundBox2D BoundBox3<_Precision>::ProjectBox(const ViewProjMethod *pclP) const
00707 {
00708 BoundBox2D clBB2D;
00709
00710 clBB2D.SetVoid();
00711
00712 for (int i = 0; i < 8; i++)
00713 {
00714 Vector3<_Precision> clTrsPt = (*pclP)(CalcPoint(i));
00715 clBB2D &= Vector2D(clTrsPt.x, clTrsPt.y);
00716 }
00717
00718 return clBB2D;
00719 }
00720
00721 template <class _Precision>
00722 inline BoundBox3<_Precision> BoundBox3<_Precision>::Transformed(const Matrix4D& mat) const
00723 {
00724 BoundBox3<_Precision> bbox;
00725 for (int i=0; i<8; i++)
00726 bbox.Add(mat * CalcPoint(i));
00727 return bbox;
00728 }
00729
00730 template <class _Precision>
00731 inline Vector3<_Precision> BoundBox3<_Precision>::NearestPoint (const Vector3<_Precision> &rclPt) const
00732 {
00733
00734 _Precision fMinDist = FLOAT_MAX;
00735 Vector3<_Precision> cBase, cNormal, clRet;
00736
00737 for (int i = 0; i < 6; i++)
00738 {
00739 Vector3<_Precision> clTemp = rclPt;
00740 CalcPlane(i, cBase, cNormal);
00741 clTemp.ProjToPlane(cBase, cNormal);
00742 _Precision fDist = (clTemp - rclPt).Length();
00743 if (fDist < fMinDist)
00744 {
00745 fMinDist = fDist;
00746 clRet = clTemp;
00747 }
00748 }
00749
00750 return clRet;
00751 }
00752
00753
00754 template <class _Precision>
00755 inline BoundBox3<_Precision>::BoundBox3 (_Precision fMinX, _Precision fMinY, _Precision fMinZ,
00756 _Precision fMaxX, _Precision fMaxY, _Precision fMaxZ)
00757 : MinX(fMinX), MinY(fMinY), MinZ(fMinZ),
00758 MaxX(fMaxX), MaxY(fMaxY), MaxZ(fMaxZ)
00759 {
00760 }
00761
00762 template <class _Precision>
00763 inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt)
00764 : MinX(FLOAT_MAX), MinY(FLOAT_MAX), MinZ(FLOAT_MAX),
00765 MaxX(-FLOAT_MAX), MaxY(-FLOAT_MAX), MaxZ(-FLOAT_MAX)
00766 {
00767 const Vector3<_Precision> *pI, *pEnd = pclVect + ulCt;
00768 for (pI = pclVect; pI < pEnd; pI++)
00769 {
00770 MinX = std::min<_Precision>(MinX, pI->x);
00771 MinY = std::min<_Precision>(MinY, pI->y);
00772 MinZ = std::min<_Precision>(MinZ, pI->z);
00773 MaxX = std::max<_Precision>(MaxX, pI->x);
00774 MaxY = std::max<_Precision>(MaxY, pI->y);
00775 MaxZ = std::max<_Precision>(MaxZ, pI->z);
00776 }
00777 }
00778
00779 template <class _Precision>
00780 inline BoundBox3<_Precision>& BoundBox3<_Precision>::operator = (const BoundBox3<_Precision> &rcBound)
00781 {
00782 MinX = rcBound.MinX;
00783 MinY = rcBound.MinY;
00784 MinZ = rcBound.MinZ;
00785 MaxX = rcBound.MaxX;
00786 MaxY = rcBound.MaxY;
00787 MaxZ = rcBound.MaxZ;
00788 return *this;
00789 }
00790
00791 template <class _Precision>
00792 inline BoundBox3<_Precision>& BoundBox3<_Precision>::operator &= (const Vector3<_Precision> &rclVect)
00793 {
00794 MinX = std::min<_Precision>(MinX, rclVect.x);
00795 MinY = std::min<_Precision>(MinY, rclVect.y);
00796 MinZ = std::min<_Precision>(MinZ, rclVect.z);
00797 MaxX = std::max<_Precision>(MaxX, rclVect.x);
00798 MaxY = std::max<_Precision>(MaxY, rclVect.y);
00799 MaxZ = std::max<_Precision>(MaxZ, rclVect.z);
00800 return *this;
00801 }
00802
00803 template <class _Precision>
00804 inline bool BoundBox3<_Precision>::operator && (const BoundBox3<_Precision> &rcBB) const
00805 {
00806 return (IS_ON_RAY (MinX, MaxX, rcBB.MinX) ||
00807 IS_ON_RAY (MinX, MaxX, rcBB.MaxX) ||
00808 IS_ON_RAY (rcBB.MinX, rcBB.MaxX, MinX) ||
00809 IS_ON_RAY (rcBB.MinX, rcBB.MaxX, MaxX)) &&
00810 (IS_ON_RAY (MinY, MaxY, rcBB.MinY) ||
00811 IS_ON_RAY (MinY, MaxY, rcBB.MaxY) ||
00812 IS_ON_RAY (rcBB.MinY, rcBB.MaxY, MinY) ||
00813 IS_ON_RAY (rcBB.MinY, rcBB.MaxY, MaxY)) &&
00814 (IS_ON_RAY (MinZ, MaxZ, rcBB.MinZ) ||
00815 IS_ON_RAY (MinZ, MaxZ, rcBB.MaxZ) ||
00816 IS_ON_RAY (rcBB.MinZ, rcBB.MaxZ, MinZ) ||
00817 IS_ON_RAY (rcBB.MinZ, rcBB.MaxZ, MaxZ));
00818 }
00819
00820 template <class _Precision>
00821 inline bool BoundBox3<_Precision>::operator && (const BoundBox2D &rcBB) const
00822 {
00823 return (IS_ON_RAY (MinX, MaxX, rcBB.fMinX) ||
00824 IS_ON_RAY (MinX, MaxX, rcBB.fMaxX) ||
00825 IS_ON_RAY (rcBB.fMinX, rcBB.fMaxX, MinX) ||
00826 IS_ON_RAY (rcBB.fMinX, rcBB.fMaxX, MaxX)) &&
00827 (IS_ON_RAY (MinY, MaxY, rcBB.fMinY) ||
00828 IS_ON_RAY (MinY, MaxY, rcBB.fMaxY) ||
00829 IS_ON_RAY (rcBB.fMinY, rcBB.fMaxY, MinY) ||
00830 IS_ON_RAY (rcBB.fMinY, rcBB.fMaxY, MaxY) );
00831 }
00832
00833 template <class _Precision>
00834 inline Vector3<_Precision> BoundBox3<_Precision>::CalcPoint (unsigned short usPoint) const
00835 {
00836 switch (usPoint)
00837 {
00838 case 0: return Vector3<_Precision>(MinX, MinY, MaxZ);
00839 case 1: return Vector3<_Precision>(MaxX, MinY, MaxZ);
00840 case 2: return Vector3<_Precision>(MaxX, MaxY, MaxZ);
00841 case 3: return Vector3<_Precision>(MinX, MaxY, MaxZ);
00842 case 4: return Vector3<_Precision>(MinX, MinY, MinZ);
00843 case 5: return Vector3<_Precision>(MaxX, MinY, MinZ);
00844 case 6: return Vector3<_Precision>(MaxX, MaxY, MinZ);
00845 case 7: return Vector3<_Precision>(MinX, MaxY, MinZ);
00846 }
00847
00848 return Vector3<_Precision>();
00849 }
00850
00851 template <class _Precision>
00852 inline Vector3<_Precision> BoundBox3<_Precision>::CalcCenter (void) const
00853 {
00854 return Vector3<_Precision>(MinX + (MaxX - MinX) / 2.0f,
00855 MinY + (MaxY - MinY) / 2.0f,
00856 MinZ + (MaxZ - MinZ) / 2.0f);
00857 }
00858
00859 template <class _Precision>
00860 inline _Precision BoundBox3<_Precision>::CalcDiagonalLength (void) const
00861 {
00862 return (_Precision)sqrt (((MaxX - MinX) * (MaxX - MinX)) +
00863 ((MaxY - MinY) * (MaxY - MinY)) +
00864 ((MaxZ - MinZ) * (MaxZ - MinZ)));
00865 }
00866
00867 template <class _Precision>
00868 inline bool BoundBox3<_Precision>::IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const
00869 {
00870 if (fabs(CalcCenter().DistanceToPlane(rclBase, rclNormal)) < CalcDiagonalLength())
00871 {
00872 _Precision fD = CalcPoint(0).DistanceToPlane(rclBase, rclNormal);
00873 for (unsigned short i = 1; i < 8; i++)
00874 {
00875 if ((CalcPoint(i).DistanceToPlane(rclBase, rclNormal) * fD) < 0.0f)
00876 return true;
00877 }
00878 }
00879 return false;
00880 }
00881
00882 template <class _Precision>
00883 inline void BoundBox3<_Precision>::Enlarge (_Precision fLen)
00884 {
00885 MinX -= fLen; MinY -= fLen; MinZ -= fLen;
00886 MaxX += fLen; MaxY += fLen; MaxZ += fLen;
00887 }
00888
00889 template <class _Precision>
00890 inline void BoundBox3<_Precision>::Shrink (_Precision fLen)
00891 {
00892 MinX += fLen; MinY += fLen; MinZ += fLen;
00893 MaxX -= fLen; MaxY -= fLen; MaxZ -= fLen;
00894 }
00895
00896 template <class _Precision>
00897 inline bool BoundBox3<_Precision>::IsInBox (const Vector3<_Precision> &rcVct) const
00898 {
00899 return (IS_ON_RAY (MinX, MaxX, rcVct.x) &&
00900 IS_ON_RAY (MinY, MaxY, rcVct.y) &&
00901 IS_ON_RAY (MinZ, MaxZ, rcVct.z));
00902 }
00903
00904 template <class _Precision>
00905 inline bool BoundBox3<_Precision>::IsInBox (const BoundBox3<_Precision> &rcBB) const
00906 {
00907 return (IS_ON_RAY (MinX, MaxX, rcBB.MinX) &&
00908 IS_ON_RAY (MinX, MaxX, rcBB.MaxX) &&
00909 IS_ON_RAY (MinY, MaxY, rcBB.MinY) &&
00910 IS_ON_RAY (MinY, MaxY, rcBB.MaxY) &&
00911 IS_ON_RAY (MinZ, MaxZ, rcBB.MinZ) &&
00912 IS_ON_RAY (MinZ, MaxZ, rcBB.MaxZ));
00913 }
00914
00915 template <class _Precision>
00916 inline bool BoundBox3<_Precision>::IsInBox (const BoundBox2D &rcBB) const
00917 {
00918 return ( IS_ON_RAY (MinX, MaxX, rcBB.fMinX) &&
00919 IS_ON_RAY (MinX, MaxX, rcBB.fMaxX) &&
00920 IS_ON_RAY (MinY, MaxY, rcBB.fMinY) &&
00921 IS_ON_RAY (MinY, MaxY, rcBB.fMaxY) );
00922 }
00923
00924 template <class _Precision>
00925 inline _Precision BoundBox3<_Precision>::LengthX (void) const
00926 {
00927 return MaxX - MinX;
00928 }
00929
00930 template <class _Precision>
00931 inline _Precision BoundBox3<_Precision>::LengthY (void) const
00932 {
00933 return MaxY - MinY;
00934 }
00935
00936 template <class _Precision>
00937 inline _Precision BoundBox3<_Precision>::LengthZ (void) const
00938 {
00939 return MaxZ - MinZ;
00940 }
00941
00942 template <class _Precision>
00943 inline void BoundBox3<_Precision>::MoveX (_Precision f)
00944 {
00945 MinX += f; MaxX += f;
00946 }
00947
00948 template <class _Precision>
00949 inline void BoundBox3<_Precision>::MoveY (_Precision f)
00950 {
00951 MinY += f; MaxY += f;
00952 }
00953
00954 template <class _Precision>
00955 inline void BoundBox3<_Precision>::MoveZ (_Precision f)
00956 {
00957 MinZ += f; MaxZ += f;
00958 }
00959
00960 template <class _Precision>
00961 inline void BoundBox3<_Precision>::ScaleX (_Precision f)
00962 {
00963 MinX *= f; MaxX *= f;
00964 }
00965
00966 template <class _Precision>
00967 inline void BoundBox3<_Precision>::ScaleY (_Precision f)
00968 {
00969 MinY *= f; MaxY *= f;
00970 }
00971
00972 template <class _Precision>
00973 inline void BoundBox3<_Precision>::ScaleZ (_Precision f)
00974 {
00975 MinZ *= f; MaxZ *= f;
00976 }
00977
00978 typedef BoundBox3<float> BoundBox3f;
00979 typedef BoundBox3<double> BoundBox3d;
00980
00981 }
00982
00983
00984 #endif // BASE_BOUNDBOX_H
00985