Extract clip planes from projection matrix

I have a projection matrix and I want to derive the clip planes from it. In particular I only care about the near and far planes if it makes it any easier.

Is there a way to do this?

-Steve

1 Like

Think about it this way. If you tried rendering the actual viewing frustum, the rendering process would wind up with a unit cube in screen space, each side of the cube lining up with the viewport’s left, right, top, and bottom and near and far clip planes.

So if you take a unit cube and transform it by the inverse of the projection matrix (plus modelview, if you want worldspace), you’d get a “cube” that’s warped into the shape of the viewing frustum.

Similarly, you can take any part of that cube, any plane or vector in image space and transform it by the inverse of the viewing transform to get it in eye (or world) space.

If its code your are looking for, here is an example:

	// Construct frustum from modelview-projection transformation.
	template <typename Scalar>
	inline
	void Frustum3<Scalar>::set( const Transformation4<Scalar>& mvp )
	{
		// Right clipping plane.
		mPlanes[0].set( mvp[3]-mvp[0], mvp[7]-mvp[4], mvp[11]-mvp[8], mvp[15]-mvp[12] );
		// Left clipping plane.
		mPlanes[1].set( mvp[3]+mvp[0], mvp[7]+mvp[4], mvp[11]+mvp[8], mvp[15]+mvp[12] );
		// Bottom clipping plane.
		mPlanes[2].set( mvp[3]+mvp[1], mvp[7]+mvp[5], mvp[11]+mvp[9], mvp[15]+mvp[13] );
		// Top clipping plane.
		mPlanes[3].set( mvp[3]-mvp[1], mvp[7]-mvp[5], mvp[11]-mvp[9], mvp[15]-mvp[13] );
		// Far clipping plane.
		mPlanes[4].set( mvp[3]-mvp[2], mvp[7]-mvp[6], mvp[11]-mvp[10], mvp[15]-mvp[14] );
		// Near clipping plane.
		mPlanes[5].set( mvp[3]+mvp[2], mvp[7]+mvp[6], mvp[11]+mvp[10], mvp[15]+mvp[14] );

		// Normalize, this is not always necessary...
		for( unsigned int i = 0; i < 6; i++ )
		{
			mPlanes[i].normalize();
		}
	}

This snippet deserves some explanation. Frustum3 is a class that holds 6 planes, the clipping planes. The member function shown above, “set”, takes a modelview-projection matrix as input. The elements of the matrix are accessed in column major order (standard OpenGL-order). The “set”-methods of the planes sets the coefficients a,b,c,d of the planes. After the planes have been set you may or may not wish to normalize them, this depends if you want measure distances from points to the planes, or if you are simply interested in which side of a plane a point is on. Happy to answer any further questions…

I think it’s possible that I understand what the code does and how to make use of it for what I want – but it’s certainly possible that I don’t.

I probably wasn’t very clear in my original question, so maybe I will start there.

Let’s say you have some code:

double l,r,t,b,n,f; /* initialized to sane values */
glMatrixMode(GL_PROJECTION);
glLoadItendity();
glFrustum(l,r,t,b,n,f);

We now have a “normal” projection matrix on the top of the stack (ie no modelview munged with it, etc). I want to inspect it and determine what value for the near clipping plane was used to construct it.

If I understand your code snippet correctly, I can get the coefficients to the standard plane equation and then use that to compute near.

The A and B coefficients are zero for a standard projection matrix produced by glFrustum, so I am left with C and D, so I can solve:

Cz + D = 0 in terms of z…which will be the value of my near clipping plane.

If it’s that easy, I will be pretty happy.

Do I get to be happy?

-Steve

Stephen, you said you wanted the clip planes, and that’s what you got!

However, if you want to extract the parameters you passed to glFrustum (which simply sets up a projection matrix) that is a bit different.

I believe that if you extract the planes using the method I described in my previous post, then then near and far are simply the D-coefficients of the near and far plane. At least I think so. You could perhaps test and confirm it?