#version 330 core

uniform transform {
   mat4 ModelViewMatrix;
   mat4 ProjectionMatrix;
} Transform;

uniform vec3 ObjectExtent;

uniform mat4 cullingMVP; 

layout(location = 0) in vec4 InstancePosition;

out vec4 OrigPosition;
flat out int objectVisible;

void main(void) {

   OrigPosition = InstancePosition;
   
   /* calculate modelview projection matrix */
   mat4 MVP = Transform.ProjectionMatrix * Transform.ModelViewMatrix;
   
   /* create the bounding box of the object */
   vec4 BoundingBox[8];
   BoundingBox[0] = cullingMVP * ( InstancePosition + vec4( ObjectExtent.x, ObjectExtent.y, ObjectExtent.z, 1.0) );
   BoundingBox[1] = cullingMVP * ( InstancePosition + vec4(-ObjectExtent.x, ObjectExtent.y, ObjectExtent.z, 1.0) );
   BoundingBox[2] = cullingMVP * ( InstancePosition + vec4( ObjectExtent.x,-ObjectExtent.y, ObjectExtent.z, 1.0) );
   BoundingBox[3] = cullingMVP * ( InstancePosition + vec4(-ObjectExtent.x,-ObjectExtent.y, ObjectExtent.z, 1.0) );
   BoundingBox[4] = cullingMVP * ( InstancePosition + vec4( ObjectExtent.x, ObjectExtent.y,-ObjectExtent.z, 1.0) );
   BoundingBox[5] = cullingMVP * ( InstancePosition + vec4(-ObjectExtent.x, ObjectExtent.y,-ObjectExtent.z, 1.0) );
   BoundingBox[6] = cullingMVP * ( InstancePosition + vec4( ObjectExtent.x,-ObjectExtent.y,-ObjectExtent.z, 1.0) );
   BoundingBox[7] = cullingMVP * ( InstancePosition + vec4(-ObjectExtent.x,-ObjectExtent.y,-ObjectExtent.z, 1.0) );
   
   /* check how the bounding box resides regarding to the view frustum */   
   int outOfBound[6] = int[6]( 0, 0, 0, 0, 0, 0 );

   for (int i=0; i<8; i++)
   {
      if ( BoundingBox[i].x >  BoundingBox[i].w ) outOfBound[0]++;
      if ( BoundingBox[i].x < -BoundingBox[i].w ) outOfBound[1]++;
      if ( BoundingBox[i].y >  BoundingBox[i].w ) outOfBound[2]++;
      if ( BoundingBox[i].y < -BoundingBox[i].w ) outOfBound[3]++;
      if ( BoundingBox[i].z >  BoundingBox[i].w ) outOfBound[4]++;
      if ( BoundingBox[i].z < -BoundingBox[i].w ) outOfBound[5]++;
   }

   bool inFrustum = true;
   
   for (int i=0; i<6; i++)
      if ( outOfBound[i] == 8 ) {
         inFrustum = false;
      }

   objectVisible = inFrustum ? 1 : 0;
}
