GLBasic forum

Main forum => GLBasic - en => Topic started by: bigsofty on 2012-Aug-25

Title: Point within viewing frustrum
Post by: bigsofty on 2012-Aug-25
Anyone know of a quick way to check if a point is within the cameras viewing frustum, or even better a sphere instead of a point?
Title: Re: Point within viewing frustrum
Post by: mentalthink on 2012-Aug-25
Hi Bigsofty, making a box like the truncated cone of the camera and looking into itself?¿... or if you launch some raycast and get the collisions?¿... Really I don´t know nothing about maths for do this... but perhaps can be useful this couple of ideas.

Regards,
Title: Re: Point within viewing frustrum
Post by: bigsofty on 2012-Aug-25
Thank for the ideas Mentalthink.  ;)

This morning, while browsing the web, I found a relevant article with a C example so I think I will just in-line that and see how I get on.
Title: Re: Point within viewing frustrum
Post by: matchy on 2012-Aug-25
Quote from: bigsofty on 2012-Aug-25
Thank for the ideas Mentalthink.  ;)

This morning, while browsing the web, I found a relevant article with a C example so I think I will just in-line that and see how I get on.

What is the point in telling us when you could share with us?
Title: Re: Point within viewing frustrum
Post by: bigsofty on 2012-Aug-26
Quote from: matchy on 2012-Aug-25
What is the point in telling us when you could share with us?

I didn't think it would be of use to anyone else but me as I assumed GLBasic 3D already has frustum culling built in? You see I am not using the GLBasic 3D Engine but my own hybrid inlined GLES one.

I have absolutely no problem posting the frustum code, I hope it's of use to you.  ;)

Code (glbasic) Select
INLINE
float frustum[6][4];

void ExtractFrustum()
{
   float   proj[16];
   float   modl[16];
   float   clip[16];
   float   t;

   /* Get the current PROJECTION matrix from OpenGL */
   glGetFloatv( GL_PROJECTION_MATRIX, proj );

   /* Get the current MODELVIEW matrix from OpenGL */
   glGetFloatv( GL_MODELVIEW_MATRIX, modl );

   /* Combine the two matrices (multiply projection by modelview) */
   clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
   clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
   clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
   clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];

   clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
   clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
   clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
   clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];

   clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
   clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
   clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
   clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];

   clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
   clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
   clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
   clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];

   /* Extract the numbers for the RIGHT plane */
   frustum[0][0] = clip[ 3] - clip[ 0];
   frustum[0][1] = clip[ 7] - clip[ 4];
   frustum[0][2] = clip[11] - clip[ 8];
   frustum[0][3] = clip[15] - clip[12];

   /* Normalize the result */
   t = sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
   frustum[0][0] /= t;
   frustum[0][1] /= t;
   frustum[0][2] /= t;
   frustum[0][3] /= t;

   /* Extract the numbers for the LEFT plane */
   frustum[1][0] = clip[ 3] + clip[ 0];
   frustum[1][1] = clip[ 7] + clip[ 4];
   frustum[1][2] = clip[11] + clip[ 8];
   frustum[1][3] = clip[15] + clip[12];

   /* Normalize the result */
   t = sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
   frustum[1][0] /= t;
   frustum[1][1] /= t;
   frustum[1][2] /= t;
   frustum[1][3] /= t;

   /* Extract the BOTTOM plane */
   frustum[2][0] = clip[ 3] + clip[ 1];
   frustum[2][1] = clip[ 7] + clip[ 5];
   frustum[2][2] = clip[11] + clip[ 9];
   frustum[2][3] = clip[15] + clip[13];

   /* Normalize the result */
   t = sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
   frustum[2][0] /= t;
   frustum[2][1] /= t;
   frustum[2][2] /= t;
   frustum[2][3] /= t;

   /* Extract the TOP plane */
   frustum[3][0] = clip[ 3] - clip[ 1];
   frustum[3][1] = clip[ 7] - clip[ 5];
   frustum[3][2] = clip[11] - clip[ 9];
   frustum[3][3] = clip[15] - clip[13];

   /* Normalize the result */
   t = sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
   frustum[3][0] /= t;
   frustum[3][1] /= t;
   frustum[3][2] /= t;
   frustum[3][3] /= t;

   /* Extract the FAR plane */
   frustum[4][0] = clip[ 3] - clip[ 2];
   frustum[4][1] = clip[ 7] - clip[ 6];
   frustum[4][2] = clip[11] - clip[10];
   frustum[4][3] = clip[15] - clip[14];

   /* Normalize the result */
   t = sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
   frustum[4][0] /= t;
   frustum[4][1] /= t;
   frustum[4][2] /= t;
   frustum[4][3] /= t;

   /* Extract the NEAR plane */
   frustum[5][0] = clip[ 3] + clip[ 2];
   frustum[5][1] = clip[ 7] + clip[ 6];
   frustum[5][2] = clip[11] + clip[10];
   frustum[5][3] = clip[15] + clip[14];

   /* Normalize the result */
   t = sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
   frustum[5][0] /= t;
   frustum[5][1] /= t;
   frustum[5][2] /= t;
   frustum[5][3] /= t;
}

