strange frustum culling behaviour

Started by
3 comments, last by cozzie 11 years, 3 months ago

Hi,

I've noticed that my frustum culling is behaving strange when doing a boundingsphere check on entities of meshes. It looks like entities are being culled just before there out of the frustum/ screen.

Before I dig into my code calculation the radius of my entities, I'd like to know if someone sees any strange things my frustum calculation and check boundingsphere functions. Any help is really appreciated:


void CD3dcam::CalculateFrustum()
{
	D3DXMatrixMultiply(&mFrustumMatrix, &mMatView, &mMatProjection);

	// left plane
	mFrustumPlane[0].a = mFrustumMatrix._14 + mFrustumMatrix._11;
	mFrustumPlane[0].b = mFrustumMatrix._24 + mFrustumMatrix._21;
	mFrustumPlane[0].c = mFrustumMatrix._34 + mFrustumMatrix._31;
	mFrustumPlane[0].d = mFrustumMatrix._44 + mFrustumMatrix._41;
	D3DXPlaneNormalize(&mFrustumPlane[0], &mFrustumPlane[0]);

	// right plane
	mFrustumPlane[1].a = mFrustumMatrix._14 - mFrustumMatrix._11;
	mFrustumPlane[1].b = mFrustumMatrix._24 - mFrustumMatrix._21;
	mFrustumPlane[1].c = mFrustumMatrix._34 - mFrustumMatrix._31;
	mFrustumPlane[1].d = mFrustumMatrix._44 - mFrustumMatrix._41;
	D3DXPlaneNormalize(&mFrustumPlane[1], &mFrustumPlane[1]);

	// top plane
	mFrustumPlane[2].a = mFrustumMatrix._14 - mFrustumMatrix._12;
	mFrustumPlane[2].b = mFrustumMatrix._24 - mFrustumMatrix._22;
	mFrustumPlane[2].c = mFrustumMatrix._34 - mFrustumMatrix._32;
	mFrustumPlane[2].d = mFrustumMatrix._44 - mFrustumMatrix._42;
	D3DXPlaneNormalize(&mFrustumPlane[2], &mFrustumPlane[2]);

	// bottom plane
	mFrustumPlane[3].a = mFrustumMatrix._14 + mFrustumMatrix._12;
	mFrustumPlane[3].b = mFrustumMatrix._24 + mFrustumMatrix._22;
	mFrustumPlane[3].c = mFrustumMatrix._34 + mFrustumMatrix._32;
	mFrustumPlane[3].d = mFrustumMatrix._44 + mFrustumMatrix._42;
	D3DXPlaneNormalize(&mFrustumPlane[3], &mFrustumPlane[3]);

	// near plane
	mFrustumPlane[4].a = mFrustumMatrix._13;
	mFrustumPlane[4].b = mFrustumMatrix._23;
	mFrustumPlane[4].c = mFrustumMatrix._33;
	mFrustumPlane[4].d = mFrustumMatrix._43;
	D3DXPlaneNormalize(&mFrustumPlane[4], &mFrustumPlane[4]);

	// far plane
	mFrustumPlane[5].a = mFrustumMatrix._14 - mFrustumMatrix._13;
	mFrustumPlane[5].b = mFrustumMatrix._24 - mFrustumMatrix._23;
	mFrustumPlane[5].c = mFrustumMatrix._34 - mFrustumMatrix._33;
	mFrustumPlane[5].d = mFrustumMatrix._44 - mFrustumMatrix._43;
	D3DXPlaneNormalize(&mFrustumPlane[5], &mFrustumPlane[5]);
}

bool CD3dcam::SphereInFrustum(D3DXVECTOR3 *pPosition, float pRadius)
{
	float fDistance;
	for(int i=0;i<6;++i)
    {
		fDistance = D3DXPlaneDotCoord(&mFrustumPlane[i], pPosition) + pRadius;

		if(fDistance < -pRadius) return false; // outside the frustum
		if((float)fabs(fDistance) < pRadius) return true; // intersects
    }
    return true; // inside the frustum completely or intersecting; see XLS
}

