• Advertisement
Sign in to follow this  

Problem with view frustrum culling/clipping

This topic is 4591 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

Hi ALL, I’m hoping someone can help. A few weeks ago I posted a request on how to setup clipping planes relative to the view/projection matrix and I received a couple of replies with two formulas for clipping. I’ve implemented both, and both are producing the same results, so I assume I’m doing something wrong, but I can’t figure it out. Let me explain what/how I’ve applied your formula and maybe someone can see something where my logic is flawed. To start with I define the projection matrix based on the resolution and set it when ever the screen changes (full screen/window toggle). I save this in a variable for later use by the clipping pane. Next, my camera is at the point of view of the player, so my view matrix is the INVERSE of the players location matrix. Every frame I set the camera as the players inverse, and when I do save that view matrix into a variable for later use in the clipping plane. Every frame I call my function (2 different ones supplied on this forum) for creating a plane for the 6 sides of the viewing frustrum. However, for my clipping tests, I’m only using the LEFT and RIGHT planes. My object to clip is a piece of my terrain, so it is flat (not a box, but more like a piece of paper. I check the 4 corners of the terrain cell (PAPER) using a distance to plane calculation, looking for “positive” values. The points are in world space. I’ve tried to convert them to camera space but the results are worse, so for now the points are in world space and I seem to be getting 99% accurate culling. If any one of the 4 points of the paper (corners) is >= than the left clipping plane, and any of the 4 points of the paper is <= than the right clipping plane, then some portion of the paper must be visible, so render the paper (terrain cell). In other words, if any point is visible, or if the points are beyond BOTH sides making the center of the paper visible, then render the paper (terrain cell). This works 99% of the time, and I’ve actually printed a map to show me what is rendering and what isn’t, and as I turn and navigate it seems to be working right, except that 1%. Here is what the map looks like when I’m facing north: 11111 01110 00100 00000 00000 Everything seems to be right, but obviously I’ve got something wrong somewhere, and was hoping maybe someone would see something I might have missed? Sometimes it's even the cell I'm standing on the culls out, and other times it's neighboring cells. Thanks, Quad

Share this post

Link to post
Share on other sites
I cant be sure because i dont have the code but it could be that you have your close clipping plane set to 0. It could also be that your far plane is too far away and that would create inaccuracies.

Please post the actual code so that we can get a better idea.

Share this post

Link to post
Share on other sites
Here is the code. Also, I discovered something new, which is making me lean towards the distance check. I discovered if I set my distance check to be
>= -100 instead of >= 0, everythin seems to work, so there is some inacuracy between by distance check math of my plane creation.

This is the projection:

float minz = 1.0f;
float maxz = 18000.0f;

float fAspect = pBackBufferSurfaceDesc-&gt;Width / (FLOAT)pBackBufferSurfaceDesc-&gt;Height;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, minZ, maxZ );
pd3dDevice-&gt;SetTransform( D3DTS_PROJECTION, &matProj );

This is plane creation:

void MU3DMATH_CreateClippingTest( D3DXMATRIX &matView, D3DXMATRIX &matProj, D3DXPLANE *FrustumPlanes)

//0. Variables:
D3DXVECTOR3 vecFrustum[8];

//1. multiply the matrices together
//D3DXMatrixInverse( &mat, NULL, &matView );
D3DXMatrixMultiply( &mat, &matView, &matProj );
D3DXMatrixInverse( &mat, NULL, &mat );
//MU3DMath_MatrixInvert(mat, mat );

//2. create the 8 points of a cube in unit-space
vecFrustum[0] = D3DXVECTOR3(-1.0f, -1.0f, 0.0f); // xyz
vecFrustum[1] = D3DXVECTOR3( 1.0f, -1.0f, 0.0f); // Xyz
vecFrustum[2] = D3DXVECTOR3(-1.0f, 1.0f, 0.0f); // xYz
vecFrustum[3] = D3DXVECTOR3( 1.0f, 1.0f, 0.0f); // XYz
vecFrustum[4] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f); // xyZ
vecFrustum[5] = D3DXVECTOR3( 1.0f, -1.0f, 1.0f); // XyZ
vecFrustum[6] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f); // xYZ
vecFrustum[7] = D3DXVECTOR3( 1.0f, 1.0f, 1.0f); // XYZ

//3. transform all 8 points by the view/proj matrix. Doing this
// gives us that ACTUAL 8 corners of the frustum area.
for( int i = 0; i &lt; 8; i++ )
D3DXVec3TransformCoord( &vecFrustum, &vecFrustum, &mat );

//4. generate and store the 6 planes that make up the frustum
D3DXPlaneFromPoints( &FrustumPlanes[0], &vecFrustum[2],
&vecFrustum[6], &vecFrustum[4] ); // Left

D3DXPlaneFromPoints( &FrustumPlanes[1], &vecFrustum[7],
&vecFrustum[3], &vecFrustum[5] ); // Right

D3DXPlaneFromPoints( &FrustumPlanes[2], &vecFrustum[2],
&vecFrustum[3], &vecFrustum[6] ); // Top

D3DXPlaneFromPoints( &FrustumPlanes[3], &vecFrustum[1],
&vecFrustum[0], &vecFrustum[4] ); // Bottom

D3DXPlaneFromPoints( &FrustumPlanes[4], &vecFrustum[0],
&vecFrustum[1], &vecFrustum[2] ); // Near

D3DXPlaneFromPoints( &FrustumPlanes[5], &vecFrustum[6],
&vecFrustum[7], &vecFrustum[5] ); // Far


This is the distance check:

float MU3DMATH_GetDistanceToPoint( D3DXPLANE & plane, D3DVECTOR & pt)
return plane.a*pt.x + plane.b*pt.y + plane.c*pt.z + plane.d;

This is another distance check I was using:

MUfloat MU3DMATH_GetDistance_old(D3DXPLANE &p, D3DVECTOR &r) //must be unitized!

VECTOR v,v0;

v.x = r.x;
v.y = r.y;
v.z = r.z;

v0.x = p.a;
v0.y = p.b;
v0.z = p.c;

return (float)(((float)D3DXVec3Dot(&v0,&v)) - (float)p.d) ;

Share this post

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

  • Advertisement