bool PointInFrustum( float x, float y, float z )
{
   int p;

   for( p = 0; p < 6; p++ )
      if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= 0 )
         return false;
   return true;
}

bool SphereInFrustum1( float x, float y, float z, float radius )
{
   int p;

   for( p = 0; p < 6; p++ )
      if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= -radius )
         return false;
   return true;
}

float SphereInFrustum2( float x, float y, float z, float radius )
{
   int p;
   float d;

   for( p = 0; p < 6; p++ )
   {
      d = frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3];
      if( d <= -radius )
         return 0;
   }
   return d + radius;
}
ENDINLINE

FUNCTION CalcFrustum:
INLINE
ExtractFrustum();
ENDINLINE
ENDFUNCTION

FUNCTION IsPointInFrustum%: x#,y#,z#
INLINE
return PointInFrustum( x,y,z );
ENDINLINE
ENDFUNCTION

FUNCTION IsSphereInFrustum1%: x#,y#,z#,r#
INLINE
return SphereInFrustum1( x,y,z,r );
ENDINLINE
ENDFUNCTION

FUNCTION IsSphereInFrustum2#: x#,y#,z#,r#
INLINE
return SphereInFrustum2( x,y,z,r );
ENDINLINE
ENDFUNCTION


Just paste this into your project and it should work. I should say, that appart from a quick compile for errors this is untested.

There are 4 functions above...
   FUNCTION CalcFrustum:
   FUNCTION IsPointInFrustum%: x#,y#,z#
   FUNCTION IsSphereInFrustum1%: x#,y#,z#,r#
   FUNCTION IsSphereInFrustum2#: x#,y#,z#,r#


This is the main frustum calculation routine.
CalcFrustum()

Call this once per game loop to update the frustum calculation.


These are the test routines.
IsPointInFrustum()

Returns True if a point in within the frustum.

IsSphereInFrustum1()

Returns True is a sphere with radius of 'r#' is within the frustum.

IsSphereInFrustum2()

Returns False if your sphere is not within frustum, else it returns the distance from the front plane to the sphere. Handy for LoD calculations for example.


Just to say again, these are untested.


EDIT: I just realised that this wont compile on your system as it directly calls the OpenGL API (eg "glGetFloatv") from within the C. I have a C header file that I include with all my projects, in the "cmp" project option ("-include general.h") for all the various #Includes that I need for my in-line stuff, of which one of these is "gl.h", so GLB will throw up an error here. Just leave this and I'll get it up and running properly tomorrow, with a little luck. I suppose I could just convert it to GLBasic...
Title: Re: Point within viewing frustrum
Post by: matchy on 2012-Aug-26
That's cool and it's certainly something useful for reference or even learning. Nicely done!  :good:
Title: Re: Point within viewing frustrum
Post by: bigsofty on 2012-Aug-26
OK, here it is without the external header dependencies, again though, untested but it looks OK as far as I can see.

Code (glbasic) Select
INLINE
typedef unsigned int    GLenum;
typedef float           GLfloat;