// calculating the entities/ meshes radius

bool CD3dmesh::CalcRadiusAndWorldPos()
{
	mAttrWorldPos		= new D3DXVECTOR3[mAttrSize];
	mAttrBoundingRadius = new float[mAttrSize];
	mAttrBoundingBox	= new BOUNDINGBOX[mAttrSize];

	TVERTEX *verticesPointer;
	TVERTEX *vertices = new TVERTEX[mMesh->GetNumVertices()];

	mVtxBuffer->Lock(0, 0, (void**)&verticesPointer, 0); //D3DLOCK_READONLY);
	memcpy(vertices, verticesPointer, mMesh->GetNumVertices()*D3DXGetDeclVertexSize(dec, 0)); 
	mVtxBuffer->Unlock();

	// scale the vertices, before determining bounding radius, mesh (world)pos etc.

	for(DWORD vc=0;vc<mMesh->GetNumVertices();++vc)
		D3DXVec3Scale(&vertices[vc].position, &vertices[vc].position, mScale);

	// calculatie bounding radius, using always absolute, 0.0.0 mMeshCenter
	D3DXComputeBoundingSphere(&vertices[0].position, mMesh->GetNumVertices(), D3DXGetDeclVertexSize(dec, 0), &mMeshCenter, &mBoundingRadius);	

	// do the same for all subobjects in the attr table, mAttrWorldPos is DETERMINED based on subobject vertices

	for(DWORD obj=0;obj<mAttrSize;++obj)
	{
		D3DXComputeBoundingSphere(&vertices[mAttrTable[obj].VertexStart].position, (DWORD)mAttrTable[obj].VertexCount, D3DXGetDeclVertexSize(dec, 0), &mAttrWorldPos[obj], &mAttrBoundingRadius[obj]); 
		mAttrBoundingRadius[obj] += 0.1f;

		CalcBoundingBox(vertices, mAttrTable[obj].VertexStart, mAttrTable[obj].VertexCount, &mAttrBoundingBox[obj]);
	}
	SafeDelete(vertices);

	// add WorldPos of object to all sub objects

	for(DWORD obj=0;obj<mAttrSize;++obj)
	{
		D3DXVec3Add(&mAttrWorldPos[obj], &mAttrWorldPos[obj], &mWorldPos); 
		for(int vc=0;vc<8;++vc) 
			D3DXVec3Add(&mAttrBoundingBox[obj].boxArray[vc], &mAttrBoundingBox[obj].boxArray[vc], &mWorldPos);
	}
	UpdateWorldMatrix(); 
	return true;
}

It doesn't seem to occur on full meshes though (first boundingsphere check in rendering a frame).

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

addition; I also tried to switch true and false in the boundingsphere check function, to see if nothing's culled, but strangely a lot of entities are still not culled (depending on the frustum at that moment)..

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Found the cause already, when I don't rotate my meshes (and thus entities), everything works fine.

I scale all vertices before calculating the boundingradius, but I don't do any rotation... probably have to do that to first

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Found the cause already, when I don't rotate my meshes (and thus entities), everything works fine.

I scale all vertices before calculating the boundingradius, but I don't do any rotation... probably have to do that to first

You mean you werent rotating your bounding sphere to be in the same place as your rendering mesh?

Did you try rendering out the bounding sphere on top of the mesh to make sure they look correct?

It doesnt sound like you're sure what the problem is. You should know what the problem is before moving on, not just put in a fix and hope that it's the right fix for the real problem.

Hi.
What i do after loading the beshes, during initialization, is calculation the bounding radius of the meshes and entities. So i can use them for boundinghere checks in culling.

What i did was:
- lock vertexbuffer in local space (not scaled or rotated)
- scale the vertices
- then calculate the boundingradius (using d3dxcreateboundingsphere)
- then do the same for all entities

I was nearly there but forgot to rotate where i scale the vertices.
Found that out by setting rotation xyz for all meshes to 0 and then the problem wasn't there.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement