Tucano  0.1
A library for rapid prototyping with modern OpenGL and GLSL
frustum.hpp
Go to the documentation of this file.
1 #ifndef __FRUSTUM__
2 #define __FRUSTUM__
3 
4 #include <iostream>
5 #include <vector>
6 #include <Eigen/Dense>
7 #include <Eigen/Geometry>
8 
9 using namespace std;
10 using namespace Eigen;
11 
12 namespace Tucano
13 {
14  template< typename Scalar, int Dim >
15  ostream& operator<<( ostream& out, const Hyperplane< Scalar, Dim >& plane )
16  {
17  out << "normal:" << plane.normal() << endl << ", offset: " << plane.offset();
18 
19  return out;
20  }
21 
22  template< typename Scalar, int Dim >
23  ostream& operator<<( ostream& out, const AlignedBox< Scalar, Dim >& box )
24  {
25  out << "min:" << box.min() << endl << ", max: " << box.max() << endl << ", size: " << box.sizes();
26 
27  return out;
28  }
29 
33  class Frustum
34  {
35  using Plane = Hyperplane< float, 3 >;
36  using Box = AlignedBox< float, 3 >;
37  public:
39  Frustum( const Matrix4f& mvp )
40  {
41 
42  for( int i = 0; i < 6; ++i )
43  {
44  m_planes.push_back( new Plane() );
45  }
46 
47  extractPlanes( mvp, true );
48  }
49 
51  {
52  for( Plane* plane : m_planes )
53  {
54  delete plane;
55  }
56  }
57 
60  void update( const Matrix4f& mvp )
61  {
62  extractPlanes( mvp, true );
63  }
64 
65 
70  bool isCullable( const Box& box );
71 
72  friend ostream& operator<<( ostream& out, const Frustum& f )
73  {
74  cout << "Frustum planes:" << endl << endl;
75  for( int i = 0; i < 6; ++i )
76  {
77  switch( i )
78  {
79  case 0: cout << "Left: "; break;
80  case 1: cout << "Right: "; break;
81  case 2: cout << "Top: "; break;
82  case 3: cout << "Bottom: "; break;
83  case 4: cout << "Near: "; break;
84  case 5: cout << "Far: "; break;
85  }
86  cout << *f.m_planes[ i ] << endl << endl;
87  }
88  cout << "End of frustum planes." << endl;
89 
90  return out;
91  }
92 
93  private:
98  void extractPlanes( const Matrix4f& mvp, const bool& normalize )
99  {
100  // It seems that the d plane coefficient has wrong sign in the original algorithm, so all d coefficients are being
101  // multiplied by -1 in this implementation.
102 
103  // Left clipping plane
104  Vector4f& leftCoeffs = m_planes[ 0 ]->coeffs();
105  leftCoeffs[ 0 ] = -( mvp( 3, 0 ) + mvp( 0, 0 ) );
106  leftCoeffs[ 1 ] = -( mvp( 3, 1 ) + mvp( 0, 1 ) );
107  leftCoeffs[ 2 ] = -( mvp( 3, 2 ) + mvp( 0, 2 ) );
108  leftCoeffs[ 3 ] = -( mvp( 3, 3 ) + mvp( 0, 3 ) );
109 
110  // Right clipping plane
111  Vector4f& rightCoeffs = m_planes[ 1 ]->coeffs();
112  rightCoeffs[ 0 ] = -( mvp( 3, 0 ) - mvp( 0, 0 ) );
113  rightCoeffs[ 1 ] = -( mvp( 3, 1 ) - mvp( 0, 1 ) );
114  rightCoeffs[ 2 ] = -( mvp( 3, 2 ) - mvp( 0, 2 ) );
115  rightCoeffs[ 3 ] = -( mvp( 3, 3 ) - mvp( 0, 3 ) );
116 
117  // Top clipping plane
118  Vector4f& topCoeffs = m_planes[ 2 ]->coeffs();
119  topCoeffs[ 0 ] = -( mvp( 3, 0 ) - mvp( 1, 0 ) );
120  topCoeffs[ 1 ] = -( mvp( 3, 1 ) - mvp( 1, 1 ) );
121  topCoeffs[ 2 ] = -( mvp( 3, 2 ) - mvp( 1, 2 ) );
122  topCoeffs[ 3 ] = -( mvp( 3, 3 ) - mvp( 1, 3 ) );
123 
124  // Bottom clipping plane
125  Vector4f& botCoeffs = m_planes[ 3 ]->coeffs();
126  botCoeffs[ 0 ] = -( mvp( 3, 0 ) + mvp( 1, 0 ) );
127  botCoeffs[ 1 ] = -( mvp( 3, 1 ) + mvp( 1, 1 ) );
128  botCoeffs[ 2 ] = -( mvp( 3, 2 ) + mvp( 1, 2 ) );
129  botCoeffs[ 3 ] = -( mvp( 3, 3 ) + mvp( 1, 3 ) );
130 
131  // Near clipping plane
132  Vector4f& nearCoeffs = m_planes[ 4 ]->coeffs();
133  nearCoeffs[ 0 ] = -( mvp( 3, 0 ) + mvp( 2, 0 ) );
134  nearCoeffs[ 1 ] = -( mvp( 3, 1 ) + mvp( 2, 1 ) );
135  nearCoeffs[ 2 ] = -( mvp( 3, 2 ) + mvp( 2, 2 ) );
136  nearCoeffs[ 3 ] = -( mvp( 3, 3 ) + mvp( 2, 3 ) );
137 
138  // Far clipping plane
139  Vector4f& farCoeffs = m_planes[ 5 ]->coeffs();
140  farCoeffs[ 0 ] = -( mvp( 3, 0 ) - mvp( 2, 0 ) );
141  farCoeffs[ 1 ] = -( mvp( 3, 1 ) - mvp( 2, 1 ) );
142  farCoeffs[ 2 ] = -( mvp( 3, 2 ) - mvp( 2, 2 ) );
143  farCoeffs[ 3 ] = -( mvp( 3, 3 ) - mvp( 2, 3 ) );
144 
145  if ( normalize )
146  {
147  for( Plane* plane : m_planes )
148  {
149  plane->normalize();
150  }
151  }
152  }
153 
155  vector< Plane* > m_planes;
156  };
157 
158  inline bool Frustum::isCullable( const Box& box )
159  {
160  //cout << "==== Starting culling ====" << endl << "Box: " << box << endl;
161 
162  Vector3f boxSizes = box.sizes();
163  Vector3f boxMin = box.min();
164  Vector3f boxMax = box.max();
165 
166  // Performs frustum plane dilatation, finds n only, since p is necessary just for detecting intersections points,
167  // and verifies if n is inside or outside the frustum.
168  for( int i = 0; i < 6; ++i )
169  {
170  Plane* plane = m_planes[ i ];
171  Vector3f normal = plane->normal();
172  float dilatation = abs( boxSizes.dot( normal ) );
173  float offset = plane->offset() - dilatation;
174  Plane dilatatedPlane( normal, offset );
175 
176  //cout << endl << "Dilatation:" << dilatation << endl << "Dilatated plane:" << dilatatedPlane << endl;
177 
178  Vector3f n;
179 
180  n[ 0 ] = ( normal[ 0 ] < 0 ) ? boxMax[ 0 ] : boxMin[ 0 ];
181  n[ 1 ] = ( normal[ 1 ] < 0 ) ? boxMax[ 1 ] : boxMin[ 1 ];
182  n[ 2 ] = ( normal[ 2 ] < 0 ) ? boxMax[ 2 ] : boxMin[ 2 ];
183 
184  float signedDist = dilatatedPlane.signedDistance( n );
185  //cout << "n point: " << n << endl << "signedDist:" << signedDist << endl;
186 
187  if( signedDist > 0 )
188  {
189  /*string planeName;
190  switch( i )
191  {
192  case 0: planeName = "left"; break;
193  case 1: planeName = "right"; break;
194  case 2: planeName = "top"; break;
195  case 3: planeName = "bot"; break;
196  case 4: planeName = "near"; break;
197  case 5: planeName = "far"; break;
198  }
199  cout << "Outside " << planeName << " plane." << endl;*/
200  return true;
201  }
202  }
203  return false;
204  }
205 }
206 
207 #endif
Hyperplane< float, 3 > Plane
Definition: frustum.hpp:35
Definition: bufferobject.hpp:34
vector< Plane * > m_planes
Definition: frustum.hpp:155
Frustum(const Matrix4f &mvp)
Definition: frustum.hpp:39
AlignedBox< float, 3 > Box
Definition: frustum.hpp:36
Definition: frustum.hpp:33
friend ostream & operator<<(ostream &out, const Frustum &f)
Definition: frustum.hpp:72
~Frustum()
Definition: frustum.hpp:50
void update(const Matrix4f &mvp)
Definition: frustum.hpp:60
void extractPlanes(const Matrix4f &mvp, const bool &normalize)
Definition: frustum.hpp:98