Original Post
Hi all, I've tried to implement frustum culling, but im having problem with the far plane of the frustum. As explained in http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf and on the website www.toymaker.info im doing like this(using C++ and Direct3D): This is the code i use and it works fine for all the clipping planes except for the far one; i know that it doesnt work with the far clipping plane cause ive put a rendered objects counter in the render() loop and even if i go far away from the objects (so far that they arent visible cause they are more far than the value i have set in D3DXMatrixPerspectiveFovLH for the far plane) and i look in direction of them, they are counted as rendered objects. For all the others 5 planes it works fine. Is there something wrong in the code where i extract the far plane normal and distance from the ViewProjection matrix? Is there something wrong in the function that test the AABB against a plane? Is there another way to get the far clipping plane normal and distance? Maybe extracting them from the others planes? What have i to do to know where is the problem? I am really stuck with this. I do appreciate whatever helps. Thanks in advance Kev
struct TFrustumPlane /*Struct that define a frustum plane*/
{
D3DXVECTOR3 m_normal;
float m_distance;
inline void Normalise()
{
float denom = 1 / sqrt((m_normal.x*m_normal.x) + (m_normal.y*m_normal.y) + (m_normal.z*m_normal.z));
m_normal.x = m_normal.x * denom;
m_normal.y = m_normal.y * denom;
m_normal.z = m_normal.z * denom;
m_distance = m_distance * denom;
}
inline float DistanceToPoint(D3DXVECTOR3 &v)
{
return D3DXVec3Dot(&m_normal, &v) + m_distance;
}
};
TFrustumPlane m_frustumPlanes[6]; /* the 6 frustum planes */
void ExtractPlanes(void) /* Function that extract the 6 planes */
{ /* and store each of them in */
D3DXMATRIXA16 matComb; /* a TFrustumPlane */
D3DXMatrixMultiply(&matComb, &viewMatrix, &projectionMatrix);
// Left clipping plane
m_frustumPlanes[0].m_normal.x = matComb._14 + matComb._11;
m_frustumPlanes[0].m_normal.y = matComb._24 + matComb._21;
m_frustumPlanes[0].m_normal.z = matComb._34 + matComb._31;
m_frustumPlanes[0].m_distance = matComb._44 + matComb._41;
// Right clipping plane
m_frustumPlanes[1].m_normal.x = matComb._14 - matComb._11;
m_frustumPlanes[1].m_normal.y = matComb._24 - matComb._21;
m_frustumPlanes[1].m_normal.z = matComb._34 - matComb._31;
m_frustumPlanes[1].m_distance = matComb._44 - matComb._41;
// Top clipping plane
m_frustumPlanes[2].m_normal.x = matComb._14 - matComb._12;
m_frustumPlanes[2].m_normal.y = matComb._24 - matComb._22;
m_frustumPlanes[2].m_normal.z = matComb._34 - matComb._32;
m_frustumPlanes[2].m_distance = matComb._44 - matComb._42;
// Bottom clipping plane
m_frustumPlanes[3].m_normal.x = matComb._14 + matComb._12;
m_frustumPlanes[3].m_normal.y = matComb._24 + matComb._22;
m_frustumPlanes[3].m_normal.z = matComb._34 + matComb._32;
m_frustumPlanes[3].m_distance = matComb._44 + matComb._42;
// Near clipping plane
m_frustumPlanes[4].m_normal.x = matComb._13;
m_frustumPlanes[4].m_normal.y = matComb._23;
m_frustumPlanes[4].m_normal.z = matComb._33;
m_frustumPlanes[4].m_distance = matComb._43;
// Far clipping plane
m_frustumPlanes[5].m_normal.x = matComb._14 - matComb._13;
m_frustumPlanes[5].m_normal.y = matComb._24 - matComb._23;
m_frustumPlanes[5].m_normal.z = matComb._34 - matComb._33;
m_frustumPlanes[5].m_distance = matComb._44 - matComb._43;
m_frustumPlanes[0].Normalise();
m_frustumPlanes[1].Normalise();
m_frustumPlanes[2].Normalise();
m_frustumPlanes[3].Normalise();
m_frustumPlanes[4].Normalise();
m_frustumPlanes[5].Normalise();
}
WORD cullAABB(const D3DXVECTOR3 &aabbMin, /* Test one AABB against the */
const D3DXVECTOR3 &aabbMax) /* frustum */
{
bool intersect = FALSE;
WORD result=0;
D3DXVECTOR3 minExtreme,maxExtreme;
for (WORD i=0;i<5;i++)
{
if (m_frustumPlanes.m_normal.x >= 0)
{
minExtreme.x = aabbMin.x;
maxExtreme.x = aabbMax.x;
}
else
{
minExtreme.x = aabbMax.x;
maxExtreme.x = aabbMin.x;
}
if (m_frustumPlanes.m_normal.y >= 0)
{
minExtreme.y = aabbMin.y;
maxExtreme.y = aabbMax.y;
}
else
{
minExtreme.y = aabbMax.y;
maxExtreme.y = aabbMin.y;
}
if (m_frustumPlanes.m_normal.z >= 0)
{
minExtreme.z = aabbMin.z;
maxExtreme.z = aabbMax.z;
}
else
{
minExtreme.z = aabbMax.z;
maxExtreme.z = aabbMin.z;
}
if((m_frustumPlanes.DistanceToPoint(minExtreme) < 0) &&
(m_frustumPlanes.DistanceToPoint(maxExtreme) < 0))
return 0;
}
return 1;
}
void FrustumCulling(void) /* Frustum culling :-) */
{
int i = 0;
D3DXVECTOR3 Min, Max;
int inside = 0;
ExtractPlanesD3D();
for(i = 0; i < NUMOBJ; i++)
{
OBJ.GetBoxMinMax(&Min, &Max);
inside = cullAABB(Min, Max);
if(inside)
OBJ.InsideFrustum = 1;
else
OBJ.InsideFrustum = 0;
}
}