#define GL_PROJECTION_MATRIX                    0x0BA7
#define GL_MODELVIEW_MATRIX                     0x0BA6
} extern "C" { void __stdcall glGetFloatv( GLenum pname , GLfloat *params );; }; namespace __GLBASIC__ {

float frustum[6][4];

void ExtractFrustum()
{
   float   proj[16];
   float   modl[16];
   float   clip[16];
   float   t;

   /* Get the current PROJECTION matrix from OpenGL */
   glGetFloatv( GL_PROJECTION_MATRIX, proj );

   /* Get the current MODELVIEW matrix from OpenGL */
   glGetFloatv( GL_MODELVIEW_MATRIX, modl );

   /* Combine the two matrices (multiply projection by modelview) */
   clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
   clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
   clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
   clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];

   clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
   clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
   clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
   clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];

   clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
   clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
   clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
   clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];

   clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
   clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
   clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
   clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];

   /* Extract the numbers for the RIGHT plane */
   frustum[0][0] = clip[ 3] - clip[ 0];
   frustum[0][1] = clip[ 7] - clip[ 4];
   frustum[0][2] = clip[11] - clip[ 8];
   frustum[0][3] = clip[15] - clip[12];

   /* Normalize the result */
   t = SQR( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] );
   frustum[0][0] /= t;
   frustum[0][1] /= t;
   frustum[0][2] /= t;
   frustum[0][3] /= t;

   /* Extract the numbers for the LEFT plane */
   frustum[1][0] = clip[ 3] + clip[ 0];
   frustum[1][1] = clip[ 7] + clip[ 4];
   frustum[1][2] = clip[11] + clip[ 8];
   frustum[1][3] = clip[15] + clip[12];

   /* Normalize the result */
   t = SQR( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] );
   frustum[1][0] /= t;
   frustum[1][1] /= t;
   frustum[1][2] /= t;
   frustum[1][3] /= t;

   /* Extract the BOTTOM plane */
   frustum[2][0] = clip[ 3] + clip[ 1];
   frustum[2][1] = clip[ 7] + clip[ 5];
   frustum[2][2] = clip[11] + clip[ 9];
   frustum[2][3] = clip[15] + clip[13];

   /* Normalize the result */
   t = SQR( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] );
   frustum[2][0] /= t;
   frustum[2][1] /= t;
   frustum[2][2] /= t;
   frustum[2][3] /= t;

   /* Extract the TOP plane */
   frustum[3][0] = clip[ 3] - clip[ 1];
   frustum[3][1] = clip[ 7] - clip[ 5];
   frustum[3][2] = clip[11] - clip[ 9];
   frustum[3][3] = clip[15] - clip[13];

   /* Normalize the result */
   t = SQR( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] );
   frustum[3][0] /= t;
   frustum[3][1] /= t;
   frustum[3][2] /= t;
   frustum[3][3] /= t;

   /* Extract the FAR plane */
   frustum[4][0] = clip[ 3] - clip[ 2];
   frustum[4][1] = clip[ 7] - clip[ 6];
   frustum[4][2] = clip[11] - clip[10];
   frustum[4][3] = clip[15] - clip[14];

   /* Normalize the result */
   t = SQR( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] );
   frustum[4][0] /= t;
   frustum[4][1] /= t;
   frustum[4][2] /= t;
   frustum[4][3] /= t;

   /* Extract the NEAR plane */
   frustum[5][0] = clip[ 3] + clip[ 2];
   frustum[5][1] = clip[ 7] + clip[ 6];
   frustum[5][2] = clip[11] + clip[10];
   frustum[5][3] = clip[15] + clip[14];

   /* Normalize the result */
   t = SQR( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] );
   frustum[5][0] /= t;
   frustum[5][1] /= t;
   frustum[5][2] /= t;
   frustum[5][3] /= t;
}

bool PointInFrustum( float x, float y, float z )
{
   int p;

   for( p = 0; p < 6; p++ )
      if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= 0 )
         return false;
   return true;
}

bool SphereInFrustum1( float x, float y, float z, float radius )
{
   int p;

   for( p = 0; p < 6; p++ )
      if( frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3] <= -radius )
         return false;
   return true;
}

float SphereInFrustum2( float x, float y, float z, float radius )
{
   int p;
   float d;

   for( p = 0; p < 6; p++ )
   {
      d = frustum[p][0] * x + frustum[p][1] * y + frustum[p][2] * z + frustum[p][3];
      if( d <= -radius )
         return 0;
   }
   return d + radius;
}
ENDINLINE

FUNCTION CalcFrustum:
INLINE
ExtractFrustum();
ENDINLINE
ENDFUNCTION

FUNCTION IsPointInFrustum%: x#,y#,z#
INLINE
return PointInFrustum( x,y,z );
ENDINLINE
ENDFUNCTION

FUNCTION IsSphereInFrustum1%: x#,y#,z#,r#
INLINE
return SphereInFrustum1( x,y,z,r );
ENDINLINE
ENDFUNCTION

FUNCTION IsSphereInFrustum2#: x#,y#,z#,r#
INLINE
return SphereInFrustum2( x,y,z,r );
ENDINLINE
ENDFUNCTION
Title: Re: Point within viewing frustrum
Post by: bigsofty on 2012-Aug-27
I actually found some time to test it within my framework and it worked well. I'll post a copy to the snippets forum now.
Title: Re: Point within viewing frustrum
Post by: Schranz0r on 2013-Oct-02
Sry Old Thread but i can need a bit of help!
I test the thing and it cuts a lot of things away... but the wrong ones.


I use PUSH- and POPMATRIX and rotation with an array of cubes, maybe this is my problem?!
See this thread here, maybe someone can help me to finger this out?!

http://www.glbasic.com/forum/index.php?topic=9499.msg82087#msg82087

Thx for the help  :good:
Title: Re: Point within viewing frustrum
Post by: Kitty Hello on 2013-Oct-04
Glget matrix might not work on all mobiles. Send me an email and I send a better solution.

Sent from my GT-N7100 using Tapatalk 4

Title: Re: Point within viewing frustrum
Post by: bigsofty on 2013-Oct-06
This does work on my own couple of tablets I tried it on but I am sure Gernot will supply a superior solution. ;)
Title: Re: Point within viewing frustrum
Post by: kanonet on 2013-Oct-06
I would like to see Gernots solution posted here.
Title: Re: Point within viewing frustrum
Post by: Schranz0r on 2013-Oct-06
I will see a solution :D

Download the last post Rarfile in the Voxelthread!