Reasons for "premature" culling?

Started by
3 comments, last by Sheep 21 years, 9 months ago
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.
Advertisement
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
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:


  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.

Bump?

Sorry if that was a code dump, but I don''t know where the problem lies
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

This topic is closed to new replies.

Advertisement