0
\$\begingroup\$

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);
    //glLoadIdentity();
    glLoadMatrixf(GetViewMatrix().m);
}

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][0] = clip.m[ 3] - clip.m[ 0];
    m_Planes[RIGHT][1] = clip.m[ 7] - clip.m[ 4];
    m_Planes[RIGHT][2] = clip.m[11] - clip.m[ 8];
    m_Planes[RIGHT][3] = clip.m[15] - clip.m[12];
    NormalizePlane(RIGHT);

    m_Planes[LEFT][0] = clip.m[ 3] + clip.m[ 0];
    m_Planes[LEFT][1] = clip.m[ 7] + clip.m[ 4];
    m_Planes[LEFT][2] = clip.m[11] + clip.m[ 8];
    m_Planes[LEFT][3] = clip.m[15] + clip.m[12];
    NormalizePlane(LEFT);

    m_Planes[BOTTOM][0] = clip.m[ 3] + clip.m[ 1];
    m_Planes[BOTTOM][1] = clip.m[ 7] + clip.m[ 5];
    m_Planes[BOTTOM][2] = clip.m[11] + clip.m[ 9];
    m_Planes[BOTTOM][3] = clip.m[15] + clip.m[13];
    NormalizePlane(BOTTOM);

    m_Planes[TOP][0] = clip.m[ 3] - clip.m[ 1];
    m_Planes[TOP][1] = clip.m[ 7] - clip.m[ 5];
    m_Planes[TOP][2] = clip.m[11] - clip.m[ 9];
    m_Planes[TOP][3] = clip.m[15] - clip.m[13];
    NormalizePlane(TOP);

    m_Planes[NEAR][0] = clip.m[ 3] + clip.m[ 2];
    m_Planes[NEAR][1] = clip.m[ 7] + clip.m[ 6];
    m_Planes[NEAR][2] = clip.m[11] + clip.m[10];
    m_Planes[NEAR][3] = clip.m[15] + clip.m[14];
    NormalizePlane(NEAR);

    m_Planes[FAR][0] = clip.m[ 3] - clip.m[ 2];
    m_Planes[FAR][1] = clip.m[ 7] - clip.m[ 6];
    m_Planes[FAR][2] = clip.m[11] - clip.m[10];
    m_Planes[FAR][3] = clip.m[15] - clip.m[14];
    NormalizePlane(FAR);
}

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

    m_Planes[side][0] *= length;
    m_Planes[side][1] *= length;
    m_Planes[side][2] *= length;
    m_Planes[side][3] *= 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][0] * x + m_Planes[i][1] * y + m_Planes[i][2] * z + m_Planes[i][3] <= 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?

\$\endgroup\$
3
  • \$\begingroup\$ Can you output some of the matrices view,proj & clip? Just to check that they have the expected orientation... \$\endgroup\$ Oct 30, 2012 at 17:41
  • \$\begingroup\$ Hmm. If your camera is at x=5,y=z=0, then why does the MV matrix have -5 at the 'z' location? \$\endgroup\$ Oct 31, 2012 at 6:57
  • \$\begingroup\$ 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). \$\endgroup\$ Oct 31, 2012 at 14:00

2 Answers 2

2
\$\begingroup\$

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!

\$\endgroup\$
0
\$\begingroup\$
  makePlane(m[3]+m[0],m[7]+m[4],m[11]+m[8],m[15]+m[12]); // 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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .