/usr/include/vmmlib/frustum_culler.hpp is in libvmmlib-dev 1.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | /*
* VMMLib - Vector & Matrix Math Lib
*
* @author Stefan Eilemann
*
* @license revised BSD license, check LICENSE
*/
#ifndef __VMML__FRUSTUM_CULLER__HPP__
#define __VMML__FRUSTUM_CULLER__HPP__
#include <vmmlib/vector.hpp>
#include <vmmlib/matrix.hpp>
#include <vmmlib/visibility.hpp>
// - declaration -
namespace vmml
{
/** Helper class for OpenGL view frustum culling. */
template< class T >
class frustum_culler
{
public:
typedef vector< 3, T > vec3;
typedef vector< 4, T > vec4;
// contructors
frustum_culler() {}// warning: components NOT initialised ( for performance )
~frustum_culler(){}
void setup( const matrix< 4, 4, T >& proj_modelview );
Visibility test_sphere( const vector< 4, T >& sphere );
private:
inline void _normalize_plane( vector< 4, T >& plane ) const;
vec4 _left_plane;
vec4 _right_plane;
vec4 _bottom_plane;
vec4 _top_plane;
vec4 _near_plane;
vec4 _far_plane;
}; // class frustum_culler
#ifndef VMMLIB_NO_TYPEDEFS
typedef frustum_culler< float > frustum_cullerf;
typedef frustum_culler< double > frustum_cullerd;
#endif
} // namespace vmml
// - implementation - //
namespace vmml
{
/**
* Setup the culler by extracting the frustum planes from the projection
* matrix. The projection matrix should contain the viewing transformation.
*/
template < class T >
void frustum_culler< T >::setup( const matrix< 4, 4, T >& proj_modelview )
{
// See http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf pp.5
const vec4& row0 = proj_modelview.get_row( 0 );
const vec4& row1 = proj_modelview.get_row( 1 );
const vec4& row2 = proj_modelview.get_row( 2 );
const vec4& row3 = proj_modelview.get_row( 3 );
_left_plane = row3 + row0;
_right_plane = row3 - row0;
_bottom_plane = row3 + row1;
_top_plane = row3 - row1;
_near_plane = row3 + row2;
_far_plane = row3 - row2;
_normalize_plane( _left_plane );
_normalize_plane( _right_plane );
_normalize_plane( _bottom_plane );
_normalize_plane( _top_plane );
_normalize_plane( _near_plane );
_normalize_plane( _far_plane );
}
template < class T >
inline void
frustum_culler< T >::_normalize_plane( vector< 4, T >& plane ) const
{
const vec3& v3 = plane.template get_sub_vector< 3 >();
const T len_i = 1.0 / v3.length();
plane.x() *= len_i;
plane.y() *= len_i;
plane.z() *= len_i;
plane.w() *= len_i;
}
template < class T >
Visibility frustum_culler< T >::test_sphere( const vector< 4, T >& sphere )
{
Visibility visibility = VISIBILITY_FULL;
// see http://www.flipcode.com/articles/article_frustumculling.shtml
// distance = plane.normal . sphere.center + plane.distance
// Test all planes:
// - if sphere behind plane: not visible
// - if sphere intersects one plane: partially visible
// - else: fully visible
T distance = _left_plane.x() * sphere.x() +
_left_plane.y() * sphere.y() +
_left_plane.z() * sphere.z() + _left_plane.w();
if( distance <= -sphere.w() )
return VISIBILITY_NONE;
if( distance < sphere.w() )
visibility = VISIBILITY_PARTIAL;
distance = _right_plane.x() * sphere.x() +
_right_plane.y() * sphere.y() +
_right_plane.z() * sphere.z() + _right_plane.w();
if( distance <= -sphere.w() )
return VISIBILITY_NONE;
if( distance < sphere.w() )
visibility = VISIBILITY_PARTIAL;
distance = _bottom_plane.x() * sphere.x() +
_bottom_plane.y() * sphere.y() +
_bottom_plane.z() * sphere.z() + _bottom_plane.w();
if( distance <= -sphere.w() )
return VISIBILITY_NONE;
if( distance < sphere.w() )
visibility = VISIBILITY_PARTIAL;
distance = _top_plane.x() * sphere.x() +
_top_plane.y() * sphere.y() +
_top_plane.z() * sphere.z() + _top_plane.w();
if( distance <= -sphere.w() )
return VISIBILITY_NONE;
if( distance < sphere.w() )
visibility = VISIBILITY_PARTIAL;
distance = _near_plane.x() * sphere.x() +
_near_plane.y() * sphere.y() +
_near_plane.z() * sphere.z() + _near_plane.w();
if( distance <= -sphere.w() )
return VISIBILITY_NONE;
if( distance < sphere.w() )
visibility = VISIBILITY_PARTIAL;
distance = _far_plane.x() * sphere.x() +
_far_plane.y() * sphere.y() +
_far_plane.z() * sphere.z() + _far_plane.w();
if( distance <= -sphere.w() )
return VISIBILITY_NONE;
if( distance < sphere.w() )
visibility = VISIBILITY_PARTIAL;
return visibility;
}
} // namespace vmml
#endif // include protection
|