123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #ifndef _MBOX_H_
- #define _MBOX_H_
- #ifndef _MPOINT_H_
- #include "math/mPoint.h"
- #endif
- //------------------------------------------------------------------------------
- /// Bounding Box
- ///
- /// A helper class for working with boxes. It runs at F32 precision.
- ///
- /// @see Box3D
- class Box3F
- {
- public:
- Point3F mMin; ///< Minimum extents of box
- Point3F mMax; ///< Maximum extents of box
- public:
- Box3F() { }
- /// Create a box from two points.
- ///
- /// Normally, this function will compensate for mismatched
- /// min/max values. If you know your values are valid, you
- /// can set in_overrideCheck to true and skip this.
- ///
- /// @param in_rMin Minimum extents of box.
- /// @param in_rMax Maximum extents of box.
- /// @param in_overrideCheck Pass true to skip check of extents.
- Box3F(const Point3F& in_rMin, const Point3F& in_rMax, const bool in_overrideCheck = false);
- /// Create a box from six extent values.
- ///
- /// No checking is performed as to the validity of these
- /// extents, unlike the other constructor.
- Box3F(F32 xmin, F32 ymin, F32 zmin, F32 max, F32 ymax, F32 zmax);
- /// Check to see if a point is contained in this box.
- bool isContained(const Point3F& in_rContained) const;
- /// Check to see if another box overlaps this box.
- bool isOverlapped(const Box3F& in_rOverlap) const;
- /// Check to see if another box is contained in this box.
- bool isContained(const Box3F& in_rContained) const;
- F32 len_x() const;
- F32 len_y() const;
- F32 len_z() const;
- /// Perform an intersection operation with another box
- /// and store the results in this box.
- void intersect(const Box3F& in_rIntersect);
- void intersect(const Point3F& in_rIntersect);
- /// Get the center of this box.
- ///
- /// This is the average of min and mMax.
- void getCenter(Point3F* center) const;
- /// Collide a line against the box.
- ///
- /// @param start Start of line.
- /// @param end End of line.
- /// @param t Value from 0.0-1.0, indicating position
- /// along line of collision.
- /// @param n Normal of collision.
- bool collideLine(const Point3F& start, const Point3F& end, F32*t, Point3F*n) const;
- /// Collide a line against the box.
- ///
- /// Returns true on collision.
- bool collideLine(const Point3F& start, const Point3F& end) const;
- /// Collide an oriented box against the box.
- ///
- /// Returns true if "oriented" box collides with us.
- /// Assumes incoming box is centered at origin of source space.
- ///
- /// @param radii The dimension of incoming box (half x,y,z length).
- /// @param toUs A transform that takes incoming box into our space.
- bool collideOrientedBox(const Point3F & radii, const MatrixF & toUs) const;
- /// Check that the box is valid.
- ///
- /// Currently, this just means that min < mMax.
- bool isValidBox() const { return (mMin.x <= mMax.x) &&
- (mMin.y <= mMax.y) &&
- (mMin.z <= mMax.z); }
- /// Return the closest point of the box, relative to the passed point.
- Point3F getClosestPoint(const Point3F& refPt) const;
- };
- inline Box3F::Box3F(const Point3F& in_rMin, const Point3F& in_rMax, const bool in_overrideCheck)
- : mMin(in_rMin),
- mMax(in_rMax)
- {
- if (in_overrideCheck == false) {
- mMin.setMin(in_rMax);
- mMax.setMax(in_rMin);
- }
- }
- inline Box3F::Box3F(F32 xMin, F32 yMin, F32 zMin, F32 xMax, F32 yMax, F32 zMax)
- : mMin(xMin,yMin,zMin),
- mMax(xMax,yMax,zMax)
- {
- }
- inline bool Box3F::isContained(const Point3F& in_rContained) const
- {
- return (in_rContained.x >= mMin.x && in_rContained.x < mMax.x) &&
- (in_rContained.y >= mMin.y && in_rContained.y < mMax.y) &&
- (in_rContained.z >= mMin.z && in_rContained.z < mMax.z);
- }
- inline bool Box3F::isOverlapped(const Box3F& in_rOverlap) const
- {
- if (in_rOverlap.mMin.x > mMax.x ||
- in_rOverlap.mMin.y > mMax.y ||
- in_rOverlap.mMin.z > mMax.z)
- return false;
- if (in_rOverlap.mMax.x < mMin.x ||
- in_rOverlap.mMax.y < mMin.y ||
- in_rOverlap.mMax.z < mMin.z)
- return false;
- return true;
- }
- inline bool Box3F::isContained(const Box3F& in_rContained) const
- {
- return (mMin.x <= in_rContained.mMin.x) &&
- (mMin.y <= in_rContained.mMin.y) &&
- (mMin.z <= in_rContained.mMin.z) &&
- (mMax.x >= in_rContained.mMax.x) &&
- (mMax.y >= in_rContained.mMax.y) &&
- (mMax.z >= in_rContained.mMax.z);
- }
- inline F32 Box3F::len_x() const
- {
- return mMax.x - mMin.x;
- }
- inline F32 Box3F::len_y() const
- {
- return mMax.y - mMin.y;
- }
- inline F32 Box3F::len_z() const
- {
- return mMax.z - mMin.z;
- }
- inline void Box3F::intersect(const Box3F& in_rIntersect)
- {
- mMin.setMin(in_rIntersect.mMin);
- mMax.setMax(in_rIntersect.mMax);
- }
- inline void Box3F::intersect(const Point3F& in_rIntersect)
- {
- mMin.setMin(in_rIntersect);
- mMax.setMax(in_rIntersect);
- }
- inline void Box3F::getCenter(Point3F* center) const
- {
- center->x = F32((mMin.x + mMax.x) * 0.5);
- center->y = F32((mMin.y + mMax.y) * 0.5);
- center->z = F32((mMin.z + mMax.z) * 0.5);
- }
- inline Point3F Box3F::getClosestPoint(const Point3F& refPt) const
- {
- Point3F closest;
- if (refPt.x <= mMin.x) closest.x = mMin.x;
- else if (refPt.x > mMax.x) closest.x = mMax.x;
- else closest.x = refPt.x;
- if (refPt.y <= mMin.y) closest.y = mMin.y;
- else if (refPt.y > mMax.y) closest.y = mMax.y;
- else closest.y = refPt.y;
- if (refPt.z <= mMin.z) closest.z = mMin.z;
- else if (refPt.z > mMax.z) closest.z = mMax.z;
- else closest.z = refPt.z;
- return closest;
- }
- //------------------------------------------------------------------------------
- /// Clone of Box3F, using 3D types.
- ///
- /// 3D types use F64.
- ///
- /// @see Box3F
- class Box3D
- {
- public:
- Point3D mMin;
- Point3D mMax;
- public:
- Box3D() { }
- Box3D(const Point3D& in_rMin, const Point3D& in_rMax, const bool in_overrideCheck = false);
- bool isContained(const Point3D& in_rContained) const;
- bool isOverlapped(const Box3D& in_rOverlap) const;
- F64 len_x() const;
- F64 len_y() const;
- F64 len_z() const;
- void intersect(const Box3D& in_rIntersect);
- void getCenter(Point3D* center) const;
- };
- inline Box3D::Box3D(const Point3D& in_rMin, const Point3D& in_rMax, const bool in_overrideCheck)
- : mMin(in_rMin),
- mMax(in_rMax)
- {
- if (in_overrideCheck == false) {
- mMin.setMin(in_rMax);
- mMax.setMax(in_rMin);
- }
- }
- inline bool Box3D::isContained(const Point3D& in_rContained) const
- {
- return (in_rContained.x >= mMin.x && in_rContained.x < mMax.x) &&
- (in_rContained.y >= mMin.y && in_rContained.y < mMax.y) &&
- (in_rContained.z >= mMin.z && in_rContained.z < mMax.z);
- }
- inline bool Box3D::isOverlapped(const Box3D& in_rOverlap) const
- {
- if (in_rOverlap.mMin.x > mMax.x ||
- in_rOverlap.mMin.y > mMax.y ||
- in_rOverlap.mMin.z > mMax.z)
- return false;
- if (in_rOverlap.mMax.x < mMin.x ||
- in_rOverlap.mMax.y < mMin.y ||
- in_rOverlap.mMax.z < mMin.z)
- return false;
- return true;
- }
- inline F64 Box3D::len_x() const
- {
- return mMax.x - mMin.x;
- }
- inline F64 Box3D::len_y() const
- {
- return mMax.y - mMin.y;
- }
- inline F64 Box3D::len_z() const
- {
- return mMax.z - mMin.z;
- }
- inline void Box3D::intersect(const Box3D& in_rIntersect)
- {
- mMin.setMin(in_rIntersect.mMin);
- mMax.setMax(in_rIntersect.mMax);
- }
- inline void Box3D::getCenter(Point3D* center) const
- {
- center->x = (mMin.x + mMax.x) * 0.5;
- center->y = (mMin.y + mMax.y) * 0.5;
- center->z = (mMin.z + mMax.z) * 0.5;
- }
- #endif // _DBOX_H_
|