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

Generated by: LCOV version 1.11