Game Development Community

Frustrum Culling

by Skylar Kelty · in Torque Game Engine · 07/28/2006 (12:02 am) · 8 replies

Hey,

I've been having problems implementing frustrum culling on interiors.
Im also a bit confused, some say it's done some say its not???

Anyway so far I have:
#include "utils\frustrumculling.h";
At the top of interiorrender.cc

And then I got stuck trying to call the frustrum init, I got confused at the bit where im supposed to pass scenestate, how could I pass the scenestate to the frustrum::init?

#1
07/28/2006 (12:10 am)
Hey James -
i haven't looked into frustrum culling myself,
but i was reading one of Tom Bampton's blog posts earlier today and came across this:
Quote:It's worth pointing out here that interiors already do their own frustrum culling..
the whole post is here.
#2
07/28/2006 (12:25 am)
Yep, posted on that but as its a public blog he cant post code and like i said:
Quote:
some say it's done some say its not???

You see theres that and then he goes onto say how to implement it.

I decided that it does culling based on bounding boxes not view frustrums, I need the view frustrums
#3
07/28/2006 (12:30 am)
Interiors already do their own frustum culling, I'm not sure why it's not getting across.
#4
07/28/2006 (1:28 am)
So if you cant see an interior (if its hiding behind another inetrior) it wont render?
#5
07/28/2006 (7:26 am)
Does terrain have Frustrum Culling?
#6
07/28/2006 (8:06 am)
Hi james, i think you're a bit confused about your terms.

here's a quick overview of the types of culling and how/whether TGE provides them.

Frustum Culling is where an object is not rendered because it's outside of the field of view of the camera. aka the camera's Viewing Frustum. Torque provides this for DTS objects based on their bounding box, and for Interiors based on finer-grained tests. Hence everyone keeps saying Interiors already do their own frustum culling.

Occlusion Culling is what you describe above, which is where an object is within the field of view, but is hiding behind another. The only object in stock TGE which provides occlusion culling is Terrain. That is, if an object (an Interior or DTS) is hiding behind a hill, it doesn't render. In the project i'm working on we have many (100+) players at once, so i added occlusion culling for player objects via raycasts, and the savings in some situations are quite significant.

Zone & Portal Culling is why you portalize your interiors. With Zone Culling, when you are inside a zone such as a closed interior, only objects (interiors & dts's) which are also in that zone are rendered. When your zone includes some Portals (a portal is a doorway, window, etc) then everything in your zone, and everything in any zone which you can see thru any portal in the viewing frustum is also rendered. TGE provides this.

AntiPortal Culling is something TGE does not provide to the best of my knowledge. Also i'm not totally sure what it is, so this is my best guess. AntiPortals is similar to Occlusion Culling, and works best when you've got a large open space which is difficult/impossible to chop into zones. For example a city block. With Antiportals, the faces of buildings effectively become occlusion-cullers in that any object which is entirely obscured by an antiportal is culled. The project i'm working with is thinking of implementing this, but it won't be soon.
#7
07/28/2006 (8:17 am)
Your free to impliment what ever kind of culling you want..

One place to do it is in Scenegraph/scenetraversal.cpp -

The function SceneGraph::treeTraverseVisit is responsible for calling each objects prepRenderImage. look
here for a full explanation of prepRenderImage, but basically if prepRenderImage get called that object is rendered that frame.

You should do your culling there, because all the objects go through that loop, and its easy enough to get in and get out (codewise) ;)

As an example this code performs simple occlusion culling using bounding boxes


//Simple Bounding Box Occlusion

bool occlusionCheck(
               SceneObject*  pObj,
               const Point3F camPos)
{
	
	U32 objectMask = pObj->getTypeMask();
	//dont try and castray on everything
	if(objectMask < 0 ) return false;
	if (objectMask & AtlasObjectType )return false;
   if (objectMask & WaterObjectType )return false;
   if (objectMask & TriggerObjectType )return false;
   if (objectMask & MarkerObjectType  )return false;
   if (objectMask & AtlasObjectType  )return false;
   if (objectMask & DecalManagerObjectType  )return false;
   if (objectMask & CameraObjectType )return false;
   if (objectMask & VehicleBlockerObjectType )return false;
   if (objectMask & PhysicalZoneObjectType )return false;
  
	RayInfo rInfo; 
	 
	Point3F localCamPos = camPos;

	U32	cullMask = AtlasObjectType | InteriorObjectType |
			           StaticObjectType |StaticTSObjectType;


	const Box3F& rBox = pObj->getWorldBox();


    
   Point3F ul(rBox.min.x, rBox.min.y, rBox.max.z);	

	if (!gClientContainer.castRay(localCamPos,ul,cullMask ,&rInfo))      
		// didn't hit anything, we can see this
		return false;
	Point3F ur(rBox.min.x, rBox.max.y, rBox.max.z);
		if (!gClientContainer.castRay(localCamPos,ur,cullMask ,&rInfo))      
		// didn't hit anything, we can see this
		return false;

	Point3F ll(rBox.max.x, rBox.min.y, rBox.max.z);
		if (!gClientContainer.castRay(localCamPos,ll,cullMask ,&rInfo))      
		// didn't hit anything, we can see this
		return false;

	Point3F lr(rBox.max.x, rBox.max.y, rBox.max.z);
	
   Point3F center = ul + lr;
	center *= 0.5f;
	if (!gClientContainer.castRay(localCamPos,center,cullMask ,&rInfo))      
		// didn't hit anything, we can see this
		return false;
//cull this 
	return true;
	
}


then in treeTraverseVisit, simply replace the terrcheck with your custom culling function
//here is where can do occlusion
	if ( doOccCheck == true && occlusionCheck(obj, localCamPos) == true)
               {
	   obj->mOcclusionCount = smOcclusionCount;
	    return;
               }

hope that helps..

btw - clark's resource from a while back is also a good reference on torgue's culling, and optimizations.
#8
07/28/2006 (9:37 am)
@ Orion & Kevin - Thanks for clearing that up