What am I missing? (bounding sphere vs frustum)

I’m trying to test a sphere against the current view frustum. I can test a single point accurately by calculating its distance from each plane, but when I try to compare it against the sphere’s radius it doesn’t work. It seems that the “distance” I’m getting needs to be scaled or something.

I call this function each time my “camera” moves or changes FOV, etc. It grabs the current frustum plane equations and puts them into a global array called ‘frustum’:

void extractfrustum()
{
int i;
GLfloat proj[16];
GLfloat modl[16];
double clip[16];
double m0, m1, m2, m3;

// Get current matricies
glGetFloatv( GL_PROJECTION_MATRIX, proj );
glGetFloatv( GL_MODELVIEW_MATRIX, modl );

// Combine them
for( i = 0; i < 4; i++ )
{
m0 = modl[i * 4 + 0];
m1 = modl[i * 4 + 1];
m2 = modl[i * 4 + 2];
m3 = modl[i * 4 + 3];
clip[i * 4 + 0] = m0 * proj[0] + m1 * proj[4] + m2 * proj[8] + m3 * proj[12];
clip[i * 4 + 1] = m0 * proj[1] + m1 * proj[5] + m2 * proj[9] + m3 * proj[13];
clip[i * 4 + 2] = m0 * proj[2] + m1 * proj[6] + m2 * proj[10] + m3 * proj[14];
clip[i * 4 + 3] = m0 * proj[3] + m1 * proj[7] + m2 * proj[11] + m3 * proj[15];
}

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];

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];

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];

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];

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];

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];
}

And here’s a function to test if a single point is within the current frustum:

bool testpoint( float x, float y, float z )
{
int i;
float distance;

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

This works. I can change my viewing angle and location and fov all I want and the test remains accurate.

Now, I would have thought that to test a sphere all I’d have to do is change the distance test to something like this (keep in mind I just want to know if any part of the sphere is in the frustum, I don’t need to differentiate between partial and full inclusion):

  if( distance < radius )
     return false;

but that doesn’t work. Any ideas what I’m missing here? I suspect it’s something trivial.

Toom

Assuming your math is right for the single-
point case (because you say it works, I
didn’t check it :slight_smile:

Wouldn’t that be “distance < -radius” because
you want a sphere whose center is outside
the frustum to still test true as long as
some part is inside?

Heh, well I’m assuming my math is correct… I draw the point no matter what, and display the result of the test function on screen with text. It indicates a true value whenever the point is visible, and false whenever it isn’t. I’ve tested it with FOV values from 1 to 180, and different viewport sizes, and different near and far planes. Seems to be bang on.

So it’d work just fine for testing the corners of a bounding box, but the distance value I get doesn’t seem to relate to anything obvious. For the test to actually work for a sphere I’d have to compare it to something like 2.6 times the radius, not the actual radius.

I figure I’m messing up something simple somewhere, I just can’t put my finger on it yet…

Toom

Nailed it - just needed to normalize the plane equations. I now have accurate frustum tests for points, spheres, and boxes.

Toom