00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __VMML__FRUSTUM_CULLER__HPP__
00010 #define __VMML__FRUSTUM_CULLER__HPP__
00011
00012 #include <vmmlib/vector.hpp>
00013 #include <vmmlib/matrix.hpp>
00014 #include <vmmlib/visibility.hpp>
00015
00016
00017
00018 namespace vmml
00019 {
00020
00022 template< class T >
00023 class frustumCuller
00024 {
00025 public:
00026
00027 frustumCuller() {}
00028 ~frustumCuller(){}
00029
00030 void setup( const matrix< 4, 4, T >& projModelView );
00031 Visibility testSphere( const vector< 4, T >& sphere );
00032
00033 private:
00034 inline void _normalizePlane( vector< 4, T >& plane ) const;
00035
00036 vector< 4, T > _leftPlane;
00037 vector< 4, T > _rightPlane;
00038 vector< 4, T > _bottomPlane;
00039 vector< 4, T > _topPlane;
00040 vector< 4, T > _nearPlane;
00041 vector< 4, T > _farPlane;
00042
00043 };
00044
00045
00046 #ifndef VMMLIB_NO_TYPEDEFS
00047 typedef frustumCuller< float > frustumCullerf;
00048 typedef frustumCuller< double > frustumCullerd;
00049 #endif
00050
00051 }
00052
00053
00054
00055
00056 namespace vmml
00057 {
00058
00063 template < class T >
00064 void frustumCuller< T >::setup( const matrix< 4, 4, T >& projModelView )
00065 {
00066
00067
00068 const vector< 4, T >& row0 = projModelView.getRow( 0 );
00069 const vector< 4, T >& row1 = projModelView.getRow( 1 );
00070 const vector< 4, T >& row2 = projModelView.getRow( 2 );
00071 const vector< 4, T >& row3 = projModelView.getRow( 3 );
00072
00073 _leftPlane = row3 + row0;
00074 _rightPlane = row3 - row0;
00075 _bottomPlane = row3 + row1;
00076 _topPlane = row3 - row1;
00077 _nearPlane = row3 + row2;
00078 _farPlane = row3 - row2;
00079
00080 _normalizePlane( _leftPlane );
00081 _normalizePlane( _rightPlane );
00082 _normalizePlane( _bottomPlane );
00083 _normalizePlane( _topPlane );
00084 _normalizePlane( _nearPlane );
00085 _normalizePlane( _farPlane );
00086
00087 }
00088
00089
00090
00091 template < class T >
00092 inline void
00093 frustumCuller< T >::_normalizePlane( vector< 4, T >& plane ) const
00094 {
00095 const vector< 3, T >& v3 = reinterpret_cast< const vector< 3, T >& >( plane );
00096 const T lInv = 1.0 / v3.length();
00097 plane.x() *= lInv;
00098 plane.y() *= lInv;
00099 plane.z() *= lInv;
00100 plane.w() *= lInv;
00101 }
00102
00103
00104
00105 template < class T >
00106 Visibility frustumCuller< T >::testSphere( const vector< 4, T >& sphere )
00107 {
00108 Visibility visibility = VISIBILITY_FULL;
00109
00110
00111
00112
00113
00114
00115
00116
00117 T distance = _leftPlane.x() * sphere.x() +
00118 _leftPlane.y() * sphere.y() +
00119 _leftPlane.z() * sphere.z() + _leftPlane.w();
00120 if( distance <= -sphere.w() )
00121 return VISIBILITY_NONE;
00122 if( distance < sphere.w() )
00123 visibility = VISIBILITY_PARTIAL;
00124
00125 distance = _rightPlane.x() * sphere.x() +
00126 _rightPlane.y() * sphere.y() +
00127 _rightPlane.z() * sphere.z() + _rightPlane.w();
00128 if( distance <= -sphere.w() )
00129 return VISIBILITY_NONE;
00130 if( distance < sphere.w() )
00131 visibility = VISIBILITY_PARTIAL;
00132
00133 distance = _bottomPlane.x() * sphere.x() +
00134 _bottomPlane.y() * sphere.y() +
00135 _bottomPlane.z() * sphere.z() + _bottomPlane.w();
00136 if( distance <= -sphere.w() )
00137 return VISIBILITY_NONE;
00138 if( distance < sphere.w() )
00139 visibility = VISIBILITY_PARTIAL;
00140
00141 distance = _topPlane.x() * sphere.x() +
00142 _topPlane.y() * sphere.y() +
00143 _topPlane.z() * sphere.z() + _topPlane.w();
00144 if( distance <= -sphere.w() )
00145 return VISIBILITY_NONE;
00146 if( distance < sphere.w() )
00147 visibility = VISIBILITY_PARTIAL;
00148
00149 distance = _nearPlane.x() * sphere.x() +
00150 _nearPlane.y() * sphere.y() +
00151 _nearPlane.z() * sphere.z() + _nearPlane.w();
00152 if( distance <= -sphere.w() )
00153 return VISIBILITY_NONE;
00154 if( distance < sphere.w() )
00155 visibility = VISIBILITY_PARTIAL;
00156
00157 distance = _farPlane.x() * sphere.x() +
00158 _farPlane.y() * sphere.y() +
00159 _farPlane.z() * sphere.z() + _farPlane.w();
00160 if( distance <= -sphere.w() )
00161 return VISIBILITY_NONE;
00162 if( distance < sphere.w() )
00163 visibility = VISIBILITY_PARTIAL;
00164
00165 return visibility;
00166 }
00167 }
00168 #endif