I’m having some trouble trying to extract the frustum planes from a projection matrix. I seem to only be able to correctly extract planes from symmetric perspective projection matricies centered on the origin.
I’ve read through a tutorial online about this, and also gone over the plane extraction code in Xith3D. While I can reproduce the results that Xith3D provides, even the Xith3D code seems to only work for the special case of symmetric, centered perspective matricies.
To save time, the code I’m posting below is the frustum planes extraction routine from Xith3D, and my own function to test the Frustum.extract() function. I was under the impression that this extraction routine would work with an arbitrary projection matrix in any orientation in space. Is it true that it only works in the special case I described above? Is there a general purpose planes extraction routine what would handle orthogonal projections and arbitrary orientations as well?
/**
* Extract the frustum from the incoming projections and modelview matrices.
* Creation date: (04/02/2001 23:25:36)
*/
public void extract(Matrix4f proj, Matrix4f modl) {
clip.set(proj);
clip.mul(proj,modl);
// Now get the frustum's 6 clipping planes
// Extract the numbers for the RIGHT plane
plane[0].normal.x = clip.m03 - clip.m00;
plane[0].normal.y = clip.m13 - clip.m10;
plane[0].normal.z = clip.m23 - clip.m20;
plane[0].d = clip.m33 - clip.m30;
// Extract the numbers for the LEFT plane
plane[1].normal.x = clip.m03 + clip.m00;
plane[1].normal.y = clip.m13 + clip.m10;
plane[1].normal.z = clip.m23 + clip.m20;
plane[1].d = clip.m33 + clip.m30;
// Extract the BOTTOM plane
plane[2].normal.x = clip.m03 + clip.m01;
plane[2].normal.y = clip.m13 + clip.m11;
plane[2].normal.z = clip.m23 + clip.m21;
plane[2].d = clip.m33 + clip.m31;
/// Extract the TOP plane
plane[3].normal.x = clip.m03 - clip.m01;
plane[3].normal.y = clip.m13 - clip.m11;
plane[3].normal.z = clip.m23 - clip.m21;
plane[3].d = clip.m33 - clip.m31;
// Extract the FAR plane
plane[4].normal.x = clip.m03 - clip.m02;
plane[4].normal.y = clip.m13 - clip.m12;
plane[4].normal.z = clip.m23 - clip.m22;
plane[4].d = clip.m33 - clip.m32;
// Extract the NEAR plane
plane[5].normal.x = clip.m03 + clip.m02;
plane[5].normal.y = clip.m13 + clip.m12;
plane[5].normal.z = clip.m23 + clip.m22;
plane[5].d = clip.m33 + clip.m32;
// Normalize all the planes
for (int i = 0; i < 6; i++) {
plane[i].normalize();
//plane[i].d += error;
}
//System.out.println(this);
}
public FrustumFrame()
{
Transform3D xform = new Transform3D();
// xform.ortho(0, 4, 0, 4, 0, 4);
xform.perspective((float)Math.toRadians(90), 1, 1, 1000);
//Apply a modelview camer change
Transform3D modelView = new Transform3D();
modelView.setTranslation(new Vector3f(10, 0, 0));
xform.mul(modelView);
Matrix4f mat = xform.getMatrix4f();
System.err.println("" + mat);
Matrix4f identity = new Matrix4f();
identity.setIdentity();
Frustum frustum = new Frustum();
frustum.extract(mat, identity);
System.err.println("" + frustum);
}