33 #ifndef __VMML__FRUSTUM_CULLER__HPP__
34 #define __VMML__FRUSTUM_CULLER__HPP__
36 #include <vmmlib/vector.hpp>
37 #include <vmmlib/matrix.hpp>
38 #include <vmmlib/visibility.hpp>
65 void setup(
const vec3& nlt,
const vec3& nrt,
66 const vec3& nlb,
const vec3& nrb,
67 const vec3& flt,
const vec3& frt,
68 const vec3& flb,
const vec3& frb );
70 Visibility test_sphere(
const vec4& sphere )
const;
71 Visibility test_aabb(
const vec2& x,
const vec2& y,
const vec2& z )
const;
73 friend std::ostream& operator << (std::ostream& os,
const frustum_culler& f)
75 return os <<
"Frustum cull planes: " << std::endl
76 <<
" left " << f._left_plane << std::endl
77 <<
" right " << f._right_plane << std::endl
78 <<
" top " << f._top_plane << std::endl
79 <<
" bottom " << f._bottom_plane << std::endl
80 <<
" near " << f._near_plane << std::endl
81 <<
" far " << f._far_plane << std::endl;
85 inline void _normalize_plane( vec4& plane )
const;
86 inline Visibility _test_aabb(
const vec4& plane,
const vec3& middle,
87 const vec3& size_2 )
const;
99 #ifndef VMMLIB_NO_TYPEDEFS
123 const vec4& row0 = proj_modelview.get_row( 0 );
124 const vec4& row1 = proj_modelview.get_row( 1 );
125 const vec4& row2 = proj_modelview.get_row( 2 );
126 const vec4& row3 = proj_modelview.get_row( 3 );
128 _left_plane = row3 + row0;
129 _right_plane = row3 - row0;
130 _bottom_plane = row3 + row1;
131 _top_plane = row3 - row1;
132 _near_plane = row3 + row2;
133 _far_plane = row3 - row2;
135 _normalize_plane( _left_plane );
136 _normalize_plane( _right_plane );
137 _normalize_plane( _bottom_plane );
138 _normalize_plane( _top_plane );
139 _normalize_plane( _near_plane );
140 _normalize_plane( _far_plane );
155 _left_plane = compute_plane( c, a, e );
156 _right_plane = compute_plane( f, b, d );
157 _bottom_plane = compute_plane( h, d, c );
158 _top_plane = compute_plane( a, b, f );
159 _near_plane = compute_plane( b, a, c );
160 _far_plane = compute_plane( g, e, f );
167 const vec3& v3 = plane.template get_sub_vector< 3 >();
168 const T len_i = 1.0 / v3.length();
176 template <
class T > Visibility
177 frustum_culler< T >::test_sphere(
const vector< 4, T >& sphere )
const
179 Visibility visibility = VISIBILITY_FULL;
188 T distance = _left_plane.x() * sphere.x() + _left_plane.y() * sphere.y() +
189 _left_plane.z() * sphere.z() + _left_plane.w();
190 if( distance <= -sphere.w() )
191 return VISIBILITY_NONE;
192 if( distance < sphere.w() )
193 visibility = VISIBILITY_PARTIAL;
195 distance = _right_plane.x() * sphere.x() + _right_plane.y() * sphere.y() +
196 _right_plane.z() * sphere.z() + _right_plane.w();
197 if( distance <= -sphere.w() )
198 return VISIBILITY_NONE;
199 if( distance < sphere.w() )
200 visibility = VISIBILITY_PARTIAL;
202 distance = _bottom_plane.x() * sphere.x() + _bottom_plane.y() * sphere.y() +
203 _bottom_plane.z() * sphere.z() + _bottom_plane.w();
204 if( distance <= -sphere.w() )
205 return VISIBILITY_NONE;
206 if( distance < sphere.w() )
207 visibility = VISIBILITY_PARTIAL;
209 distance = _top_plane.x() * sphere.x() + _top_plane.y() * sphere.y() +
210 _top_plane.z() * sphere.z() + _top_plane.w();
211 if( distance <= -sphere.w() )
212 return VISIBILITY_NONE;
213 if( distance < sphere.w() )
214 visibility = VISIBILITY_PARTIAL;
216 distance = _near_plane.x() * sphere.x() + _near_plane.y() * sphere.y() +
217 _near_plane.z() * sphere.z() + _near_plane.w();
219 if( distance <= -sphere.w() )
220 return VISIBILITY_NONE;
221 if( distance < sphere.w() )
222 visibility = VISIBILITY_PARTIAL;
224 distance = _far_plane.x() * sphere.x() + _far_plane.y() * sphere.y() +
225 _far_plane.z() * sphere.z() + _far_plane.w();
226 if( distance <= -sphere.w() )
227 return VISIBILITY_NONE;
228 if( distance < sphere.w() )
229 visibility = VISIBILITY_PARTIAL;
235 Visibility frustum_culler< T >::_test_aabb(
const vec4& plane,
237 const vec3& extent )
const
240 const T d = plane.dot( middle );
241 const T n = extent.x() * fabs( plane.x( )) +
242 extent.y() * fabs( plane.y( )) +
243 extent.z() * fabs( plane.z( ));
246 return VISIBILITY_FULL;
248 return VISIBILITY_PARTIAL;
249 return VISIBILITY_NONE;
253 Visibility frustum_culler< T >::test_aabb(
const vec2& x,
const vec2& y,
254 const vec2& z )
const
256 Visibility result = VISIBILITY_FULL;
257 const vec3& middle = vec3( x[0] + x[1], y[0] + y[1], z[0] + z[1] ) * .5;
258 const vec3& extent = vec3( fabs(x[1] - x[0]), fabs(y[1] - y[0]),
259 fabs(z[1] - z[0]) ) * .5;
260 switch( _test_aabb( _left_plane, middle, extent ))
262 case VISIBILITY_FULL:
break;
263 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
264 case VISIBILITY_NONE:
return VISIBILITY_NONE;
267 switch( _test_aabb( _right_plane, middle, extent ))
269 case VISIBILITY_FULL:
break;
270 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
271 case VISIBILITY_NONE:
return VISIBILITY_NONE;
274 switch( _test_aabb( _bottom_plane, middle, extent ))
276 case VISIBILITY_FULL:
break;
277 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
278 case VISIBILITY_NONE:
return VISIBILITY_NONE;
281 switch( _test_aabb( _top_plane, middle, extent ))
283 case VISIBILITY_FULL:
break;
284 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
285 case VISIBILITY_NONE:
return VISIBILITY_NONE;
288 switch( _test_aabb( _near_plane, middle, extent ))
290 case VISIBILITY_FULL:
break;
291 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
292 case VISIBILITY_NONE:
return VISIBILITY_NONE;
295 switch( _test_aabb( _far_plane, middle, extent ))
297 case VISIBILITY_FULL:
break;
298 case VISIBILITY_PARTIAL: result = VISIBILITY_PARTIAL;
break;
299 case VISIBILITY_NONE:
return VISIBILITY_NONE;
307 #endif // include protection
Helper class for OpenGL view frustum culling.
void setup(const matrix< 4, 4, T > &proj_modelview)
Set up the culling state using a 4x4 projection*modelView matrix.
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