vmmlib  1.11.0
Templatized C++ vector and matrix math library
frustum.hpp
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 {
42 template< typename T > class Frustum
43 {
44 public:
46  Frustum();
47 
49  Frustum( T left, T right, T bottom, T top, T nearPlane, T farPlane );
50 
52  Frustum( T field_of_view_y, T aspect_ratio, T nearPlane_, T farPlane );
53 
55  Frustum( const Matrix< 4, 4, T >& projection );
56 
58  ~Frustum() {}
59 
61  bool operator==( const Frustum< T >& other ) const;
62 
64  bool operator!=( const Frustum< T >& other ) const;
65 
67  bool equals( const Frustum< T >& other,
68  T tolerance = std::numeric_limits< T >::epsilon( )) const;
69 
72 
75 
77  void jitter( const vector< 2, T >& jitter_ );
78 
85  void adjustNearPlane( const T nearPlane );
86 
89  T& left() { return _array[0]; }
90  T left() const { return _array[0]; }
91 
92  T& right() { return _array[1]; }
93  T right() const { return _array[1]; }
94 
95  T& bottom() { return _array[2]; }
96  T bottom() const { return _array[2]; }
97 
98  T& top() { return _array[3]; }
99  T top() const { return _array[3]; }
100 
101  T& nearPlane() { return _array[4]; }
102  T nearPlane() const { return _array[4]; }
103 
104  T& farPlane() { return _array[5]; }
105  T farPlane() const { return _array[5]; }
107 
109  T getWidth() const;
110 
112  T getHeight() const;
113 
114  friend std::ostream& operator << ( std::ostream& os, const Frustum& f )
115  {
116  const std::ios::fmtflags flags = os.flags();
117  const int prec = os.precision();
118 
119  os.setf( std::ios::right, std::ios::adjustfield );
120  os.precision( 5 );
121  os << "[" << std::setw(10) << f.left() << " "
122  << std::setw(10) << f.right() << " "
123  << std::setw(10) << f.bottom() << " "
124  << std::setw(10) << f.top() << " "
125  << std::setw(10) << f.nearPlane() << " "
126  << std::setw(10) << f.farPlane() << "]";
127  os.precision( prec );
128  os.setf( flags );
129  return os;
130  };
131 
132 private:
133  T _array[6];
134 };
135 } // namespace vmml
136 
137 // - implementation - //
138 
139 namespace vmml
140 {
141 
142 template< typename T > Frustum< T >::Frustum()
143 {
144  _array[0] = -1;
145  _array[1] = 1;
146  _array[2] = -1;
147  _array[3] = 1;
148  _array[4] = 0.1f;
149  _array[5] = 100;
150 }
151 
152 template < typename T >
153 Frustum<T>::Frustum( const T _left, const T _right, const T _bottom,
154  const T _top, const T _near, const T _far )
155 {
156  _array[0] = _left;
157  _array[1] = _right;
158  _array[2] = _bottom;
159  _array[3] = _top;
160  _array[4] = _near;
161  _array[5] = _far;
162 }
163 
164 template < typename T >
165 Frustum<T>::Frustum( const T fov_y, const T aspect_ratio, const T nearPlane_,
166  const T farPlane_ )
167 {
168  _array[2] = std::tan( 0.5 * fov_y * M_PI / 180.0 ) * 0.5;
169  _array[3] = -_array[2];
170  // depend on _array[2,3]:
171  _array[0] = bottom() * aspect_ratio;
172  _array[1] = top() * aspect_ratio;
173  _array[4] = nearPlane_;
174  _array[5] = farPlane_;
175 }
176 
177 template < typename T >
179 {
180  _array[4] = projection( 2, 3 ) / (projection( 2, 2 ) - 1.0);
181  _array[5] = projection( 2, 3 ) / (projection( 2, 2 ) + 1.0);
182  _array[2] = nearPlane() * ( projection( 1, 2 ) - 1.0 ) / projection( 1, 1 );
183  _array[3] = nearPlane() * ( projection( 1, 2 ) + 1.0 ) / projection( 1, 1 );
184  _array[0] = nearPlane() * ( projection( 0, 2 ) - 1.0 ) / projection( 0, 0 );
185  _array[1] = nearPlane() * ( projection( 0, 2 ) + 1.0 ) / projection( 0, 0 );
186 }
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 bool Frustum<T>::equals( const Frustum< T >& other, const T tolerance ) const
202 {
203  return std::abs( _array[0] - other._array[0] ) <= tolerance &&
204  std::abs( _array[1] - other._array[1] ) <= tolerance &&
205  std::abs( _array[2] - other._array[2] ) <= tolerance &&
206  std::abs( _array[3] - other._array[3] ) <= tolerance &&
207  std::abs( _array[4] - other._array[4] ) <= tolerance &&
208  std::abs( _array[5] - other._array[5] ) <= tolerance;
209 }
210 
211 template < typename T >
213 {
215 
216  M( 0,0 ) = 2.0 * nearPlane() / ( right() - left() );
217  M( 0,1 ) = 0.0;
218  M( 0,2 ) = ( right() + left() ) / ( right() - left() );
219  M( 0,3 ) = 0.0;
220 
221  M( 1,0 ) = 0.0;
222  M( 1,1 ) = 2.0 * nearPlane() / ( top() - bottom() );
223  M( 1,2 ) = ( top() + bottom() ) / ( top() - bottom() );
224  M( 1,3 ) = 0.0;
225 
226  M( 2,0 ) = 0.0;
227  M( 2,1 ) = 0.0;
228  // NOTE: Some glfrustum man pages say wrongly '(far + near) / (far - near)'
229  M( 2,2 ) = -( farPlane() + nearPlane() ) / ( farPlane() - nearPlane( ));
230  M( 2,3 ) = -2.0 * farPlane() * nearPlane() / (farPlane() - nearPlane());
231 
232  M( 3,0 ) = 0.0;
233  M( 3,1 ) = 0.0;
234  M( 3,2 ) = -1.0;
235  M( 3,3 ) = 0.0;
236 
237  return M;
238 }
239 
240 template < typename T >
242 {
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
Represents a frustum, following OpenGL conventions.
Definition: frustum.hpp:42
bool operator==(const Frustum< T > &other) const
Definition: frustum.hpp:189
T getWidth() const
Definition: frustum.hpp:290
Frustum()
Construct a default frustum (-1, 1, -1, 1, 0.1, 100).
Definition: frustum.hpp:142
bool operator!=(const Frustum< T > &other) const
Definition: frustum.hpp:195
Matrix< 4, 4, T > computePerspectiveMatrix() const
Definition: frustum.hpp:212
Matrix< 4, 4, T > computeOrthoMatrix() const
Definition: frustum.hpp:241
void adjustNearPlane(const T nearPlane)
Move the frustum near plane.
Definition: frustum.hpp:277
heavily inspired by boost::enable_if http://www.boost.org, file: boost/utility/enable_if.hpp, Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine
Definition: aabb.hpp:40
~Frustum()
Destruct this frustum.
Definition: frustum.hpp:58
bool equals(const Frustum< T > &other, T tolerance=std::numeric_limits< T >::epsilon()) const
Definition: frustum.hpp:201
void jitter(const vector< 2, T > &jitter_)
Move the frustum near plane by the given offset "sideways".
Definition: frustum.hpp:269
Matrix with R rows and C columns of element type T.
Definition: matrix.hpp:51
T getHeight() const
Definition: frustum.hpp:295