Reasons for "premature" culling?
Hello everyone. I have recently gotten culling to work for my meshes (see, I got it right), and in all my excitement I didn''t realize that my culling wasn''t working correctly (NOTE: I am using modified code from the "Cull" sample from the SDK).
Imagine a scene with one model in the center and the interactive camera in looking straight at it: When the camera is, lets say, 10 units away, everything looks correctly. Now, lets say we tilt the camera up a bit. Now the mesh should still be in the frustum, but it isn''t being drawn. Next, lets say we move forward toward the object. Now that we are 5 (estimate) units away from the objects, it disappears again.
Does anyone know a reason why this could happen so I can go back and recheck my code? I have tried rewriting several times, so I suspect that I''m not doing something correctly. If you want to see parts of my code, I will be happy to post it.
Thanks.
It depends on the type of culling from the frustrum you mean - sphere, cube, rectangle, point, ...
You might want to summarize and post a small example of your culling code.
Jim Adams
home.att.net/~rpgbook
Author, Programming Role-Playing Games with DirectX
You might want to summarize and post a small example of your culling code.
Jim Adams
home.att.net/~rpgbook
Author, Programming Role-Playing Games with DirectX
Ok, here it goes: I am culling (bounding) boxes, using modified code from the "Cull" example.
There are two main classes for my culling: CBoundingBox and CFrustum. CBoundingBox has two (relatively) short functions:
CBoundingBox::Compute() is called once during the creation of the object-to-be-culled:
CBoundingBox::Recompute() is called once every frame.
CFrustum has one function to update the FOV:
The objects rendering code looks like this:
The CullObject() function is too long for me too here without getting yelled at, but it can be found in cull.cpp in the "cull" sample. This has probably been very vague, so I can elaborate if needed.
There are two main classes for my culling: CBoundingBox and CFrustum. CBoundingBox has two (relatively) short functions:
HRESULT CBoundingBox::Compute(PVOID pPointsFVF, DWORD dwNumVerts, DWORD dwFVF){ HRESULT hr; D3DXVECTOR3 vecMin; D3DXVECTOR3 vecMax; if(FAILED( hr = D3DXComputeBoundingBox( pPointsFVF, dwNumVerts, dwFVF, &vecMin, &vecMax ))) return hr; m_vecBoundsLocal[0] = D3DXVECTOR3( vecMin.x, vecMin.y, vecMin.z ); // xyz m_vecBoundsLocal[1] = D3DXVECTOR3( vecMax.x, vecMin.y, vecMin.z ); // Xyz m_vecBoundsLocal[2] = D3DXVECTOR3( vecMin.x, vecMax.y, vecMin.z ); // xYz m_vecBoundsLocal[3] = D3DXVECTOR3( vecMax.x, vecMax.y, vecMin.z ); // XYz m_vecBoundsLocal[4] = D3DXVECTOR3( vecMin.x, vecMin.y, vecMax.z ); // xyZ m_vecBoundsLocal[5] = D3DXVECTOR3( vecMax.x, vecMin.y, vecMax.z ); // XyZ m_vecBoundsLocal[6] = D3DXVECTOR3( vecMin.x, vecMax.y, vecMax.z ); // xYZ m_vecBoundsLocal[7] = D3DXVECTOR3( vecMax.x, vecMax.y, vecMax.z ); // XYZ return hr;}void CBoundingBox::Recompute(D3DXMATRIX matOrientation){ // Transform bounding box coords from local space to world space for( int i = 0; i < 8; i++ ) D3DXVec3TransformCoord( &m_vecBoundsWorld[i], &m_vecBoundsLocal[i], &matOrientation ); // Determine planes of the bounding box D3DXPlaneFromPoints( &m_planeBoundsWorld[0], &m_vecBoundsWorld[0], &m_vecBoundsWorld[1], &m_vecBoundsWorld[2] ); // Near D3DXPlaneFromPoints( &m_planeBoundsWorld[1], &m_vecBoundsWorld[6], &m_vecBoundsWorld[7], &m_vecBoundsWorld[5] ); // Far D3DXPlaneFromPoints( &m_planeBoundsWorld[2], &m_vecBoundsWorld[2], &m_vecBoundsWorld[6], &m_vecBoundsWorld[4] ); // Left D3DXPlaneFromPoints( &m_planeBoundsWorld[3], &m_vecBoundsWorld[7], &m_vecBoundsWorld[3], &m_vecBoundsWorld[5] ); // Right D3DXPlaneFromPoints( &m_planeBoundsWorld[4], &m_vecBoundsWorld[2], &m_vecBoundsWorld[3], &m_vecBoundsWorld[6] ); // Top D3DXPlaneFromPoints( &m_planeBoundsWorld[5], &m_vecBoundsWorld[1], &m_vecBoundsWorld[0], &m_vecBoundsWorld[4] ); // Bottom}
CBoundingBox::Compute() is called once during the creation of the object-to-be-culled:
VOID* pVertices; if( FAILED( hr = m_pObjMesh->GetSysMemMesh()->LockVertexBuffer(D3DLOCK_READONLY, (BYTE**)&pVertices) ) ) return hr; if( FAILED( hr = m_BoundingBox.Compute(pVertices, m_pObjMesh->GetSysMemMesh()->GetNumVertices(), m_pObjMesh->GetSysMemMesh()->GetFVF()))) return hr; m_pObjMesh->GetSysMemMesh()->UnlockVertexBuffer();
CBoundingBox::Recompute() is called once every frame.
CFrustum has one function to update the FOV:
void CFrustum::UpdateFrustum(D3DXMATRIX* pMatView, D3DXMATRIX* pMatProj){ D3DXMATRIX mat; D3DXMatrixMultiply( &mat, pMatView, pMatProj ); D3DXMatrixInverse( &mat, NULL, &mat ); 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 for( INT i = 0; i < 8; i++ ) D3DXVec3TransformCoord(&vecFrustum[i],&vecFrustum[i], &mat ); D3DXPlaneFromPoints( &planeFrustum[0], &vecFrustum[0], &vecFrustum[1], &vecFrustum[2] ); // Near D3DXPlaneFromPoints( &planeFrustum[1], &vecFrustum[6], &vecFrustum[7], &vecFrustum[5] ); // Far D3DXPlaneFromPoints( &planeFrustum[2], &vecFrustum[2], &vecFrustum[6], &vecFrustum[4] ); // Left D3DXPlaneFromPoints( &planeFrustum[3], &vecFrustum[7], &vecFrustum[3], &vecFrustum[5] ); // Right D3DXPlaneFromPoints( &planeFrustum[4], &vecFrustum[2], &vecFrustum[3], &vecFrustum[6] ); // Top D3DXPlaneFromPoints( &planeFrustum[5], &vecFrustum[1], &vecFrustum[0], &vecFrustum[4] ); // Bottom}
The objects rendering code looks like this:
HRESULT CObject::Render(CFrustum *pFrustum){ m_cullstate = CullObject(pFrustum, m_BoundingBox.GetLocalBoundingBoxCoords(), m_BoundingBox.GetWorldBoundingBoxPlanes()); switch(m_cullstate) { case CS_UNKNOWN: return S_OK; case CS_INSIDE: m_pObjMesh->Render(m_pd3dDevice, TRUE, TRUE); return S_OK; case CS_OUTSIDE: return S_OK; case CS_INSIDE_SLOW: m_pObjMesh->Render(m_pd3dDevice, TRUE, TRUE); return S_OK; case CS_OUTSIDE_SLOW: return S_OK; default: return E_FAIL; } return S_OK;}
The CullObject() function is too long for me too here without getting yelled at, but it can be found in cull.cpp in the "cull" sample. This has probably been very vague, so I can elaborate if needed.
Take a look at this site: http://groups.google.com/groups?hl=en&selm=uBMtTHu1%24GA.242%40cppssbbsa02.microsoft.com&rnum=3
note: you will notice some negative signs in code that makes a frustum out of the matrix, you need to remove them to make it work
Combind that with Mark Morly''s code and you have a _working_ D3D Frustum
note: you will notice some negative signs in code that makes a frustum out of the matrix, you need to remove them to make it work
Combind that with Mark Morly''s code and you have a _working_ D3D Frustum
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement