LCOV - code coverage report
Current view: top level - vmmlib - frustum.hpp (source / functions) Hit Total Coverage
Test: vmmlib Lines: 59 59 100.0 %
Date: 2015-11-02 15:45:14 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006-2014, 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/vmmlib_config.hpp>
      37             : #include <vmmlib/matrix.hpp>
      38             : 
      39             : #include <cmath>
      40             : 
      41             : // - declaration -
      42             : 
      43             : namespace vmml
      44             : {
      45             : template< typename T > class frustum
      46             : {
      47             : public:
      48             :     T array[6]; //!< left, right, bottom, top, near, far storage
      49             : 
      50             :     // contructors
      51             :     frustum() : array() {} // http://stackoverflow.com/questions/5602030
      52             :     frustum( const T left, const T right, const T bottom, const T top,
      53             :              const T near_plane, const T far_plane );
      54             : 
      55             :     template< typename U > frustum( const frustum< U >& source_ );
      56             : 
      57             :     //the pointer 'values' must be a valid 6 component c array of the resp. type
      58             :     template< typename U > frustum( const U* values );
      59             : 
      60             :     ~frustum();
      61             : 
      62             :     frustum& operator=( const frustum& source_ );
      63             :     template< typename U >
      64             :     void operator=( const frustum< U >& source_ );
      65             : 
      66             :     void set( const T _left, const T _right, const T _bottom,
      67             :         const T _top, const T _near, const T _far );
      68             : 
      69             :     // set the frustum using the same parameters as gluPerspective.
      70             :     void set_perspective( T field_of_view_y, T aspect_ratio, T near_plane_,
      71             :         T far_plane );
      72             : 
      73             :     matrix< 4, 4, T > compute_matrix() const;
      74             :     matrix< 4, 4, T > compute_ortho_matrix() const;
      75             : 
      76             :     void compute_matrix( matrix< 4, 4, T >& matrix_ ) const;
      77             :     void compute_ortho_matrix( matrix< 4, 4, T >& matrix_ ) const;
      78             :     void apply_jitter( const vector< 2, T >& jitter_ );
      79             : 
      80             :     // 'move' the frustum. this function changes the near_plane, and adjusts the
      81             :     // other parameters in a way that the 'perspective pyramid' stays the same.
      82             :     void adjust_near( const T near_plane );
      83             : 
      84             :     inline T& left();
      85             :     inline const T& left() const;
      86             : 
      87             :     inline T& right();
      88             :     inline const T& right() const;
      89             : 
      90             :     inline T& bottom();
      91             :     inline const T& bottom() const;
      92             : 
      93             :     inline T& top();
      94             :     inline const T& top() const;
      95             : 
      96             :     inline T& near_plane();
      97             :     inline const T& near_plane() const;
      98             : 
      99             :     inline T& far_plane();
     100             :     inline const T& far_plane() const;
     101             : 
     102             :     inline T get_width() const;
     103             :     inline T get_height() const;
     104             : 
     105             :     friend std::ostream& operator << ( std::ostream& os, const frustum& f )
     106             :     {
     107             :         const std::ios::fmtflags flags = os.flags();
     108             :         const int                prec  = os.precision();
     109             : 
     110             :         os.setf( std::ios::right, std::ios::adjustfield );
     111             :         os.precision( 5 );
     112             :         os << "[" << std::setw(10) << f.left() << " "
     113             :            << std::setw(10) << f.right()  << " "
     114             :            << std::setw(10) << f.bottom() << " "
     115             :            << std::setw(10) << f.top()    << " "
     116             :            << std::setw(10) << f.near_plane()   << " "
     117             :            << std::setw(10) << f.far_plane()    << "]";
     118             :         os.precision( prec );
     119             :         os.setf( flags );
     120             :         return os;
     121             :     };
     122             : 
     123             :     static const frustum DEFAULT;
     124             : };
     125             : 
     126             : #ifndef VMMLIB_NO_TYPEDEFS
     127             : typedef frustum< float >  Frustumf;
     128             : typedef frustum< double > Frustumd;
     129             : #endif
     130             : 
     131             : } // namespace vmml
     132             : 
     133             : // - implementation - //
     134             : 
     135             : namespace vmml
     136             : {
     137             : 
     138             : template< typename T >
     139             : const frustum< T > frustum< T >::DEFAULT( static_cast< T >( -1.0 ),
     140             :                                           static_cast< T >( 1.0 ),
     141             :                                           static_cast< T >( -1.0 ),
     142             :                                           static_cast< T >( 1.0 ),
     143             :                                           static_cast< T >( 0.1 ),
     144             :                                           static_cast< T >( 100.0 ) );
     145             : 
     146             : 
     147             : template < typename T >
     148           1 : frustum<T>::frustum( const T _left, const T _right, const T _bottom,
     149             :                      const T _top, const T _near, const T _far )
     150             : {
     151           1 :     set( _left, _right, _bottom, _top, _near, _far );
     152           1 : }
     153             : 
     154             : 
     155             : template < typename T >
     156             : template< typename U >
     157             : frustum< T >::frustum( const frustum< U >& source_ )
     158             : {
     159             :     (*this) = source_;
     160             : }
     161             : 
     162             : 
     163             : 
     164             : template < typename T >
     165             : template< typename U >
     166             : frustum< T >::frustum( const U* values )
     167             : {
     168             :     assert( values &&
     169             :             "frustum: Nullpointer argument as source for initialisation!" );
     170             :     left()      = static_cast< T > ( values[0] );
     171             :     right()     = static_cast< T > ( values[1] );
     172             :     bottom()    = static_cast< T > ( values[2] );
     173             :     top()       = static_cast< T > ( values[3] );
     174             :     near_plane() = static_cast< T > ( values[4] );
     175             :     far_plane()  = static_cast< T > ( values[5] );
     176             : }
     177             : 
     178             : 
     179             : 
     180             : template < typename T >
     181           1 : frustum< T >::~frustum()
     182           1 : {}
     183             : 
     184             : 
     185             : 
     186             : template< typename T >
     187             : frustum< T >& frustum< T >::operator=( const frustum& source_ )
     188             : {
     189             :     memcpy( array, source_.array, 6 * sizeof( T ) );
     190             :     return *this;
     191             : }
     192             : 
     193             : template< typename T > template< typename U >
     194             : void frustum< T >::operator = ( const frustum< U >& source_ )
     195             : {
     196             :     for( size_t index = 0; index < 6; ++index )
     197             :     {
     198             :         array[ index ] = static_cast< T >( source_.array[ index ] );
     199             :     }
     200             : }
     201             : 
     202             : 
     203             : 
     204             : template < typename T >
     205             : void
     206           1 : frustum< T >::set( const T _left, const T _right, const T _bottom,
     207             :     const T _top, const T _near, const T _far )
     208             : {
     209           1 :     left()      = _left;
     210           1 :     right()     = _right;
     211           1 :     bottom()    = _bottom;
     212           1 :     top()       = _top;
     213           1 :     near_plane() = _near;
     214           1 :     far_plane()  = _far;
     215           1 : }
     216             : 
     217             : 
     218             : // 'move' the frustum. this function changes the near_plane, and adjusts the
     219             : // other parameters in a way that the 'perspective pyramid' stays the same.
     220             : template < typename T >
     221             : void
     222             : frustum<T>::adjust_near( const T new_near )
     223             : {
     224             :         if( new_near == near_plane() )
     225             :                 return;
     226             : 
     227             :         const T ratio = new_near / near_plane();
     228             :         right()     *= ratio;
     229             :         left()      *= ratio;
     230             :         top()       *= ratio;
     231             :         bottom()    *= ratio;
     232             :         near_plane()  = new_near;
     233             : }
     234             : 
     235             : 
     236             : 
     237             : // set the frustum using the same parameters as gluPerspective.
     238             : template < typename T >
     239             : void
     240             : frustum<T>::set_perspective( T fov_y, T aspect_ratio, T near_plane_,
     241             :     T far_plane_ )
     242             : {
     243             :     near_plane() = near_plane_;
     244             :     far_plane()   = far_plane_;
     245             : 
     246             :     top()       = tan( 0.5 * fov_y * M_PI / 180.0 ) * 0.5;
     247             :     bottom()    = - top();
     248             : 
     249             :     left()      = bottom() * aspect_ratio;
     250             :     right()     = top() * aspect_ratio;
     251             : }
     252             : 
     253             : 
     254             : 
     255             : template < typename T >
     256             : matrix< 4, 4, T >
     257           1 : frustum<T>::compute_matrix() const
     258             : {
     259           1 :     matrix< 4, 4, T > matrix_;
     260           1 :     compute_matrix( matrix_ );
     261           1 :     return matrix_;
     262             : }
     263             : 
     264             : 
     265             : 
     266             : template < typename T >
     267             : void
     268           1 : frustum<T>::compute_matrix( matrix< 4, 4, T >& M ) const
     269             : {
     270           1 :     M( 0,0 ) = 2.0 * near_plane() / ( right() - left() );
     271           1 :     M( 0,1 ) = 0.0;
     272           1 :     M( 0,2 ) = ( right() + left() ) / ( right() - left() );
     273           1 :     M( 0,3 ) = 0.0;
     274             : 
     275           1 :     M( 1,0 ) = 0.0;
     276           1 :     M( 1,1 ) = 2.0 * near_plane() / ( top() - bottom() );
     277           1 :     M( 1,2 ) = ( top() + bottom() ) / ( top() - bottom() );
     278           1 :     M( 1,3 ) = 0.0;
     279             : 
     280           1 :     M( 2,0 ) = 0.0;
     281           1 :     M( 2,1 ) = 0.0;
     282             :     // NOTE: Some glfrustum man pages say wrongly '(far + near) / (far - near)'
     283           1 :     M( 2,2 ) = -( far_plane() + near_plane() ) / ( far_plane() - near_plane() );
     284           1 :     M( 2,3 ) = -2.0 * far_plane() * near_plane() / ( far_plane() - near_plane() );
     285             : 
     286           1 :     M( 3,0 ) = 0.0;
     287           1 :     M( 3,1 ) = 0.0;
     288           1 :     M( 3,2 ) = -1.0;
     289           1 :     M( 3,3 ) =  0.0;
     290           1 : }
     291             : 
     292             : 
     293             : 
     294             : template < typename T >
     295             : matrix< 4, 4, T >
     296             : frustum< T >::compute_ortho_matrix() const
     297             : {
     298             :     matrix< 4, 4, T > matrix_;
     299             :     compute_ortho_matrix( matrix_ );
     300             :     return matrix_;
     301             : }
     302             : 
     303             : 
     304             : 
     305             : template < typename T >
     306             : void
     307             : frustum< T >::compute_ortho_matrix( matrix< 4, 4, T >& M ) const
     308             : {
     309             :     M( 0,0 ) = 2.0 / ( right() - left() );
     310             :     M( 0,1 ) = 0.0;
     311             :     M( 0,2 ) = 0.0;
     312             :     M( 0,3 ) = -( right() + left() ) / ( right() - left() );
     313             : 
     314             :     M( 1,0 ) = 0.0;
     315             :     M( 1,1 ) = 2.0 / ( top() - bottom() );
     316             :     M( 1,2 ) = 0.0f;
     317             :     M( 1,3 ) = -( top() + bottom() ) / ( top() - bottom() );
     318             : 
     319             :     M( 2,0 ) = 0.0;
     320             :     M( 2,1 ) = 0.0;
     321             :     M( 2,2 ) = -2.0 / ( far_plane() - near_plane() );
     322             :     M( 2,3 ) = -( far_plane() + near_plane() ) / ( far_plane() - near_plane() );
     323             : 
     324             :     M( 3,0 ) = 0.0;
     325             :     M( 3,1 ) = 0.0;
     326             :     M( 3,2 ) = 0.0;
     327             :     M( 3,3 ) = 1.0f;
     328             : }
     329             : 
     330             : template < typename T >
     331             : void frustum< T >::apply_jitter( const vector< 2, T >& jitter_ )
     332             : {
     333             :     left()   = left() + jitter_.x();
     334             :     right()  = right() + jitter_.x();
     335             :     bottom() = bottom() + jitter_.y();
     336             :     top()    = top() + jitter_.y();
     337             : }
     338             : 
     339             : template< typename T >
     340           1 : inline T& frustum< T >::left()
     341             : {
     342           1 :     return array[ 0 ];
     343             : }
     344             : 
     345             : template< typename T >
     346           3 : inline const T& frustum< T >::left() const
     347             : {
     348           3 :     return array[ 0 ];
     349             : }
     350             : 
     351             : template< typename T >
     352           1 : inline T& frustum< T >::right()
     353             : {
     354           1 :     return array[ 1 ];
     355             : }
     356             : 
     357             : template< typename T >
     358           3 : inline const T& frustum< T >::right() const
     359             : {
     360           3 :     return array[ 1 ];
     361             : }
     362             : 
     363             : template< typename T >
     364           1 : inline T& frustum< T >::bottom()
     365             : {
     366           1 :     return array[ 2 ];
     367             : }
     368             : 
     369             : template< typename T >
     370           3 : inline const T& frustum< T >::bottom() const
     371             : {
     372           3 :     return array[ 2 ];
     373             : }
     374             : 
     375             : template< typename T >
     376           1 : inline T& frustum< T >::top()
     377             : {
     378           1 :     return array[ 3 ];
     379             : }
     380             : 
     381             : template< typename T >
     382           3 : inline const T& frustum< T >::top() const
     383             : {
     384           3 :     return array[ 3 ];
     385             : }
     386             : 
     387             : template< typename T >
     388           1 : inline T& frustum< T >::near_plane()
     389             : {
     390           1 :     return array[ 4 ];
     391             : }
     392             : 
     393             : template< typename T >
     394           6 : inline const T& frustum< T >::near_plane() const
     395             : {
     396           6 :     return array[ 4 ];
     397             : }
     398             : 
     399             : template< typename T >
     400           1 : inline T& frustum< T >::far_plane()
     401             : {
     402           1 :     return array[ 5 ];
     403             : }
     404             : 
     405             : template< typename T >
     406           4 : inline const T& frustum< T >::far_plane() const
     407             : {
     408           4 :     return array[ 5 ];
     409             : }
     410             : 
     411             : template< typename T > inline T frustum< T >::get_width() const
     412             : {
     413             :     return fabs( right() - left( ));
     414             : }
     415             : 
     416             : template< typename T > inline T frustum< T >::get_height() const
     417             : {
     418             :     return fabs( top() - bottom( ));
     419             : }
     420             : 
     421             : 
     422             : } //namespace vmml
     423             : 
     424             : #endif

Generated by: LCOV version 1.11