LCOV - code coverage report
Current view: top level - vmmlib - frustum.hpp (source / functions) Hit Total Coverage
Test: vmmlib Lines: 68 80 85.0 %
Date: 2018-06-05 00:11:40 Functions: 16 17 94.1 %

          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             : 
      33             : #ifndef __VMML__FRUSTUM__HPP__
      34             : #define __VMML__FRUSTUM__HPP__
      35             : 
      36             : #include <cstring>           // memcmp
      37             : #include <vmmlib/matrix.hpp> // used inline
      38             : 
      39             : #if defined(_MSC_VER)
      40             :  //can otherwise cause problems with, e.g., M_PI under Windows.
      41             : #define _USE_MATH_DEFINES
      42             : #include <cmath>
      43             : #ifndef M_PI
      44             : #include <corecrt_math_defines.h>
      45             : #endif
      46             : #else
      47             : #ifndef M_PI
      48             : #define M_PI 3.1415926535897932
      49             : #endif
      50             : #endif
      51             : 
      52             : namespace vmml
      53             : {
      54             : /** Represents a frustum, following OpenGL conventions. */
      55             : template <typename T>
      56             : class Frustum
      57             : {
      58             : public:
      59             :     /** Construct a default frustum (-1, 1, -1, 1, 0.1, 100). */
      60             :     Frustum();
      61             : 
      62             :     /** Construct a frustum with default values */
      63             :     Frustum(T left, T right, T bottom, T top, T nearPlane, T farPlane);
      64             : 
      65             :     /** Construct a frustum using gluPerspective semantics */
      66             :     Frustum(T field_of_view_y, T aspect_ratio, T nearPlane_, T farPlane);
      67             : 
      68             :     /** Construct a frustum from a projection matrix */
      69             :     Frustum(const Matrix<4, 4, T>& projection);
      70             : 
      71             :     /** Destruct this frustum */
      72           4 :     ~Frustum() {}
      73             :     /** @return true if this and the other frustum are identical */
      74             :     bool operator==(const Frustum<T>& other) const;
      75             : 
      76             :     /** @return true if this and the other frustum are not identical */
      77             :     bool operator!=(const Frustum<T>& other) const;
      78             : 
      79             :     /** @return true if thw two frusta are identical withing the tolerance */
      80             :     bool equals(const Frustum<T>& other,
      81             :                 T tolerance = std::numeric_limits<T>::epsilon()) const;
      82             : 
      83             :     /** @return the perspective matrix for the given frustum. */
      84             :     Matrix<4, 4, T> computePerspectiveMatrix() const;
      85             : 
      86             :     /** @return the orthographic matrix for the given frustum. */
      87             :     Matrix<4, 4, T> computeOrthoMatrix() const;
      88             : 
      89             :     /** Move the frustum near plane by the given offset "sideways" */
      90             :     void jitter(const vector<2, T>& jitter_);
      91             : 
      92             :     /**
      93             :      * Move the frustum near plane.
      94             :      *
      95             :      * Changes the position of the nearPlane, adjusting the other parameters in
      96             :      * a way that the shape of the perspective pyramid stays the same.
      97             :      */
      98             :     void adjustNearPlane(const T nearPlane);
      99             : 
     100             :     /** @name Access to frustum corners */
     101             :     //@{
     102             :     T& left() { return _array[0]; }
     103           9 :     T left() const { return _array[0]; }
     104             :     T& right() { return _array[1]; }
     105           9 :     T right() const { return _array[1]; }
     106           1 :     T& bottom() { return _array[2]; }
     107           9 :     T bottom() const { return _array[2]; }
     108           1 :     T& top() { return _array[3]; }
     109           9 :     T top() const { return _array[3]; }
     110           4 :     T& nearPlane() { return _array[4]; }
     111          18 :     T nearPlane() const { return _array[4]; }
     112             :     T& farPlane() { return _array[5]; }
     113          12 :     T farPlane() const { return _array[5]; }
     114             :     //@}
     115             : 
     116             :     /** @return the width of this frustum at the near plane */
     117             :     T getWidth() const;
     118             : 
     119             :     /** @return the height of this frustum at the near plane */
     120             :     T getHeight() const;
     121             : 
     122           0 :     friend std::ostream& operator<<(std::ostream& os, const Frustum& f)
     123             :     {
     124           0 :         const std::ios::fmtflags flags = os.flags();
     125           0 :         const int prec = os.precision();
     126             : 
     127           0 :         os.setf(std::ios::right, std::ios::adjustfield);
     128           0 :         os.precision(5);
     129           0 :         os << "[" << std::setw(10) << f.left() << " " << std::setw(10)
     130           0 :            << f.right() << " " << std::setw(10) << f.bottom() << " "
     131           0 :            << std::setw(10) << f.top() << " " << std::setw(10) << f.nearPlane()
     132           0 :            << " " << std::setw(10) << f.farPlane() << "]";
     133           0 :         os.precision(prec);
     134           0 :         os.setf(flags);
     135           0 :         return os;
     136             :     };
     137             : 
     138             : private:
     139             :     T _array[6]; //!< left, right, bottom, top, near, far storage
     140             : };
     141             : } // namespace vmml
     142             : 
     143             : // - implementation - //
     144             : 
     145             : namespace vmml
     146             : {
     147             : template <typename T>
     148           1 : Frustum<T>::Frustum()
     149             : {
     150           1 :     _array[0] = -1;
     151           1 :     _array[1] = 1;
     152           1 :     _array[2] = -1;
     153           1 :     _array[3] = 1;
     154           1 :     _array[4] = 0.1f;
     155           1 :     _array[5] = 100;
     156           1 : }
     157             : 
     158             : template <typename T>
     159           1 : Frustum<T>::Frustum(const T _left, const T _right, const T _bottom,
     160             :                     const T _top, const T _near, const T _far)
     161             : {
     162           1 :     _array[0] = _left;
     163           1 :     _array[1] = _right;
     164           1 :     _array[2] = _bottom;
     165           1 :     _array[3] = _top;
     166           1 :     _array[4] = _near;
     167           1 :     _array[5] = _far;
     168           1 : }
     169             : 
     170             : template <typename T>
     171           1 : Frustum<T>::Frustum(const T fov_y, const T aspect_ratio, const T nearPlane_,
     172             :                     const T farPlane_)
     173             : {
     174           1 :     _array[2] = std::tan(0.5 * fov_y * M_PI / 180.0) * nearPlane_;
     175           1 :     _array[3] = -_array[2];
     176             :     // depend on _array[2,3]:
     177           1 :     _array[0] = bottom() * aspect_ratio;
     178           1 :     _array[1] = top() * aspect_ratio;
     179           1 :     _array[4] = nearPlane_;
     180           1 :     _array[5] = farPlane_;
     181           1 : }
     182             : 
     183             : template <typename T>
     184           1 : Frustum<T>::Frustum(const Matrix<4, 4, T>& projection)
     185             : {
     186           1 :     _array[4] = projection(2, 3) / (projection(2, 2) - 1.0);
     187           1 :     _array[5] = projection(2, 3) / (projection(2, 2) + 1.0);
     188           1 :     _array[2] = nearPlane() * (projection(1, 2) - 1.0) / projection(1, 1);
     189           1 :     _array[3] = nearPlane() * (projection(1, 2) + 1.0) / projection(1, 1);
     190           1 :     _array[0] = nearPlane() * (projection(0, 2) - 1.0) / projection(0, 0);
     191           1 :     _array[1] = nearPlane() * (projection(0, 2) + 1.0) / projection(0, 0);
     192           1 : }
     193             : 
     194             : template <typename T>
     195             : bool Frustum<T>::operator==(const Frustum<T>& other) const
     196             : {
     197             :     return ::memcmp(_array, other._array, sizeof(_array)) == 0;
     198             : }
     199             : 
     200             : template <typename T>
     201             : bool Frustum<T>::operator!=(const Frustum<T>& other) const
     202             : {
     203             :     return ::memcmp(_array, other._array, sizeof(_array)) != 0;
     204             : }
     205             : 
     206             : template <typename T>
     207           1 : bool Frustum<T>::equals(const Frustum<T>& other, const T tolerance) const
     208             : {
     209           2 :     return std::abs(_array[0] - other._array[0]) <= tolerance &&
     210           2 :            std::abs(_array[1] - other._array[1]) <= tolerance &&
     211           2 :            std::abs(_array[2] - other._array[2]) <= tolerance &&
     212           2 :            std::abs(_array[3] - other._array[3]) <= tolerance &&
     213           3 :            std::abs(_array[4] - other._array[4]) <= tolerance &&
     214           2 :            std::abs(_array[5] - other._array[5]) <= tolerance;
     215             : }
     216             : 
     217             : template <typename T>
     218           3 : Matrix<4, 4, T> Frustum<T>::computePerspectiveMatrix() const
     219             : {
     220           3 :     Matrix<4, 4, T> M;
     221             : 
     222           3 :     M(0, 0) = 2.0 * nearPlane() / (right() - left());
     223           3 :     M(0, 1) = 0.0;
     224           3 :     M(0, 2) = (right() + left()) / (right() - left());
     225           3 :     M(0, 3) = 0.0;
     226             : 
     227           3 :     M(1, 0) = 0.0;
     228           3 :     M(1, 1) = 2.0 * nearPlane() / (top() - bottom());
     229           3 :     M(1, 2) = (top() + bottom()) / (top() - bottom());
     230           3 :     M(1, 3) = 0.0;
     231             : 
     232           3 :     M(2, 0) = 0.0;
     233           3 :     M(2, 1) = 0.0;
     234             :     // NOTE: Some glfrustum man pages say wrongly '(far + near) / (far - near)'
     235           3 :     M(2, 2) = -(farPlane() + nearPlane()) / (farPlane() - nearPlane());
     236           3 :     M(2, 3) = -2.0 * farPlane() * nearPlane() / (farPlane() - nearPlane());
     237             : 
     238           3 :     M(3, 0) = 0.0;
     239           3 :     M(3, 1) = 0.0;
     240           3 :     M(3, 2) = -1.0;
     241           3 :     M(3, 3) = 0.0;
     242             : 
     243           3 :     return M;
     244             : }
     245             : 
     246             : template <typename T>
     247             : Matrix<4, 4, T> Frustum<T>::computeOrthoMatrix() const
     248             : {
     249             :     Matrix<4, 4, T> M;
     250             : 
     251             :     M(0, 0) = 2.0 / (right() - left());
     252             :     M(0, 1) = 0.0;
     253             :     M(0, 2) = 0.0;
     254             :     M(0, 3) = -(right() + left()) / (right() - left());
     255             : 
     256             :     M(1, 0) = 0.0;
     257             :     M(1, 1) = 2.0 / (top() - bottom());
     258             :     M(1, 2) = 0.0f;
     259             :     M(1, 3) = -(top() + bottom()) / (top() - bottom());
     260             : 
     261             :     M(2, 0) = 0.0;
     262             :     M(2, 1) = 0.0;
     263             :     M(2, 2) = -2.0 / (farPlane() - nearPlane());
     264             :     M(2, 3) = -(farPlane() + nearPlane()) / (farPlane() - nearPlane());
     265             : 
     266             :     M(3, 0) = 0.0;
     267             :     M(3, 1) = 0.0;
     268             :     M(3, 2) = 0.0;
     269             :     M(3, 3) = 1.0f;
     270             : 
     271             :     return M;
     272             : }
     273             : 
     274             : template <typename T>
     275             : void Frustum<T>::jitter(const vector<2, T>& jitter_)
     276             : {
     277             :     left() = left() + jitter_.x();
     278             :     right() = right() + jitter_.x();
     279             :     bottom() = bottom() + jitter_.y();
     280             :     top() = top() + jitter_.y();
     281             : }
     282             : 
     283             : template <typename T>
     284             : void Frustum<T>::adjustNearPlane(const T new_near)
     285             : {
     286             :     if (new_near == nearPlane())
     287             :         return;
     288             : 
     289             :     const T ratio = new_near / nearPlane();
     290             :     right() *= ratio;
     291             :     left() *= ratio;
     292             :     top() *= ratio;
     293             :     bottom() *= ratio;
     294             :     nearPlane() = new_near;
     295             : }
     296             : 
     297             : template <typename T>
     298             : inline T Frustum<T>::getWidth() const
     299             : {
     300             :     return std::abs(right() - left());
     301             : }
     302             : 
     303             : template <typename T>
     304             : inline T Frustum<T>::getHeight() const
     305             : {
     306             :     return std::abs(top() - bottom());
     307             : }
     308             : 
     309             : } // namespace vmml
     310             : 
     311             : #endif

Generated by: LCOV version 1.11