Jump to content
  • Advertisement
Sign in to follow this  

Extracting View Frustum Planes

This topic is 675 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i am working on a 3D soft engine written from scratch and i am attempting to extract the view frustum planes so i will be able to do view frustum culling, clipping, etc. However i am not getting the correct results and i cannot seem to solve it. I am attempting to extract the planes from my view-projection matrix using a method described here http://www.txutxi.com/?p=444. Firstly i multiply the view and projection matrix together and then input that result into a method to extract the planes as follows: 

public Plane[] extractPlanes(double[][] m){
		Plane l,r,t,b,n,f;
		l=new Plane(m[0][0]+m[3][0], m[0][1]+m[3][1], m[0][2]+m[3][2], m[0][3]+m[3][3]);
		r=new Plane(m[3][0]-m[0][0], m[3][1]-m[0][1], m[3][2]-m[0][2], m[3][3]-m[0][3]);
		t=new Plane(m[3][0]-m[1][0], m[3][1]-m[1][1], m[3][2]-m[1][2], m[3][3]-m[1][3]);
		b=new Plane(m[1][0]+m[3][0], m[1][1]+m[3][1], m[1][2]+m[3][2], m[1][3]+m[3][3]);
		n=new Plane(m[2][0]+m[3][0], m[2][1]+m[3][1], m[2][2]+m[3][2], m[2][3]+m[3][3]);
		f=new Plane(m[3][0]-m[2][0], m[3][1]-m[2][1], m[3][2]-m[2][2], m[3][3]-m[2][3]);
		return new Plane[]{l,r,t,b,n,f};

the plane constructor i am using is as follows, however i am not sure if i am constructing a plane correctly from the values that i am obtaining, clarification would also be welcome: 

public Plane(double a, double b, double c, double d){
		Vector3 p0=new Vector3(-d/a,0,0);
		Vector3 p1 = new Vector3(0,-d/b, 0);
		Vector3 p2 = new Vector3(0,0,-d/c);
		this.normal = Vector3.subtract(p2, p1).cross(Vector3.subtract(p0,p1)); 
		this.normal = this.normal.normalize();
		this.distance = -this.normal.dot(p1);

finally, i am aware that both my projection and view matrices are correct, and that they are multiplied together correctly but my Plane extracting method may be using the wrong column-order so i will attach both the projection matrix and the view matrix methods as well:

 public static double[][] perspectiveProjection(double fovx, double fovy, double near, double far){
		 double[][] m = new double[4][4];
		 for (double[] row: m){
			    Arrays.fill(row, 0);
		 m[0][0]= 1/Math.tan(fovx/2);
		 m[1][1]= 1/Math.tan(fovy/2);
		 m[2][2]= -1*(far+near)/(far-near);
		 return m;

	public static double[][] fpsViewRH(Vector3 eye, double pitch, double yaw ){
		//the pitch and yaw values need to have been converted to radians
	    double cosPitch = Math.cos(pitch);
	    double sinPitch = Math.sin(pitch);
	    double cosYaw = Math.cos(yaw);
	    double sinYaw = Math.sin(yaw);
	    Vector3 xaxis = new Vector3(cosYaw, 0, -sinYaw);
	    Vector3 yaxis = new Vector3( sinYaw * sinPitch, cosPitch, cosYaw * sinPitch);
	    Vector3 zaxis = new Vector3(sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw);
	    // Create a 4x4 view matrix from the right, up, forward and eye position vectors
	    double[][] viewMatrix = new double[4][4];

	    viewMatrix[0][0]=xaxis.x; viewMatrix[0][1]=yaxis.x; viewMatrix[0][2]=zaxis.x; viewMatrix[0][3]=0;
            viewMatrix[1][0]=xaxis.y; viewMatrix[1][1]=yaxis.y; viewMatrix[1][2]=zaxis.y; viewMatrix[1][3]=0;
        viewMatrix[2][0]=xaxis.z; viewMatrix[2][1]=yaxis.z; viewMatrix[2][2]=zaxis.z; viewMatrix[2][3]=0;
        viewMatrix[3][0]=-xaxis.dot(eye); viewMatrix[3][1]= -yaxis.dot(eye); viewMatrix[3][2]= -zaxis.dot(eye); viewMatrix[3][3]=1;
        return viewMatrix;

If anybody understands where i have gone wrong, help would be appreciated, thank you.

Edited by WTD3933

Share this post

Link to post
Share on other sites

my Plane extracting method may be using the wrong column-order

This would be my guess. Your plane extraction code looks right to me. How do you know the planes aren't correct? The way the incorrect behavior shows itself could be a clue for what is wrong. Edited by HappyCoder

Share this post

Link to post
Share on other sites

Just a side note for view frustum culling or occlusion culling implementations. Always test this with 2-viewports. One is from the camera. Another one is F.e. top or side view of whole scene - render also frustum planes into it and use frustum culling from the camera (e.g. you will see just the objects, the first camera actually renders).


This was kind of helpful to me when implementing view frustum culling and few occlusion culling attempts - as this allows you to determine whether your algorithm is correct or wrong.

Share this post

Link to post
Share on other sites

If anybody understands where i have gone wrong, help would be appreciated, thank you.


its less work for me to post my working code and let you figure it out.   this code came from a combo of ratertek and another source online. both had bugs.  between the two i got a complete set of working code.

// const float SCREEN_DEPTH = 1000.0f;           // ROCKLAND: the far clip plane distance

D3DXPLANE m_planes[6];        // ROCKLAND: the frustum planes
D3DXPLANE m_planes2[6];        // ROCKLAND: the frustum planes.  frustum rotated only.

// ROCKLAND: screenDepth = the far clip plane distance
// ROCKLAND: projectionMatrix = the current projection matrix 
// ROCKLAND: viewMatrix = the current view matrix 

// ROCKLAND: Z3D equivalents:
// ROCKLAND: screenDepth = (float)Zfarplane
// ROCKLAND: projectionMatrix = Zprojection_matrix
// ROCKLAND: viewMatrix = ZmView

void Zcalc_frustum_planes()
//float   //screenDepth,                // ROCKLAND:  far plane
        //zMinimum,                   // ROCKLAND: near plane
        //r;                          // ROCKLAND:    far / far-near
D3DXMATRIX  projectionMatrix,       // ROCKLAND: copy of current projection matrix
            viewMatrix,             // ROCKLAND: copy of current view matrix
            matrix;                 // ROCKLAND: frustum matrix  ( view * modified proj )

// ROCKLAND: copy Z3D values into the local vars used by this code.
projectionMatrix = Zprojection_matrix;
viewMatrix = ZmView;
// Calculate the minimum Z distance in the frustum.
zMinimum = -projectionMatrix._43 / projectionMatrix._33;
r = screenDepth / (screenDepth - zMinimum);
projectionMatrix._33 = r;
projectionMatrix._43 = -r * zMinimum;
// Create the frustum matrix from the view matrix and updated projection matrix.

D3DXMatrixMultiply(&matrix, &viewMatrix, &projectionMatrix);

// Calculate left plane of frustum.
m_planes[2].a = matrix._14 + matrix._11; 
m_planes[2].b = matrix._24 + matrix._21;
m_planes[2].c = matrix._34 + matrix._31;
m_planes[2].d = matrix._44 + matrix._41;
D3DXPlaneNormalize(&m_planes[2], &m_planes[2]);

// Calculate right plane of frustum.
m_planes[3].a = matrix._14 - matrix._11; 
m_planes[3].b = matrix._24 - matrix._21;
m_planes[3].c = matrix._34 - matrix._31;
m_planes[3].d = matrix._44 - matrix._41;
D3DXPlaneNormalize(&m_planes[3], &m_planes[3]);

// Calculate top plane of frustum.
m_planes[4].a = matrix._14 - matrix._12; 
m_planes[4].b = matrix._24 - matrix._22;
m_planes[4].c = matrix._34 - matrix._32;
m_planes[4].d = matrix._44 - matrix._42;
D3DXPlaneNormalize(&m_planes[4], &m_planes[4]);

// Calculate bottom plane of frustum.
m_planes[5].a = matrix._14 + matrix._12;
m_planes[5].b = matrix._24 + matrix._22;
m_planes[5].c = matrix._34 + matrix._32;
m_planes[5].d = matrix._44 + matrix._42;
D3DXPlaneNormalize(&m_planes[5], &m_planes[5]);

// Calculate near plane of frustum.
m_planes[0].a = matrix._13;        // matrix._14 + matrix._13;
m_planes[0].b = matrix._23;        // matrix._24 + matrix._23;
m_planes[0].c = matrix._33;        // matrix._34 + matrix._33;
m_planes[0].d = matrix._43;        // matrix._44 + matrix._43;
D3DXPlaneNormalize(&m_planes[0], &m_planes[0]);

// Calculate far plane of frustum.
m_planes[1].a = matrix._14 - matrix._13; 
m_planes[1].b = matrix._24 - matrix._23;
m_planes[1].c = matrix._34 - matrix._33;
m_planes[1].d = matrix._44 - matrix._43;
D3DXPlaneNormalize(&m_planes[1], &m_planes[1]);


Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!