Page MenuHome

BGE: Frustrum culling not working properly
Closed, ResolvedPublic


System Information
Arch Linux 64-bit
Intel HD Graphics 4000

Blender Version
Broken: version 2.70 (sub 5), hash 003387fab543711495e2ceb80a663d7f79fcf447

Short description of error
In KX_Scene::CalculateVisibleMeshes, I think the CullingTest function is not working properly. In my attached blend file, it'll correctly calculate when an object enters the frustrum but not when it exits. When I use the other method with MarkVisible, it works properly.

I'm not completely sure whether the KX_GameObject attribute (m_bCulled) is not being set properly or the CullingTest is failing or both.

Exact steps for others to reproduce the error
In order to check, I've added the following code in KX_Scene:

void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int layer)
	bool dbvt_culling = false;
	if (m_dbvt_culling) 
		// test culling through Bullet
		MT_Vector4 planes[6];
		// get the clip planes
		MT_Vector4* cplanes = cam->GetNormalizedClipPlanes();
		// and convert
		planes[0].setValue(cplanes[4].getValue());	// near
		planes[1].setValue(cplanes[5].getValue());	// far
		planes[2].setValue(cplanes[0].getValue());	// left
		planes[3].setValue(cplanes[1].getValue());	// right
		planes[4].setValue(cplanes[2].getValue());	// top
		planes[5].setValue(cplanes[3].getValue());	// bottom
		CullingInfo info(layer);

		double mvmat[16] = {0};
		double pmat[16] = {0};

		dbvt_culling = m_physicsEnvironment->CullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res,
		                                                 mvmat, pmat);
	if (!dbvt_culling) {
		// the physics engine couldn't help us, do it the hard way
		for (int i = 0; i < m_objectlist->GetCount(); i++)
			MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);

	for (int i = 0; i < m_objectlist->GetCount(); i++)
		KX_GameObject *gameobj = static_cast<KX_GameObject*>(m_objectlist->GetValue(i));
		bool culled = gameobj->GetCulled();
		printf("Name: %s, Culled: %s\n", gameobj->GetName().Ptr(), culled == true ? "True" : "False");

And the blend file:

Event Timeline

Kevin Ednalino (mahalin) raised the priority of this task from to 90.
Kevin Ednalino (mahalin) updated the task description. (Show Details)
Kevin Ednalino (mahalin) edited a custom field.
Mitchell Stokes (moguri) lowered the priority of this task from 90 to 50.May 20 2014, 5:55 AM

The Bullet assisted culling code will never set KX_GameObject::m_bCulled to true. However, mesh slots are automatically set to true after they are rendered. This means that the meshes are indeed getting culled, but some of our other code that is relying on KX_GameObject::GetCulled() (e.g., animation culling, LoDs) are not working properly.

So another idea I have is we could maintain a list of the non-culled items (i.e. visible) by adding objects to a list in the Physics callback e.g. m_nonculledobjects.push_back(KX_GameObject). We would clear it each frame before doing the culling check. Of course, it would be valid only for that frame.

This list would be useful for functions that operate only on non-culled items, like LOD. I believe it would also be more efficient as now there is no need to iterate over every object and check its culling flag.

Hmm, we could also have the material bucket be responsible for adding to this list or would that be a code smell? Ultimately, it decides if an object's mesh is culled and thus rendered.

Mitchell Stokes (moguri) changed the task status from Unknown Status to Resolved.Jul 1 2014, 9:41 PM

Closed by commit rB978dba461685.

Mitchell Stokes (moguri) changed the task status from Resolved to Unknown Status.Jul 10 2014, 7:38 AM

The fix was reverted as it didn't actually fix the problem and, instead, broke skeletal mesh animations.

Mitchell Stokes (moguri) changed the task status from Unknown Status to Resolved.Jul 11 2014, 7:18 AM

Closed by commit rB315609ec0c1e.

Mitchell Stokes (moguri) edited this Maniphest Task.