Tuesday April 16, 2024

 The Maths of 3D You can't have 3D without a little maths...

Frustum Culling

by bkenwright@xbdev.net

So what is a Viewing Frustum, and how will it help us with our 3D rendering?  Well its a very simple concept, but it can soon get very complicated with maths.  Its so we only render vertices which are within a specified field of view...usually our view...which is a pyrimid type shape.

Now in DirectX, when we set the Projection View, we are in effect setting the clipping region for our view, but its testing all our vertices....so if we have a 1000 vertices, it will test each one...and only render the one's in our frustum.

If we group our vertices into groups of 100, and then only test there center points....we only need to render vertices in that group...which makes things more efficient now!

Split the world into groups of vertices for each part...then for each group...have a centre point....and we check that centre point, and only render it if its in our frustum.

Now its worth demonstrating this with a piece of code, how would we do this in DirectX3D...easy with the help of matrix's

 //////////////////////////////////////////////////////////////////////////////////// //                                                                                \\ // This is a simple Frustum Function, which is for DirectX3D, its used for       \\ // tutorial purposes, and demonstrates how you can implement the Frustum Check    \\ // using DirectX.  How it works is, you pass in the coordinate for the vertex     \\ // point your checking, then if its in the frustum, it will return true, else it  \\ // not, so will return false....and you can take the appropriate action.           \\ //                                                                                \\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/   bool FrustrumCheck(float x, float y, float z) {       D3DXMATRIX matWorld, matView, matProjection;         g_pd3dDevice->GetTransform(D3DTS_WORLD, &matWorld);       g_pd3dDevice->GetTransform(D3DTS_VIEW,  &matView);       //g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &matProjection);       // I chaned this line, so you could change the projection view here, adjusting       // the near and far plane...alternatively you can just use the GetTransform       // DX call, and use the pre-set one.       D3DXMatrixPerspectiveFovLH( &matProjection, D3DX_PI/2, 1.0f, 1.0f, 30.0f );         D3DXMATRIX Cull = matWorld * matView * matProjection;         D3DXVECTOR4 vNode = D3DXVECTOR4(x,y,z,1);         D3DXVECTOR4 vTestVert;       D3DXVec4Transform(&vTestVert, &vNode, &Cull);         if( abs_f(vTestVert.x) > abs_f(vTestVert.w) ) // Outside our X Frustum Plane             return false;         if( abs_f(vTestVert.y) > abs_f(vTestVert.w) ) // Outside our Y Frustum Plane             return false;         if( (vTestVert.z<0.0f) || (vTestVert.z>vTestVert.w)) // Outside our z Frustum Plane             return false;         return true; }

The formula you should memorize by heart is the distance from a point on a plane to the origin:

A.x + B.y + C.z + D = 0

Where:

ABC is our plane normal.

xyz is our point on the plane

D is the distance to the origin.

To be continued.....................