LCOV - code coverage report
Current view: top level - usr/include/irrlicht - aabbox3d.h (source / functions) Hit Total Coverage
Test: report Lines: 59 60 98.3 %
Date: 2015-07-11 18:23:49 Functions: 16 16 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2002-2012 Nikolaus Gebhardt
       2             : // This file is part of the "Irrlicht Engine".
       3             : // For conditions of distribution and use, see copyright notice in irrlicht.h
       4             : 
       5             : #ifndef __IRR_AABBOX_3D_H_INCLUDED__
       6             : #define __IRR_AABBOX_3D_H_INCLUDED__
       7             : 
       8             : #include "irrMath.h"
       9             : #include "plane3d.h"
      10             : #include "line3d.h"
      11             : 
      12             : namespace irr
      13             : {
      14             : namespace core
      15             : {
      16             : 
      17             : //! Axis aligned bounding box in 3d dimensional space.
      18             : /** Has some useful methods used with occlusion culling or clipping.
      19             : */
      20             : template <class T>
      21     4209526 : class aabbox3d
      22             : {
      23             :         public:
      24             : 
      25             :                 //! Default Constructor.
      26      847762 :                 aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {}
      27             :                 //! Constructor with min edge and max edge.
      28         192 :                 aabbox3d(const vector3d<T>& min, const vector3d<T>& max): MinEdge(min), MaxEdge(max) {}
      29             :                 //! Constructor with only one point.
      30        2064 :                 aabbox3d(const vector3d<T>& init): MinEdge(init), MaxEdge(init) {}
      31             :                 //! Constructor with min edge and max edge as single values, not vectors.
      32     1560778 :                 aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz): MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {}
      33             : 
      34             :                 // operators
      35             :                 //! Equality operator
      36             :                 /** \param other box to compare with.
      37             :                 \return True if both boxes are equal, else false. */
      38             :                 inline bool operator==(const aabbox3d<T>& other) const { return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);}
      39             :                 //! Inequality operator
      40             :                 /** \param other box to compare with.
      41             :                 \return True if both boxes are different, else false. */
      42             :                 inline bool operator!=(const aabbox3d<T>& other) const { return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);}
      43             : 
      44             :                 // functions
      45             : 
      46             :                 //! Resets the bounding box to a one-point box.
      47             :                 /** \param x X coord of the point.
      48             :                 \param y Y coord of the point.
      49             :                 \param z Z coord of the point. */
      50      111922 :                 void reset(T x, T y, T z)
      51             :                 {
      52      111922 :                         MaxEdge.set(x,y,z);
      53      111922 :                         MinEdge = MaxEdge;
      54      111922 :                 }
      55             : 
      56             :                 //! Resets the bounding box.
      57             :                 /** \param initValue New box to set this one to. */
      58             :                 void reset(const aabbox3d<T>& initValue)
      59             :                 {
      60             :                         *this = initValue;
      61             :                 }
      62             : 
      63             :                 //! Resets the bounding box to a one-point box.
      64             :                 /** \param initValue New point. */
      65      537240 :                 void reset(const vector3d<T>& initValue)
      66             :                 {
      67      537240 :                         MaxEdge = initValue;
      68      537240 :                         MinEdge = initValue;
      69      537240 :                 }
      70             : 
      71             :                 //! Adds a point to the bounding box
      72             :                 /** The box grows bigger, if point was outside of the box.
      73             :                 \param p: Point to add into the box. */
      74    30012105 :                 void addInternalPoint(const vector3d<T>& p)
      75             :                 {
      76    30012105 :                         addInternalPoint(p.X, p.Y, p.Z);
      77    30012009 :                 }
      78             : 
      79             :                 //! Adds another bounding box
      80             :                 /** The box grows bigger, if the new box was outside of the box.
      81             :                 \param b: Other bounding box to add into this box. */
      82      423480 :                 void addInternalBox(const aabbox3d<T>& b)
      83             :                 {
      84      423480 :                         addInternalPoint(b.MaxEdge);
      85      423480 :                         addInternalPoint(b.MinEdge);
      86      423480 :                 }
      87             : 
      88             :                 //! Adds a point to the bounding box
      89             :                 /** The box grows bigger, if point is outside of the box.
      90             :                 \param x X coordinate of the point to add to this box.
      91             :                 \param y Y coordinate of the point to add to this box.
      92             :                 \param z Z coordinate of the point to add to this box. */
      93    30011991 :                 void addInternalPoint(T x, T y, T z)
      94             :                 {
      95    30011991 :                         if (x>MaxEdge.X) MaxEdge.X = x;
      96    30011991 :                         if (y>MaxEdge.Y) MaxEdge.Y = y;
      97    30011991 :                         if (z>MaxEdge.Z) MaxEdge.Z = z;
      98             : 
      99    30011991 :                         if (x<MinEdge.X) MinEdge.X = x;
     100    30011991 :                         if (y<MinEdge.Y) MinEdge.Y = y;
     101    30011991 :                         if (z<MinEdge.Z) MinEdge.Z = z;
     102    30011991 :                 }
     103             : 
     104             :                 //! Get center of the bounding box
     105             :                 /** \return Center of the bounding box. */
     106     2265945 :                 vector3d<T> getCenter() const
     107             :                 {
     108     2265945 :                         return (MinEdge + MaxEdge) / 2;
     109             :                 }
     110             : 
     111             :                 //! Get extent of the box (maximal distance of two points in the box)
     112             :                 /** \return Extent of the bounding box. */
     113     1124763 :                 vector3d<T> getExtent() const
     114             :                 {
     115     1124763 :                         return MaxEdge - MinEdge;
     116             :                 }
     117             : 
     118             :                 //! Check if the box is empty.
     119             :                 /** This means that there is no space between the min and max edge.
     120             :                 \return True if box is empty, else false. */
     121             :                 bool isEmpty() const
     122             :                 {
     123             :                         return MinEdge.equals ( MaxEdge );
     124             :                 }
     125             : 
     126             :                 //! Get the volume enclosed by the box in cubed units
     127             :                 T getVolume() const
     128             :                 {
     129             :                         const vector3d<T> e = getExtent();
     130             :                         return e.X * e.Y * e.Z;
     131             :                 }
     132             : 
     133             :                 //! Get the surface area of the box in squared units
     134             :                 T getArea() const
     135             :                 {
     136             :                         const vector3d<T> e = getExtent();
     137             :                         return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z);
     138             :                 }
     139             : 
     140             :                 //! Stores all 8 edges of the box into an array
     141             :                 /** \param edges: Pointer to array of 8 edges. */
     142             :                 void getEdges(vector3d<T> *edges) const
     143             :                 {
     144             :                         const core::vector3d<T> middle = getCenter();
     145             :                         const core::vector3d<T> diag = middle - MaxEdge;
     146             : 
     147             :                         /*
     148             :                         Edges are stored in this way:
     149             :                         Hey, am I an ascii artist, or what? :) niko.
     150             :                    /3--------/7
     151             :                   / |       / |
     152             :                  /  |      /  |
     153             :                 1---------5   |
     154             :                 |  /2- - -|- -6
     155             :                 | /       |  /
     156             :                 |/        | /
     157             :                 0---------4/
     158             :                         */
     159             : 
     160             :                         edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z);
     161             :                         edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z);
     162             :                         edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z);
     163             :                         edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z);
     164             :                         edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z);
     165             :                         edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z);
     166             :                         edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z);
     167             :                         edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z);
     168             :                 }
     169             : 
     170             :                 //! Repairs the box.
     171             :                 /** Necessary if for example MinEdge and MaxEdge are swapped. */
     172       14892 :                 void repair()
     173             :                 {
     174             :                         T t;
     175             : 
     176       14892 :                         if (MinEdge.X > MaxEdge.X)
     177         772 :                                 { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; }
     178       14892 :                         if (MinEdge.Y > MaxEdge.Y)
     179           0 :                                 { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; }
     180       14892 :                         if (MinEdge.Z > MaxEdge.Z)
     181        1246 :                                 { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; }
     182       14892 :                 }
     183             : 
     184             :                 //! Calculates a new interpolated bounding box.
     185             :                 /** d=0 returns other, d=1 returns this, all other values blend between
     186             :                 the two boxes.
     187             :                 \param other Other box to interpolate between
     188             :                 \param d Value between 0.0f and 1.0f.
     189             :                 \return Interpolated box. */
     190             :                 aabbox3d<T> getInterpolated(const aabbox3d<T>& other, f32 d) const
     191             :                 {
     192             :                         f32 inv = 1.0f - d;
     193             :                         return aabbox3d<T>((other.MinEdge*inv) + (MinEdge*d),
     194             :                                 (other.MaxEdge*inv) + (MaxEdge*d));
     195             :                 }
     196             : 
     197             :                 //! Determines if a point is within this box.
     198             :                 /** Border is included (IS part of the box)!
     199             :                 \param p: Point to check.
     200             :                 \return True if the point is within the box and false if not */
     201             :                 bool isPointInside(const vector3d<T>& p) const
     202             :                 {
     203             :                         return (p.X >= MinEdge.X && p.X <= MaxEdge.X &&
     204             :                                 p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y &&
     205             :                                 p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z);
     206             :                 }
     207             : 
     208             :                 //! Determines if a point is within this box and not its borders.
     209             :                 /** Border is excluded (NOT part of the box)!
     210             :                 \param p: Point to check.
     211             :                 \return True if the point is within the box and false if not. */
     212             :                 bool isPointTotalInside(const vector3d<T>& p) const
     213             :                 {
     214             :                         return (p.X > MinEdge.X && p.X < MaxEdge.X &&
     215             :                                 p.Y > MinEdge.Y && p.Y < MaxEdge.Y &&
     216             :                                 p.Z > MinEdge.Z && p.Z < MaxEdge.Z);
     217             :                 }
     218             : 
     219             :                 //! Check if this box is completely inside the 'other' box.
     220             :                 /** \param other: Other box to check against.
     221             :                 \return True if this box is completly inside the other box,
     222             :                 otherwise false. */
     223             :                 bool isFullInside(const aabbox3d<T>& other) const
     224             :                 {
     225             :                         return (MinEdge.X >= other.MinEdge.X && MinEdge.Y >= other.MinEdge.Y && MinEdge.Z >= other.MinEdge.Z &&
     226             :                                 MaxEdge.X <= other.MaxEdge.X && MaxEdge.Y <= other.MaxEdge.Y && MaxEdge.Z <= other.MaxEdge.Z);
     227             :                 }
     228             : 
     229             :                 //! Determines if the axis-aligned box intersects with another axis-aligned box.
     230             :                 /** \param other: Other box to check a intersection with.
     231             :                 \return True if there is an intersection with the other box,
     232             :                 otherwise false. */
     233             :                 bool intersectsWithBox(const aabbox3d<T>& other) const
     234             :                 {
     235             :                         return (MinEdge.X <= other.MaxEdge.X && MinEdge.Y <= other.MaxEdge.Y && MinEdge.Z <= other.MaxEdge.Z &&
     236             :                                 MaxEdge.X >= other.MinEdge.X && MaxEdge.Y >= other.MinEdge.Y && MaxEdge.Z >= other.MinEdge.Z);
     237             :                 }
     238             : 
     239             :                 //! Tests if the box intersects with a line
     240             :                 /** \param line: Line to test intersection with.
     241             :                 \return True if there is an intersection , else false. */
     242     1124763 :                 bool intersectsWithLine(const line3d<T>& line) const
     243             :                 {
     244     2249526 :                         return intersectsWithLine(line.getMiddle(), line.getVector().normalize(),
     245     3374289 :                                         (T)(line.getLength() * 0.5));
     246             :                 }
     247             : 
     248             :                 //! Tests if the box intersects with a line
     249             :                 /** \param linemiddle Center of the line.
     250             :                 \param linevect Vector of the line.
     251             :                 \param halflength Half length of the line.
     252             :                 \return True if there is an intersection, else false. */
     253     1124763 :                 bool intersectsWithLine(const vector3d<T>& linemiddle,
     254             :                                         const vector3d<T>& linevect, T halflength) const
     255             :                 {
     256     1124763 :                         const vector3d<T> e = getExtent() * (T)0.5;
     257     1124763 :                         const vector3d<T> t = getCenter() - linemiddle;
     258             : 
     259     2576415 :                         if ((fabs(t.X) > e.X + halflength * fabs(linevect.X)) ||
     260     1420044 :                                 (fabs(t.Y) > e.Y + halflength * fabs(linevect.Y)) ||
     261       31608 :                                 (fabs(t.Z) > e.Z + halflength * fabs(linevect.Z)) )
     262     1118038 :                                 return false;
     263             : 
     264        6725 :                         T r = e.Y * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.Y);
     265        6725 :                         if (fabs(t.Y*linevect.Z - t.Z*linevect.Y) > r )
     266        4084 :                                 return false;
     267             : 
     268        2641 :                         r = e.X * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.X);
     269        2641 :                         if (fabs(t.Z*linevect.X - t.X*linevect.Z) > r )
     270        1913 :                                 return false;
     271             : 
     272         728 :                         r = e.X * (T)fabs(linevect.Y) + e.Y * (T)fabs(linevect.X);
     273         728 :                         if (fabs(t.X*linevect.Y - t.Y*linevect.X) > r)
     274         253 :                                 return false;
     275             : 
     276         475 :                         return true;
     277             :                 }
     278             : 
     279             :                 //! Classifies a relation with a plane.
     280             :                 /** \param plane Plane to classify relation to.
     281             :                 \return Returns ISREL3D_FRONT if the box is in front of the plane,
     282             :                 ISREL3D_BACK if the box is behind the plane, and
     283             :                 ISREL3D_CLIPPED if it is on both sides of the plane. */
     284             :                 EIntersectionRelation3D classifyPlaneRelation(const plane3d<T>& plane) const
     285             :                 {
     286             :                         vector3d<T> nearPoint(MaxEdge);
     287             :                         vector3d<T> farPoint(MinEdge);
     288             : 
     289             :                         if (plane.Normal.X > (T)0)
     290             :                         {
     291             :                                 nearPoint.X = MinEdge.X;
     292             :                                 farPoint.X = MaxEdge.X;
     293             :                         }
     294             : 
     295             :                         if (plane.Normal.Y > (T)0)
     296             :                         {
     297             :                                 nearPoint.Y = MinEdge.Y;
     298             :                                 farPoint.Y = MaxEdge.Y;
     299             :                         }
     300             : 
     301             :                         if (plane.Normal.Z > (T)0)
     302             :                         {
     303             :                                 nearPoint.Z = MinEdge.Z;
     304             :                                 farPoint.Z = MaxEdge.Z;
     305             :                         }
     306             : 
     307             :                         if (plane.Normal.dotProduct(nearPoint) + plane.D > (T)0)
     308             :                                 return ISREL3D_FRONT;
     309             : 
     310             :                         if (plane.Normal.dotProduct(farPoint) + plane.D > (T)0)
     311             :                                 return ISREL3D_CLIPPED;
     312             : 
     313             :                         return ISREL3D_BACK;
     314             :                 }
     315             : 
     316             :                 //! The near edge
     317             :                 vector3d<T> MinEdge;
     318             : 
     319             :                 //! The far edge
     320             :                 vector3d<T> MaxEdge;
     321             : };
     322             : 
     323             :         //! Typedef for a f32 3d bounding box.
     324             :         typedef aabbox3d<f32> aabbox3df;
     325             :         //! Typedef for an integer 3d bounding box.
     326             :         typedef aabbox3d<s32> aabbox3di;
     327             : 
     328             : } // end namespace core
     329             : } // end namespace irr
     330             : 
     331             : #endif
     332             : 

Generated by: LCOV version 1.11