LCOV - code coverage report
Current view: top level - vmmlib - aabb.hpp (source / functions) Hit Total Coverage
Test: vmmlib Lines: 58 63 92.1 %
Date: 2018-06-05 00:11:40 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006-2016, Visualization and Multimedia Lab,
       3             :  *                          University of Zurich <http://vmml.ifi.uzh.ch>,
       4             :  *                          Eyescale Software GmbH,
       5             :  *                          Blue Brain Project, EPFL
       6             :  *
       7             :  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
       8             :  *
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions are met:
      11             :  *
      12             :  * Redistributions of source code must retain the above copyright notice, this
      13             :  * list of conditions and the following disclaimer.  Redistributions in binary
      14             :  * form must reproduce the above copyright notice, this list of conditions and
      15             :  * the following disclaimer in the documentation and/or other materials provided
      16             :  * with the distribution.  Neither the name of the Visualization and Multimedia
      17             :  * Lab, University of Zurich nor the names of its contributors may be used to
      18             :  * endorse or promote products derived from this software without specific prior
      19             :  * written permission.
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      21             :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      24             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30             :  * POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : #ifndef __VMML__AXIS_ALIGNED_BOUNDING_BOX__HPP__
      33             : #define __VMML__AXIS_ALIGNED_BOUNDING_BOX__HPP__
      34             : 
      35             : #include <limits>
      36             : #include <vmmlib/vector.hpp>
      37             : 
      38             : namespace lunchbox
      39             : {
      40             : template <class T>
      41             : void byteswap(T&);
      42             : }
      43             : 
      44             : namespace vmml
      45             : {
      46             : template <typename T>
      47             : class AABB;
      48             : }
      49             : namespace staticjson
      50             : {
      51             : class ObjectHandler;
      52             : template <typename U>
      53             : void init(vmml::AABB<U>*, ObjectHandler*);
      54             : }
      55             : 
      56             : namespace vmml
      57             : {
      58             : /**
      59             :  * An axis-aligned bounding box.
      60             :  *
      61             :  * An empty bounding box has undefined, implementation-specific values. Read
      62             :  * operations (getMin(), getMax(), getSize(), isIn(), etc.) have undefined
      63             :  * semantics on an empty bounding box. set() and merge() operations will define
      64             :  * the bounding box correctly.
      65             :  */
      66             : template <typename T>
      67             : class AABB
      68             : {
      69             : public:
      70             :     /** Create an empty bounding box. */
      71             :     AABB();
      72             : 
      73             :     /** Create a new bounding box from two corner points */
      74             :     AABB(const vector<3, T>& pMin, const vector<3, T>& pMax);
      75             : 
      76             :     /** Create a new bounding box from a bounding sphere */
      77             :     AABB(const vector<4, T>& sphere);
      78             : 
      79             :     /** @return true if the given point is within this bounding box. */
      80             :     bool isIn(const vector<3, T>& point) const;
      81             : 
      82             :     /** @return true if the given sphere is within this bounding box. */
      83             :     bool isIn(const vector<4, T>& sphere) const;
      84             : 
      85             :     /**
      86             :      * @return true if this bounding box is in front of the given plane
      87             :      *         ([normal.x|y|z, d] notation).
      88             :      */
      89             :     bool isInFront(const vector<4, T>& plane) const;
      90             : 
      91             :     /** @return the minimum corner point */
      92             :     const vector<3, T>& getMin() const;
      93             : 
      94             :     /** @return the maximum corner point */
      95             :     const vector<3, T>& getMax() const;
      96             : 
      97             :     /** Create the union of this and the given bounding box */
      98             :     void merge(const AABB<T>& aabb);
      99             : 
     100             :     /** Create the union of this and the given point */
     101             :     void merge(const vector<3, T>& point);
     102             : 
     103             :     /** Clear this bounding box */
     104             :     void reset();
     105             : 
     106             :     /** @return true if this bounding box has not been set */
     107             :     bool isEmpty() const;
     108             : 
     109             :     /** @return true if this and the other bounding box are identical */
     110             :     bool operator==(const AABB<T>& other) const;
     111             : 
     112             :     /** @return true if this and the other bounding box are not identical */
     113             :     bool operator!=(const AABB<T>& other) const;
     114             : 
     115             :     /** @return the center of this bounding box */
     116             :     vector<3, T> getCenter() const;
     117             : 
     118             :     /** @return the size of this bounding box */
     119             :     vector<3, T> getSize() const;
     120             : 
     121             :     /**
     122             :      * Compute the nearest and furthest point of this box relative to the given
     123             :      * plane.
     124             :      */
     125             :     void computeNearFar(const vector<4, T>& plane, vector<3, T>& nearPoint,
     126             :                         vector<3, T>& farPoint) const;
     127             : 
     128             :     /** @return a bounding box of size one with the minimum point at zero. */
     129             :     static AABB<T> makeUnitBox();
     130             : 
     131             : #ifdef __INTEL_COMPILER
     132             :     // For some reason, ICC does not understand the friend declarations and
     133             :     // generates compilation issues. Making the attributes public is not great
     134             :     // but it still is consistent with the rest of the vmmlib library (Vectors
     135             :     // and Quaternions also expose public class members)
     136             : public:
     137             :     vector<3, T> _min;
     138             :     vector<3, T> _max;
     139             : #else
     140             : private:
     141             :     vector<3, T> _min;
     142             :     vector<3, T> _max;
     143             :     template <class U>
     144             :     friend void lunchbox::byteswap(U&);
     145             :     friend void staticjson::init(AABB<float>*, staticjson::ObjectHandler*);
     146             :     friend void staticjson::init(AABB<double>*, staticjson::ObjectHandler*);
     147             : #endif
     148             : };
     149             : 
     150             : template <typename T>
     151           0 : inline std::ostream& operator<<(std::ostream& os, const AABB<T>& aabb)
     152             : {
     153           0 :     return os << aabb.getMin() << " - " << aabb.getMax();
     154             : }
     155             : 
     156             : template <typename T>
     157             : AABB<T>::AABB()
     158             :     : _min(std::numeric_limits<T>::max())
     159             :     , _max(std::numeric_limits<T>::min())
     160             : {
     161             : }
     162             : 
     163             : template <>
     164           1 : inline AABB<float>::AABB()
     165           2 :     : _min(std::numeric_limits<float>::max())
     166           2 :     , _max(-std::numeric_limits<float>::max())
     167             : {
     168           1 : }
     169             : 
     170             : template <>
     171             : inline AABB<double>::AABB()
     172             :     : _min(std::numeric_limits<double>::max())
     173             :     , _max(-std::numeric_limits<double>::max())
     174             : {
     175             : }
     176             : 
     177             : template <typename T>
     178           9 : AABB<T>::AABB(const vector<3, T>& pMin, const vector<3, T>& pMax)
     179          18 :     : _min(vector<3, T>(std::min(pMin[0], pMax[0]), std::min(pMin[1], pMax[1]),
     180           9 :                         std::min(pMin[2], pMax[2])))
     181          18 :     , _max(vector<3, T>(std::max(pMin[0], pMax[0]), std::max(pMin[1], pMax[1]),
     182          45 :                         std::max(pMin[2], pMax[2])))
     183             : {
     184           9 : }
     185             : 
     186             : template <typename T>
     187             : AABB<T>::AABB(const vector<4, T>& sphere)
     188             : {
     189             :     _max = _min = sphere.getCenter();
     190             :     _max += sphere.getRadius();
     191             :     _min -= sphere.getRadius();
     192             : }
     193             : 
     194             : template <typename T>
     195             : inline bool AABB<T>::isIn(const vector<3, T>& pos) const
     196             : {
     197             :     if (pos.x() > _max.x() || pos.y() > _max.y() || pos.z() > _max.z() ||
     198             :         pos.x() < _min.x() || pos.y() < _min.y() || pos.z() < _min.z())
     199             :     {
     200             :         return false;
     201             :     }
     202             :     return true;
     203             : }
     204             : 
     205             : template <typename T>
     206             : inline bool AABB<T>::isIn(const vector<4, T>& sphere) const
     207             : {
     208             :     const vector<3, T>& sv = sphere.getCenter();
     209             :     sv += sphere.getRadius();
     210             :     if (sv.x() > _max.x() || sv.y() > _max.y() || sv.z() > _max.z())
     211             :         return false;
     212             :     sv -= sphere.getRadius() * 2.0f;
     213             :     if (sv.x() < _min.x() || sv.y() < _min.y() || sv.z() < _min.z())
     214             :         return false;
     215             :     return true;
     216             : }
     217             : 
     218             : template <typename T>
     219           6 : inline bool AABB<T>::isInFront(const vector<4, T>& plane) const
     220             : {
     221           6 :     const auto& extent = getSize() * 0.5f;
     222           6 :     const float d = plane.dot(getCenter());
     223          12 :     const float n = extent.x() * std::abs(plane.x()) +
     224           6 :                     extent.y() * std::abs(plane.y()) +
     225           6 :                     extent.z() * std::abs(plane.z());
     226             : 
     227           6 :     return !(d - n >= 0 || d + n > 0);
     228             : }
     229             : 
     230             : template <typename T>
     231           4 : inline const vector<3, T>& AABB<T>::getMin() const
     232             : {
     233           4 :     return _min;
     234             : }
     235             : 
     236             : template <typename T>
     237           4 : inline const vector<3, T>& AABB<T>::getMax() const
     238             : {
     239           4 :     return _max;
     240             : }
     241             : 
     242             : template <typename T>
     243           1 : inline bool AABB<T>::operator==(const AABB<T>& other) const
     244             : {
     245           1 :     return _min == other._min && _max == other._max;
     246             : }
     247             : 
     248             : template <typename T>
     249             : inline bool AABB<T>::operator!=(const AABB<T>& other) const
     250             : {
     251             :     return _min != other._min || _max != other._max;
     252             : }
     253             : 
     254             : template <typename T>
     255          13 : vector<3, T> AABB<T>::getCenter() const
     256             : {
     257          13 :     return (_min + _max) * 0.5f;
     258             : }
     259             : 
     260             : template <typename T>
     261          15 : vector<3, T> AABB<T>::getSize() const
     262             : {
     263          15 :     return _max - _min;
     264             : }
     265             : 
     266             : template <typename T>
     267           1 : void AABB<T>::merge(const AABB<T>& aabb)
     268             : {
     269           1 :     const vector<3, T>& min = aabb.getMin();
     270           1 :     const vector<3, T>& max = aabb.getMax();
     271             : 
     272           1 :     if (min.x() < _min.x())
     273           1 :         _min.x() = min.x();
     274           1 :     if (min.y() < _min.y())
     275           1 :         _min.y() = min.y();
     276           1 :     if (min.z() < _min.z())
     277           1 :         _min.z() = min.z();
     278             : 
     279           1 :     if (max.x() > _max.x())
     280           0 :         _max.x() = max.x();
     281           1 :     if (max.y() > _max.y())
     282           0 :         _max.y() = max.y();
     283           1 :     if (max.z() > _max.z())
     284           0 :         _max.z() = max.z();
     285           1 : }
     286             : 
     287             : template <typename T>
     288           2 : void AABB<T>::merge(const vector<3, T>& point)
     289             : {
     290           2 :     if (point.x() < _min.x())
     291           1 :         _min.x() = point.x();
     292           2 :     if (point.y() < _min.y())
     293           1 :         _min.y() = point.y();
     294           2 :     if (point.z() < _min.z())
     295           1 :         _min.z() = point.z();
     296             : 
     297           2 :     if (point.x() > _max.x())
     298           2 :         _max.x() = point.x();
     299           2 :     if (point.y() > _max.y())
     300           2 :         _max.y() = point.y();
     301           2 :     if (point.z() > _max.z())
     302           2 :         _max.z() = point.z();
     303           2 : }
     304             : 
     305             : template <typename T>
     306             : inline void AABB<T>::reset()
     307             : {
     308             :     _min = std::numeric_limits<T>::max();
     309             :     _max = -std::numeric_limits<T>::max();
     310             : }
     311             : 
     312             : template <typename T>
     313           4 : inline bool AABB<T>::isEmpty() const
     314             : {
     315           4 :     return _min.x() >= _max.x() || _min.y() >= _max.y() || _min.z() >= _max.x();
     316             : }
     317             : 
     318             : template <typename T>
     319             : inline void AABB<T>::computeNearFar(const vector<4, T>& plane,
     320             :                                     vector<3, T>& nearPoint,
     321             :                                     vector<3, T>& farPoint) const
     322             : {
     323             :     for (size_t i = 0; i < 3; ++i)
     324             :     {
     325             :         if (plane[i] >= 0.0)
     326             :         {
     327             :             nearPoint[i] = _min[i];
     328             :             farPoint[i] = _max[i];
     329             :         }
     330             :         else
     331             :         {
     332             :             nearPoint[i] = _max[i];
     333             :             farPoint[i] = _min[i];
     334             :         }
     335             :     }
     336             : }
     337             : 
     338             : template <typename T>
     339           2 : AABB<T> AABB<T>::makeUnitBox()
     340             : {
     341           2 :     return AABB(vector<3, T>(), vector<3, T>(1));
     342             : }
     343             : }
     344             : 
     345             : #endif

Generated by: LCOV version 1.11