33 #ifndef __VMML__FRUSTUMCULLER__HPP__
34 #define __VMML__FRUSTUMCULLER__HPP__
36 #include <vmmlib/aabb.hpp>
37 #include <vmmlib/matrix.hpp>
38 #include <vmmlib/vector.hpp>
39 #include <vmmlib/visibility.hpp>
65 const vec3& nlb,
const vec3& nrb,
66 const vec3& flt,
const vec3& frt,
67 const vec3& flb,
const vec3& frb );
73 Visibility
test(
const vec4& sphere )
const;
81 friend std::ostream& operator << (std::ostream& os,
const FrustumCuller& f)
83 return os <<
"Frustum cull planes: " << std::endl
84 <<
" left " << f._leftPlane << std::endl
85 <<
" right " << f._rightPlane << std::endl
86 <<
" top " << f._topPlane << std::endl
87 <<
" bottom " << f._bottomPlane << std::endl
88 <<
" near " << f._nearPlane << std::endl
89 <<
" far " << f._farPlane << std::endl;
93 inline void _normalizePlane( vec4& plane )
const;
94 inline Visibility _test(
const vec4& plane,
const vec3& middle,
95 const vec3& size_2 )
const;
116 template <
typename T >
120 const vec4& row0 = projModelView.getRow( 0 );
121 const vec4& row1 = projModelView.getRow( 1 );
122 const vec4& row2 = projModelView.getRow( 2 );
123 const vec4& row3 = projModelView.getRow( 3 );
125 _leftPlane = row3 + row0;
126 _rightPlane = row3 - row0;
127 _bottomPlane = row3 + row1;
128 _topPlane = row3 - row1;
129 _nearPlane = row3 + row2;
130 _farPlane = row3 - row2;
132 _normalizePlane( _leftPlane );
133 _normalizePlane( _rightPlane );
134 _normalizePlane( _bottomPlane );
135 _normalizePlane( _topPlane );
136 _normalizePlane( _nearPlane );
137 _normalizePlane( _farPlane );
140 template <
typename T >
152 _leftPlane = compute_plane( c, a, e );
153 _rightPlane = compute_plane( f, b, d );
154 _bottomPlane = compute_plane( h, d, c );
155 _topPlane = compute_plane( a, b, f );
156 _nearPlane = compute_plane( b, a, c );
157 _farPlane = compute_plane( g, e, f );
160 template <
typename T >
164 const vec3& v3 = plane.template get_sub_vector< 3, 0 >();
165 const T len_i = 1.0 / v3.length();
173 template <
typename T > Visibility
176 Visibility visibility = VISIBILITY_FULL;
185 T distance = _leftPlane.x() * sphere.x() + _leftPlane.y() * sphere.y() +
186 _leftPlane.z() * sphere.z() + _leftPlane.w();
187 if( distance <= -sphere.w() )
188 return VISIBILITY_NONE;
189 if( distance < sphere.w() )
190 visibility = VISIBILITY_PARTIAL;
192 distance = _rightPlane.x() * sphere.x() + _rightPlane.y() * sphere.y() +
193 _rightPlane.z() * sphere.z() + _rightPlane.w();
194 if( distance <= -sphere.w() )
195 return VISIBILITY_NONE;
196 if( distance < sphere.w() )
197 visibility = VISIBILITY_PARTIAL;
199 distance = _bottomPlane.x() * sphere.x() + _bottomPlane.y() * sphere.y() +
200 _bottomPlane.z() * sphere.z() + _bottomPlane.w();
201 if( distance <= -sphere.w() )
202 return VISIBILITY_NONE;
203 if( distance < sphere.w() )
204 visibility = VISIBILITY_PARTIAL;
206 distance = _topPlane.x() * sphere.x() + _topPlane.y() * sphere.y() +
207 _topPlane.z() * sphere.z() + _topPlane.w();
208 if( distance <= -sphere.w() )
209 return VISIBILITY_NONE;
210 if( distance < sphere.w() )
211 visibility = VISIBILITY_PARTIAL;
213 distance = _nearPlane.x() * sphere.x() + _nearPlane.y() * sphere.y() +
214 _nearPlane.z() * sphere.z() + _nearPlane.w();
216 if( distance <= -sphere.w() )
217 return VISIBILITY_NONE;
218 if( distance < sphere.w() )
219 visibility = VISIBILITY_PARTIAL;
221 distance = _farPlane.x() * sphere.x() + _farPlane.y() * sphere.y() +
222 _farPlane.z() * sphere.z() + _farPlane.w();
223 if( distance <= -sphere.w() )
224 return VISIBILITY_NONE;
225 if( distance < sphere.w() )
226 visibility = VISIBILITY_PARTIAL;
231 template <
typename T >
233 const vec3& extent )
const
236 const T d = plane.dot( middle );
237 const T n = extent.x() * fabs( plane.x( )) +
238 extent.y() * fabs( plane.y( )) +
239 extent.z() * fabs( plane.z( ));
242 return VISIBILITY_FULL;
244 return VISIBILITY_PARTIAL;
245 return VISIBILITY_NONE;
248 template <
typename T >
251 Visibility result = VISIBILITY_FULL;
254 switch( _test( _leftPlane, middle, extent ))
256 case VISIBILITY_FULL:
break;
257 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
258 case VISIBILITY_NONE:
return VISIBILITY_NONE;
261 switch( _test( _rightPlane, middle, extent ))
263 case VISIBILITY_FULL:
break;
264 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
265 case VISIBILITY_NONE:
return VISIBILITY_NONE;
268 switch( _test( _bottomPlane, middle, extent ))
270 case VISIBILITY_FULL:
break;
271 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
272 case VISIBILITY_NONE:
return VISIBILITY_NONE;
275 switch( _test( _topPlane, middle, extent ))
277 case VISIBILITY_FULL:
break;
278 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
279 case VISIBILITY_NONE:
return VISIBILITY_NONE;
282 switch( _test( _nearPlane, middle, extent ))
284 case VISIBILITY_FULL:
break;
285 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
286 case VISIBILITY_NONE:
return VISIBILITY_NONE;
289 switch( _test( _farPlane, middle, extent ))
291 case VISIBILITY_FULL:
break;
292 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
293 case VISIBILITY_NONE:
return VISIBILITY_NONE;
301 #endif // include protection
Helper class to perform OpenGL view frustum culling.
vector< 3, T > getSize() const
FrustumCuller()
Construct a new frustum culler.
const vec4 & getNearPlane() const
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
An axis-aligned bounding box.
Visibility test(const vec4 &sphere) const
~FrustumCuller()
Destruct this frustum culler.
vector< 3, T > getCenter() const
Matrix with R rows and C columns of element type T.