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
|