Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

AABB/frustum intersection

By: vexator on Oct 9th, 2011  |  syntax: C++  |  size: 5.94 KB  |  views: 302  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // DECLARATION:
  2.  
  3. class BoundingVolume
  4. {
  5.         public:
  6.  
  7.                 enum TestResult
  8.                 {
  9.                         TEST_OUTSIDE,
  10.                         TEST_INTERSECT,
  11.                         TEST_INSIDE
  12.                 };
  13.  
  14.         public:
  15.        
  16.                 virtual TestResult testIntersection( const vec3 &point ) const = 0;
  17.                 virtual TestResult testIntersection( shared_ptr<const BoundingBox> box ) const = 0;
  18.                 virtual TestResult testIntersection( shared_ptr<const BoundingSphere> sphere ) const = 0;
  19. };
  20.  
  21. class BoundingBox : public BoundingVolume
  22. {
  23.         public:
  24.        
  25.                 vec3 minimum;
  26.                 vec3 maximum;
  27.                
  28.                 vec3 position;
  29.  
  30.         public:
  31.  
  32.                 BoundingBox( vec3 minimum, vec3 maximum, vec3 position = vec3(0.0f) ) : BoundingVolume()
  33.                 {
  34.                         this->minimum = minimum;
  35.                         this->maximum = maximum;
  36.                        
  37.                         this->position = position;
  38.                 }
  39.  
  40.                 virtual vec3 getPositiveVertex( const vec3 &normal ) const;
  41.                 virtual vec3 getNegativeVertex( const vec3 &normal ) const;
  42.  
  43.                 TestResult testIntersection( const vec3 &point ) const;
  44.                 TestResult testIntersection( shared_ptr<const BoundingBox> box ) const;
  45.                 TestResult testIntersection( shared_ptr<const BoundingSphere> sphere ) const;
  46. };
  47.  
  48. class Frustum : public BoundingVolume
  49. {
  50.         public:
  51.  
  52.                 enum Plane
  53.                 {
  54.                         PLANE_BACK,
  55.                         PLANE_FRONT,
  56.                         PLANE_RIGHT,
  57.                         PLANE_LEFT,
  58.                         PLANE_TOP,
  59.                         PLANE_BOTTOM
  60.                 };
  61.  
  62.         public:
  63.  
  64.                 Frustum( const mat4 &viewMatrix, const mat4 &projectionMatrix );
  65.  
  66.                 const vec4 &getPlane( const int plane ) const;
  67.                
  68.                 TestResult testIntersection( const vec3 &point ) const;
  69.                 TestResult testIntersection( shared_ptr<const BoundingBox> box ) const;
  70.                 TestResult testIntersection( shared_ptr<const BoundingSphere> sphere ) const;
  71.  
  72.         protected:
  73.  
  74.                 vec4 m_planes[6];
  75. };
  76.  
  77.  
  78.  
  79. // RELEVANT IMPLEMENTATION:
  80.  
  81. // compute frustum planes from view and projection matrices
  82. Frustum::Frustum( const mat4 &viewMatrix, const mat4 &projectionMatrix ) : BoundingVolume()
  83. {
  84.         const mat4 &v = viewMatrix;
  85.         const mat4 &p = projectionMatrix;
  86.  
  87.         mat4 clipMatrix;
  88.  
  89.         clipMatrix[0][0] = v[0][0 ]*p[0][0]+v[0][1]*p[1][0]+v[0][2]*p[2][0]+v[0][3]*p[3][0];
  90.         clipMatrix[1][0] = v[0][0]*p[0][1]+v[0][1]*p[1][1]+v[0][2]*p[2][1]+v[0][3]*p[3][1];
  91.         clipMatrix[2][0] = v[0][0]*p[0][2]+v[0][1]*p[1][2]+v[0][2]*p[2][2]+v[0][3]*p[3][2];
  92.         clipMatrix[3][0] = v[0][0]*p[0][3]+v[0][1]*p[1][3]+v[0][2]*p[2][3]+v[0][3]*p[3][3];
  93.         clipMatrix[0][1] = v[1][0]*p[0][0]+v[1][1]*p[1][0]+v[1][2]*p[2][0]+v[1][3]*p[3][0];
  94.         clipMatrix[1][1] = v[1][0]*p[0][1]+v[1][1]*p[1][1]+v[1][2]*p[2][1]+v[1][3]*p[3][1];
  95.         clipMatrix[2][1] = v[1][0]*p[0][2]+v[1][1]*p[1][2]+v[1][2]*p[2][2]+v[1][3]*p[3][2];
  96.         clipMatrix[3][1] = v[1][0]*p[0][3]+v[1][1]*p[1][3]+v[1][2]*p[2][3]+v[1][3]*p[3][3];
  97.         clipMatrix[0][2] = v[2][0]*p[0][0]+v[2][1]*p[1][0]+v[2][2]*p[2][0]+v[2][3]*p[3][0];
  98.         clipMatrix[1][2] = v[2][0]*p[0][1]+v[2][1]*p[1][1]+v[2][2]*p[2][1]+v[2][3]*p[3][1];
  99.         clipMatrix[2][2] = v[2][0]*p[0][2]+v[2][1]*p[1][2]+v[2][2]*p[2][2]+v[2][3]*p[3][2];
  100.         clipMatrix[3][2] = v[2][0]*p[0][3]+v[2][1]*p[1][3]+v[2][2]*p[2][3]+v[2][3]*p[3][3];
  101.         clipMatrix[0][3] = v[3][0]*p[0][0]+v[3][1]*p[1][0]+v[3][2]*p[2][0]+v[3][3]*p[3][0];
  102.         clipMatrix[1][3] = v[3][0]*p[0][1]+v[3][1]*p[1][1]+v[3][2]*p[2][1]+v[3][3]*p[3][1];
  103.         clipMatrix[2][3] = v[3][0]*p[0][2]+v[3][1]*p[1][2]+v[3][2]*p[2][2]+v[3][3]*p[3][2];
  104.         clipMatrix[3][3] = v[3][0]*p[0][3]+v[3][1]*p[1][3]+v[3][2]*p[2][3]+v[3][3]*p[3][3];
  105.  
  106.         m_planes[PLANE_RIGHT].x = clipMatrix[3][0]-clipMatrix[0][0];
  107.         m_planes[PLANE_RIGHT].y = clipMatrix[3][1]-clipMatrix[0][1];
  108.         m_planes[PLANE_RIGHT].z = clipMatrix[3][2]-clipMatrix[0][2];
  109.         m_planes[PLANE_RIGHT].w = clipMatrix[3][3]-clipMatrix[0][3];
  110.  
  111.         m_planes[PLANE_LEFT].x = clipMatrix[3][0]+clipMatrix[0][0];
  112.         m_planes[PLANE_LEFT].y = clipMatrix[3][1]+clipMatrix[0][1];
  113.         m_planes[PLANE_LEFT].z = clipMatrix[3][2]+clipMatrix[0][2];
  114.         m_planes[PLANE_LEFT].w = clipMatrix[3][3]+clipMatrix[0][3];
  115.  
  116.         m_planes[PLANE_BOTTOM].x = clipMatrix[3][0]+clipMatrix[1][0];
  117.         m_planes[PLANE_BOTTOM].y = clipMatrix[3][1]+clipMatrix[1][1];
  118.         m_planes[PLANE_BOTTOM].z = clipMatrix[3][2]+clipMatrix[1][2];
  119.         m_planes[PLANE_BOTTOM].w = clipMatrix[3][3]+clipMatrix[1][3];
  120.  
  121.         m_planes[PLANE_TOP].x = clipMatrix[3][0]-clipMatrix[1][0];
  122.         m_planes[PLANE_TOP].y = clipMatrix[3][1]-clipMatrix[1][1];
  123.         m_planes[PLANE_TOP].z = clipMatrix[3][2]-clipMatrix[1][2];
  124.         m_planes[PLANE_TOP].w = clipMatrix[3][3]-clipMatrix[1][3];
  125.  
  126.         m_planes[PLANE_BACK].x = clipMatrix[3][0]-clipMatrix[2][0];
  127.         m_planes[PLANE_BACK].y = clipMatrix[3][1]-clipMatrix[2][1];
  128.         m_planes[PLANE_BACK].z = clipMatrix[3][2]-clipMatrix[2][2];
  129.         m_planes[PLANE_BACK].w = clipMatrix[3][3]-clipMatrix[2][3];
  130.  
  131.         m_planes[PLANE_FRONT].x = clipMatrix[3][0]+clipMatrix[2][0];
  132.         m_planes[PLANE_FRONT].y = clipMatrix[3][1]+clipMatrix[2][1];
  133.         m_planes[PLANE_FRONT].z = clipMatrix[3][2]+clipMatrix[2][2];
  134.         m_planes[PLANE_FRONT].w = clipMatrix[3][3]+clipMatrix[2][3];
  135.  
  136.         for( int i = 0; i < 6; i++ )
  137.         {
  138.                 m_planes[i] = glm::normalize( m_planes[i] );
  139.         }
  140. }
  141.  
  142. // check whether an AABB intersects the frustum
  143. BoundingVolume::TestResult Frustum::testIntersection( shared_ptr<const BoundingBox> box ) const
  144. {
  145.         TestResult result = TEST_INSIDE;
  146.  
  147.         for( uint i = 0; i < 6; i++ )
  148.         {
  149.                 const float pos = m_planes[i].w;
  150.                 const vec3 normal = vec3(m_planes[i]);
  151.  
  152.                 if( glm::dot(normal, box->getPositiveVertex(normal))+pos < 0.0f )
  153.                 {
  154.                         return TEST_OUTSIDE;
  155.                 }
  156.  
  157.                 if( glm::dot(normal, box->getNegativeVertex(normal))+pos < 0.0f )
  158.                 {
  159.                         result = TEST_INTERSECT;
  160.                 }
  161.         }
  162.  
  163.         return result;
  164. }
  165.  
  166. vec3 BoundingBox::getPositiveVertex( const vec3 &normal ) const
  167. {
  168.         vec3 positiveVertex = minimum;
  169.  
  170.         if( normal.x >= 0.0f ) positiveVertex.x = maximum.x;
  171.         if( normal.y >= 0.0f ) positiveVertex.y = maximum.y;
  172.         if( normal.z >= 0.0f ) positiveVertex.z = maximum.z;
  173.  
  174.         return position+positiveVertex;
  175. }
  176.  
  177. vec3 BoundingBox::getNegativeVertex( const vec3 &normal ) const
  178. {
  179.         vec3 negativeVertex = maximum;
  180.  
  181.         if( normal.x >= 0.0f ) negativeVertex.x = minimum.x;
  182.         if( normal.y >= 0.0f ) negativeVertex.y = minimum.y;
  183.         if( normal.z >= 0.0f ) negativeVertex.z = minimum.z;
  184.  
  185.         return position+negativeVertex;
  186. }
  187.