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> 63 FrustumCuller(
const vec3& nlt,
const vec3& nrt,
const vec3& nlb,
64 const vec3& nrb,
const vec3& flt,
const vec3& frt,
65 const vec3& flb,
const vec3& frb);
70 Visibility
test(
const vec4& sphere)
const;
77 friend std::ostream& operator<<(std::ostream& os,
const FrustumCuller& f)
79 return os <<
"Frustum cull planes: " << std::endl
80 <<
" left " << f._leftPlane << std::endl
81 <<
" right " << f._rightPlane << std::endl
82 <<
" top " << f._topPlane << std::endl
83 <<
" bottom " << f._bottomPlane << std::endl
84 <<
" near " << f._nearPlane << std::endl
85 <<
" far " << f._farPlane << std::endl;
89 inline void _normalizePlane(vec4& plane)
const;
90 inline Visibility _test(
const vec4& plane,
const vec3& middle,
91 const vec3& size_2)
const;
110 template <
typename T>
114 const vec4& row0 = projModelView.getRow(0);
115 const vec4& row1 = projModelView.getRow(1);
116 const vec4& row2 = projModelView.getRow(2);
117 const vec4& row3 = projModelView.getRow(3);
119 _leftPlane = row3 + row0;
120 _rightPlane = row3 - row0;
121 _bottomPlane = row3 + row1;
122 _topPlane = row3 - row1;
123 _nearPlane = row3 + row2;
124 _farPlane = row3 - row2;
126 _normalizePlane(_leftPlane);
127 _normalizePlane(_rightPlane);
128 _normalizePlane(_bottomPlane);
129 _normalizePlane(_topPlane);
130 _normalizePlane(_nearPlane);
131 _normalizePlane(_farPlane);
134 template <
typename T>
145 _leftPlane = compute_plane(c, a, e);
146 _rightPlane = compute_plane(f, b, d);
147 _bottomPlane = compute_plane(h, d, c);
148 _topPlane = compute_plane(a, b, f);
149 _nearPlane = compute_plane(b, a, c);
150 _farPlane = compute_plane(g, e, f);
153 template <
typename T>
156 const vec3& v3 = plane.template get_sub_vector<3, 0>();
157 const T len_i = 1.0 / v3.length();
164 template <
typename T>
167 Visibility visibility = VISIBILITY_FULL;
176 T distance = _leftPlane.x() * sphere.x() + _leftPlane.y() * sphere.y() +
177 _leftPlane.z() * sphere.z() + _leftPlane.w();
178 if (distance <= -sphere.w())
179 return VISIBILITY_NONE;
180 if (distance < sphere.w())
181 visibility = VISIBILITY_PARTIAL;
183 distance = _rightPlane.x() * sphere.x() + _rightPlane.y() * sphere.y() +
184 _rightPlane.z() * sphere.z() + _rightPlane.w();
185 if (distance <= -sphere.w())
186 return VISIBILITY_NONE;
187 if (distance < sphere.w())
188 visibility = VISIBILITY_PARTIAL;
190 distance = _bottomPlane.x() * sphere.x() + _bottomPlane.y() * sphere.y() +
191 _bottomPlane.z() * sphere.z() + _bottomPlane.w();
192 if (distance <= -sphere.w())
193 return VISIBILITY_NONE;
194 if (distance < sphere.w())
195 visibility = VISIBILITY_PARTIAL;
197 distance = _topPlane.x() * sphere.x() + _topPlane.y() * sphere.y() +
198 _topPlane.z() * sphere.z() + _topPlane.w();
199 if (distance <= -sphere.w())
200 return VISIBILITY_NONE;
201 if (distance < sphere.w())
202 visibility = VISIBILITY_PARTIAL;
204 distance = _nearPlane.x() * sphere.x() + _nearPlane.y() * sphere.y() +
205 _nearPlane.z() * sphere.z() + _nearPlane.w();
207 if (distance <= -sphere.w())
208 return VISIBILITY_NONE;
209 if (distance < sphere.w())
210 visibility = VISIBILITY_PARTIAL;
212 distance = _farPlane.x() * sphere.x() + _farPlane.y() * sphere.y() +
213 _farPlane.z() * sphere.z() + _farPlane.w();
214 if (distance <= -sphere.w())
215 return VISIBILITY_NONE;
216 if (distance < sphere.w())
217 visibility = VISIBILITY_PARTIAL;
222 template <
typename T>
224 const vec3& extent)
const 227 const T d = plane.dot(middle);
228 const T n = extent.x() * fabs(plane.x()) + extent.y() * fabs(plane.y()) +
229 extent.z() * fabs(plane.z());
232 return VISIBILITY_FULL;
234 return VISIBILITY_PARTIAL;
235 return VISIBILITY_NONE;
238 template <
typename T>
241 Visibility result = VISIBILITY_FULL;
244 switch (_test(_leftPlane, middle, extent))
246 case VISIBILITY_FULL:
248 case VISIBILITY_PARTIAL:
249 result = VISIBILITY_PARTIAL;
251 case VISIBILITY_NONE:
252 return VISIBILITY_NONE;
255 switch (_test(_rightPlane, middle, extent))
257 case VISIBILITY_FULL:
259 case VISIBILITY_PARTIAL:
260 result = VISIBILITY_PARTIAL;
262 case VISIBILITY_NONE:
263 return VISIBILITY_NONE;
266 switch (_test(_bottomPlane, middle, extent))
268 case VISIBILITY_FULL:
270 case VISIBILITY_PARTIAL:
271 result = VISIBILITY_PARTIAL;
273 case VISIBILITY_NONE:
274 return VISIBILITY_NONE;
277 switch (_test(_topPlane, middle, extent))
279 case VISIBILITY_FULL:
281 case VISIBILITY_PARTIAL:
282 result = VISIBILITY_PARTIAL;
284 case VISIBILITY_NONE:
285 return VISIBILITY_NONE;
288 switch (_test(_nearPlane, middle, extent))
290 case VISIBILITY_FULL:
292 case VISIBILITY_PARTIAL:
293 result = VISIBILITY_PARTIAL;
295 case VISIBILITY_NONE:
296 return VISIBILITY_NONE;
299 switch (_test(_farPlane, middle, extent))
301 case VISIBILITY_FULL:
303 case VISIBILITY_PARTIAL:
304 result = VISIBILITY_PARTIAL;
306 case VISIBILITY_NONE:
307 return VISIBILITY_NONE;
315 #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
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.