# My frustum culling is culling from the wrong point

I'm having problems with my frustum being in the wrong origin. It follows the rotation of my camera but not the position.

In my camera class I'm generating a view-matrix:

void Camera::Update()
{
UpdateViewMatrix();

glMatrixMode(GL_MODELVIEW);
}


Then extracting the planes using the projection matrix and modelview matrix:

void UpdateFrustum()
{
Matrix4x4 projection, model, clip;

glGetFloatv(GL_PROJECTION_MATRIX, projection.m);
glGetFloatv(GL_MODELVIEW_MATRIX, model.m);

clip = model * projection;

m_Planes[RIGHT] = clip.m[ 3] - clip.m[ 0];
m_Planes[RIGHT] = clip.m[ 7] - clip.m[ 4];
m_Planes[RIGHT] = clip.m - clip.m[ 8];
m_Planes[RIGHT] = clip.m - clip.m;
NormalizePlane(RIGHT);

m_Planes[LEFT] = clip.m[ 3] + clip.m[ 0];
m_Planes[LEFT] = clip.m[ 7] + clip.m[ 4];
m_Planes[LEFT] = clip.m + clip.m[ 8];
m_Planes[LEFT] = clip.m + clip.m;
NormalizePlane(LEFT);

m_Planes[BOTTOM] = clip.m[ 3] + clip.m[ 1];
m_Planes[BOTTOM] = clip.m[ 7] + clip.m[ 5];
m_Planes[BOTTOM] = clip.m + clip.m[ 9];
m_Planes[BOTTOM] = clip.m + clip.m;
NormalizePlane(BOTTOM);

m_Planes[TOP] = clip.m[ 3] - clip.m[ 1];
m_Planes[TOP] = clip.m[ 7] - clip.m[ 5];
m_Planes[TOP] = clip.m - clip.m[ 9];
m_Planes[TOP] = clip.m - clip.m;
NormalizePlane(TOP);

m_Planes[NEAR] = clip.m[ 3] + clip.m[ 2];
m_Planes[NEAR] = clip.m[ 7] + clip.m[ 6];
m_Planes[NEAR] = clip.m + clip.m;
m_Planes[NEAR] = clip.m + clip.m;
NormalizePlane(NEAR);

m_Planes[FAR] = clip.m[ 3] - clip.m[ 2];
m_Planes[FAR] = clip.m[ 7] - clip.m[ 6];
m_Planes[FAR] = clip.m - clip.m;
m_Planes[FAR] = clip.m - clip.m;
NormalizePlane(FAR);
}

void NormalizePlane(int side)
{
float length =  1.0/(float)sqrt(m_Planes[side] * m_Planes[side] +
m_Planes[side] * m_Planes[side] +
m_Planes[side] * m_Planes[side]);

m_Planes[side] *= length;
m_Planes[side] *= length;
m_Planes[side] *= length;
m_Planes[side] *= length;
}


And check against it with:

bool PointInFrustum(float x, float y, float z)
{
for(int i = 0; i < 6; i++)
{
if( m_Planes[i] * x + m_Planes[i] * y + m_Planes[i] * z + m_Planes[i] <= 0 )
return false;
}
return true;
}


Then i render using:

camera->Update();
UpdateFrustum();

int numCulled = 0;

for(int i = 0; i < (int)meshes.size(); i++)
{
if(!PointInFrustum(meshCenter.x, meshCenter.y, meshCenter.z))
{
meshes[i]->SetDraw(false);
numCulled++;
}
else
meshes[i]->SetDraw(true);
}


Matrices look like (Camera is at (5, 0, 0)):

ModelView
[0,0,0.99,0] [0,1,0,0] [-0.99,0,0,0] [0,0,-5,1]

Projection
[0.814,0,0,0] [0,1.303,0,0] [0,0,-1,0] [0,0,-0.02,0]

Clip
[0,0,-1,-0.999] [0,1.30,0,0] [-0.814,0,0,0] [0,0,4.98,4.99]


What am I doing wrong?

• Can you output some of the matrices view,proj & clip? Just to check that they have the expected orientation... – Aki Suihkonen Oct 30 '12 at 17:41
• Hmm. If your camera is at x=5,y=z=0, then why does the MV matrix have -5 at the 'z' location? – Aki Suihkonen Oct 31 '12 at 6:57
• Hi @Xbetas - you don't need to put "SOLVED" in your title. Just make sure you mark the answer you posted as the accepted answer when you can, and your question will be marked as having an accepted answer (though still this won't appear in the title). – doppelgreener Oct 31 '12 at 14:00

It appeared that the points i were testing against had not been scaled, while the render code had. So it was working all along, but the change was too small to see!

  makePlane(m+m,m+m,m+m,m+m); // left plane

function makePlane(a,b,c,d) {
s=1.0/Math.sqrt(a*a+b*b+c*c);
return [a*s,b*s,c*s,d*s]
// NOT return [a/s,b/s,c/s,d/s]  ...
}


BTW, if you are only clipping single points, then a more efficient method is to calculate [x,y,z,1] * clip_matrix -> [X,Y,Z,W] and to check that |X|<|W|, |Y|<|W|,|Z|<|W|.

I'm justifying using 'makePlane' approach because I cull axis aligned bounding boxes and have something more in the makePlane routine that makes the frustumCulling function to choose a single corner of the boundingbox per clipping plane.

• I have tried to do so, but the fourth value is right on the planes when i normalize the distance too. – Xbetas Oct 30 '12 at 16:54
• sorry for the confusion. That fragment up there is from my working application. – Aki Suihkonen Oct 30 '12 at 17:08
• That gives the exact same result as i had before. – Xbetas Oct 30 '12 at 17:28