# Strange frustum problem...

This topic is 2635 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi all,

When I check a sphere against my frustum (d3d dx9 engine, c++), it's all good.
Now I made a function to check a bounding box against the frustum, but it now does this:

every object is only rendered when it's inside the frustum AND somehow intersects with the frustum planes.

I've double checked the min and max positions of the bounding boxes, they're all ok.

Can someone help me out?

Here's the code:

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}// NO PROBLEMS WITH SHERE CHECKINGbool CD3dcam::BoxInFrustum(D3DXVECTOR3* pMinPosition, D3DXVECTOR3* pMaxPosition){	float fDistance;	for(int i=0;i<6;++i)    {		fDistance = D3DXPlaneDotCoord(&mFrustumPlane[i], pMinPosition);		if(fDistance <= 0) return true;		fDistance = D3DXPlaneDotCoord(&mFrustumPlane[i], pMaxPosition);		if(fDistance <= 0) return true;    }	return false;}

##### Share on other sites
fDistance = D3DXPlaneDotCoord(&mFrustumPlane[i], pMinPosition);
if(fDistance >= 0) return true;

maybe...

##### Share on other sites
Just a quick look (didn't go into it in depth):

Should:

if(fDistance <= 0) return true;

be?:

if(fDistance >= 0) return true;

EDIT: ninja'd

##### Share on other sites
hi szecs,
that would sound logical indeed, because inside the frustum the value should allways be 0 or higher.
I tried it out, but now all objects are rendered at all time, even when there not in the frustum (I keep a counter).

##### Share on other sites
Just think about it a bit, and you should see what's the problem.

For example if the first condition is not true the second one will surely be: the two conditions should be in AND relation, now they are in OR (think about it)

##### Share on other sites
Reviewed your code. Any coordinate in the world will be on the positive side of one of the frustum planes.

Try checking for both min/max < 0 for each plane. That will, at least, cull boxes entirely on the outside of one of the planes.

EDIT:
fdist1 = D3DXPlane..(plane[i],min);
fdist2 = D3DXPlane..(plane[i],max);
if( fdist1 < 0 && fdist2 < 0 ) return false;

If false is not returned for any frustum plane, return true.

EDIT: ninja #2 [smile]

##### Share on other sites
Both thanks for the hints, I understand that I should check both (and not or), the reason why I used or is that I also want to render boxen that intersect the frustum.

I changed the code now to this:

bool CD3dcam::BoxInFrustum(D3DXVECTOR3* pMinPosition, D3DXVECTOR3* pMaxPosition){	float fDistanceMin, fDistanceMax;	for(int i=0;i<6;i++)    {		fDistanceMin = D3DXPlaneDotCoord(&mFrustumPlane[i], pMinPosition);		fDistanceMax = D3DXPlaneDotCoord(&mFrustumPlane[i], pMaxPosition);		if(fDistanceMin < 0 && fDistanceMax < 0) return false;     }	return true;}

This works almost, only now objects that are not fully in the frustum are not rendered I think. When I change it to '<= 0' instead of "<0" still objects that are partially in the frustum are not returned as 'true' and therefor not rendered.

##### Share on other sites
Because you're using AABB, it's possible that min and max could be outside the frustum, but one of the corners (not min or max) could be inside the frustum.

I think you'll have to test all 8 corners of the AABB.

##### Share on other sites
Ok, I can make that work and code that.
But will checking all 8 points still be be quicker then just checking all objects (included boxes) with a radius as a bounding sphere?

##### Share on other sites
Quote:
 But will checking all 8 points still be be quicker then just checking all objects (included boxes) with a radius as a bounding sphere?

Unfortunately, no. However, depending on how many objects and what their shapes are, you can cull bounding spheres that are outside the frustum. Then do the full 8 point AABB check only for those objects whose bounding spheres are not outside the frustum.

EDIT: I don't know how you determine the bounding radius, but you can precalculate the radius (and sphere center position) for each object if you don't already. That would speed things up a bit as you wouldn't have to calculate the radius for each "in-frustum" call.

##### Share on other sites
Thanks, knowing this I would suggest the following approach:

- calculate radius for full mesh/object
- calculate 8 AABB corners for subobjects

RenderFrame:

- update camera
- occlusioncull
- if full mesh/object visible:
- for each sububject: check if sphere's in frustum
- for each subobject: check against 8x AABB box
- if both true, then render

OcclusionCull:

- check if full mesh/object is in frustum, using radius and sphere in frustum
if so, full mesh visible = true

Would this be a good approach?

I also considered keeping track per full and sub-object if it has to be checked using boundingbox or sphere, but I doubt if that will help.

##### Share on other sites
Quote:
 - if full mesh/object visible:

If, by "full" you mean some portion is visible, that looks like a good approach. Certainly precalculating as many parameters as possible will give benefits.

As you obviously realize, the fastest draw for a triangle is one that's not drawn at all.

Take note, cozzie, that, if you're concerned about performance, you might want to do some profiling to make sure your algorithm is, in fact, showing some benefit under actual game conditions.

Quote:
 I also considered keeping track per full and sub-object if it has to be checked using boundingbox or sphere, but I doubt if that will help.

Probably of less benefit than the frustum culling you're already going to do. But, at the expense of a single bool variable per object (if it can be precalculated) and a single "should-I-check-AABB?" statement, there may be a marginal benefit.

##### Share on other sites
Hi
I implemented the 8x AABB boundingbox check, not very clean code yet, but first to see if it works.

Here it is:

// one time per subobject			mAttrBoundingBox[obj].boxArray[0].x = mAttrBoundingBox[obj].min.x;			mAttrBoundingBox[obj].boxArray[0].y = mAttrBoundingBox[obj].min.y;			mAttrBoundingBox[obj].boxArray[0].z = mAttrBoundingBox[obj].min.z;			mAttrBoundingBox[obj].boxArray[1].x = mAttrBoundingBox[obj].max.x;			mAttrBoundingBox[obj].boxArray[1].y = mAttrBoundingBox[obj].min.y;			mAttrBoundingBox[obj].boxArray[1].z = mAttrBoundingBox[obj].min.z;			mAttrBoundingBox[obj].boxArray[2].x = mAttrBoundingBox[obj].max.x;			mAttrBoundingBox[obj].boxArray[2].y = mAttrBoundingBox[obj].max.y;			mAttrBoundingBox[obj].boxArray[2].z = mAttrBoundingBox[obj].min.z;			mAttrBoundingBox[obj].boxArray[3].x = mAttrBoundingBox[obj].min.x;			mAttrBoundingBox[obj].boxArray[3].y = mAttrBoundingBox[obj].max.y;			mAttrBoundingBox[obj].boxArray[3].z = mAttrBoundingBox[obj].min.z;			mAttrBoundingBox[obj].boxArray[4].x = mAttrBoundingBox[obj].min.x;			mAttrBoundingBox[obj].boxArray[4].y = mAttrBoundingBox[obj].min.y;			mAttrBoundingBox[obj].boxArray[4].z = mAttrBoundingBox[obj].max.z;			mAttrBoundingBox[obj].boxArray[5].x = mAttrBoundingBox[obj].max.x;			mAttrBoundingBox[obj].boxArray[5].y = mAttrBoundingBox[obj].min.y;			mAttrBoundingBox[obj].boxArray[5].z = mAttrBoundingBox[obj].max.z;			mAttrBoundingBox[obj].boxArray[6].x = mAttrBoundingBox[obj].max.x;			mAttrBoundingBox[obj].boxArray[6].y = mAttrBoundingBox[obj].max.y;			mAttrBoundingBox[obj].boxArray[6].z = mAttrBoundingBox[obj].max.z;			mAttrBoundingBox[obj].boxArray[7].x = mAttrBoundingBox[obj].min.x;			mAttrBoundingBox[obj].boxArray[7].y = mAttrBoundingBox[obj].max.y;			mAttrBoundingBox[obj].boxArray[7].z = mAttrBoundingBox[obj].max.z;// check functionbool CD3dcam::BoxInFrustum(BOUNDINGBOX *pBoundingBox){	float fDistance;	for(int i=0;i<6;++i)    {		for(int bc=0;bc<8;++bc)		{			fDistance = D3DXPlaneDotCoord(&mFrustumPlane[i], &pBoundingBox->boxArray[bc]);			if(fDistance >= 0) return true;		}	}	return false;}

Unfortunately everything is still rendered/ returned as true.
Probably has something to do with return true to early, although I don't understand. Will try some things.

If you see something that's wrong, please let me know.

##### Share on other sites
Use debugger, or debug on paper. We can do it for you, but why should we?

##### Share on other sites
You don't have to check all 8 corners of the AABB. Google 'aabb plane test', 'box plane test', 'aabb frustum culling', or similar terms, and you should find some example implementations.

In particular, look for references that talk about the 'n-vertex' and the 'p-vertex' (I think that's the terminology that's often used). This actually still isn't the fastest method available (I don't believe), but it seems to be better documented than the alternatives.

##### Share on other sites
Good point :)

Solved it, I was looking for something difficult, but it was something stupid.

I did this: BoxInFrustum(&mD3dMeshes[oc].mAttrBoundingBox) which had to be
BoxInFrustum(&mD3dMeshes[oc].mAttrBoundingBox[obj]).
Stupid.

Got it all working know, that's for the help.
Next thing I'll do is do a much larger testscene and see if it's quicker or nog to keep track of 'check 8x AABB' or not.

##### Share on other sites

This topic is 2635 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628707
• Total Posts
2984312

• 23
• 10
• 9
• 13
• 14