Extracting a viewing frustum

Started by
16 comments, last by Jiia 19 years, 1 month ago
Quote:Original post by hoogie
Well one of the things im unsure about was the checking of points against the plane. Each node in my quadtree has its minimum and maximum world coordinates so initially I assumed I could check if it was viewable by checking if the world coordinates were within the frustum planes.

Sorry, I forgot to answer this one. To know if a box shape is outside of the frustum, all of the 8 corners of the box must be outside of a plane. That doesn't mean pass all 8 corners to Cull_Point. It means all 8 points must be outside of a single plane.

If you were looking directly at your box, the four top corners may be outside of the top plane, and the four bottom corners may be outside of the bottom plane. So all points are outside of the frustum, yet your box is totally centered in view. So all points of the object must be outside of a single plane.
Advertisement
Hey, first thanks for all the replys.

I am trying to implement my checks like Jiia described and am almsot there. Currently clipping is taking place but not entirely as it should, sometimes the clipping can be seen and at other time the entire terrain dissappears. This is how im currently doing my tests

// calculates position data to test against the frustum planesD3DXVECTOR3 minOff, maxOff;minOff = node->GetMinimumBounds() - cameraPos;maxOff = node->GetMaximumBounds() - cameraPos;// if node completely invisible set all child nodes to invisibleif( D3DXVec3Dot(&minOff, &m_leftPlane.normal)  < 0.0f &&    D3DXVec3Dot(&maxOff, &m_leftPlane.normal)  < 0.0f ||    D3DXVec3Dot(&minOff, &m_rightPlane.normal) < 0.0f &&    D3DXVec3Dot(&maxOff, &m_rightPlane.normal) < 0.0f )    CFrustum::SetAllInvisible(node);// else if node completely visible set all child nodes to visibleelse if( D3DXVec3Dot(&minOff, &m_leftPlane.normal)  >= 0.0f  &&	 D3DXVec3Dot(&maxOff, &m_leftPlane.normal)  <  0.0f  ||	 D3DXVec3Dot(&minOff, &m_rightPlane.normal) >= 0.0f  &&	 D3DXVec3Dot(&maxOff, &m_rightPlane.normal) <  0.0f )			 	 CFrustum::SetAllVisible(node);// else if partially visible but has children progress further down quadtreeelse if( node->m_childNode[0] != NULL && node->m_childNode[1] != NULL &&          node->m_childNode[2] != NULL && node->m_childNode[3] != NULL ){    CFrustum::ClipQuadTree(node->m_childNode[0], cameraPos);    CFrustum::ClipQuadTree(node->m_childNode[1], cameraPos);    CFrustum::ClipQuadTree(node->m_childNode[2], cameraPos);    CFrustum::ClipQuadTree(node->m_childNode[3], cameraPos);}// else if partially visible but has no children set to visibleelse    CFrustum::SetAllVisible(node);


Does that look correct or am i doing something wrong somewhere?

Thanks
I haven't actually culled a bounding box with my routine yet. But I think your problem is in using GetMinimum/MaximumBounds. This is what I was trying to explain before about all points having to be outside of a single plane.

For example, if your bounding box has 8 points, you have to test every single point against the left plane. If all of them are outside of that plane, then it's hidden. If not, do it again for another plane. Then again until you find a plane that all points are outside of. If none are found, the box is visible.

The reason your entire terrain is being hidden is because all of it's points are outside of planes, yet the center of the box is in view. That's why all points must be outside of a single plane.

Like I said, I haven't experimented with it much. Don't take my word for gold ;)

edit:

I think there might some optimizations you could do, though. If you can find the point that is most-left relative to the camera, you only need to test that point against the right plane. Test the most-right point against the left plane, etc. But finding a point most left/right/etc of the camera may require more processing than is needed to check the planes to begin with. It all depends on how you caclulate most extreme points.

The first idea that comes to mind to find the most right point is to dot each offset with the camera right-vector. But I doubt this would show any performance boost; it may even slow it down.

Also, depending on how your camera and bounding boxes rotate, you may be able to test fewer points. For example, if UP is always UP (your camera doesn't twist - meaning your world isn't ever viewed sideways, and your bounding box is AABB or also doesn't twist), you don't need to test both top and bottom points against the left and right planes. Is this case, you could just test the four bottom points against each side.

[Edited by - Jiia on April 1, 2005 6:27:49 AM]
It sounds like you may be getting this figured out, so I'm not sure this'll help. However, I found Mark Morley's frustum culling tutorial really helpful. It's in OpenGL, but I think only the plane extraction should be different (is that true?). I found this article about plane extraction to be really helpful and it covers both opengl and directx and has example code. Anyway, hope you get it working.
Well currently my only test that leads to anything being set as invisible is

// if node completely invisible set all child nodes to invisible
if( D3DXVec3Dot(&minOff, &m_leftPlane.normal) < 0.0f &&
D3DXVec3Dot(&maxOff, &m_leftPlane.normal) < 0.0f ||
D3DXVec3Dot(&minOff, &m_rightPlane.normal) < 0.0f &&
D3DXVec3Dot(&maxOff, &m_rightPlane.normal) < 0.0f )

CFrustum::SetAllInvisible(node);

And im under the impression that that is only called when the min and max bound are outside of the same plane.

I cant think that my planes could be wrong as they are extracted like all the turorials say and theres no way that my view matrix could be incorrect
I'm not sure I follow what the problem is. Here is a snap shot from my debug cam in my project:

Free Image Hosting at www.ImageShack.us
The screen is viewed from the debug camera looking at the real camera. All lighting and culling is done relative to the real camera. The white lines are the frustum of the real camera. It's looking almost completely down on the guy standing in grass. Culling isn't activated in this snap shot, but you can see how it would be easy to mess this up. The entire flat grass area is a single quad. All four points of the quad are outside of the frustum planes, yet the camera is staring right at it.

Hope that helps a bit, if that is the problem.
Hey,

Ive been continuing with my implementation of the frustum culling and found a good tutorial covering the kind of loop needed to clip a cube.

Im having one final problem and think I might know the reason why. Basically the implementation I currently have is clipping my quadtree nodes but the clipping is always slightly off so the clip is noticeable, as such I figured that my data must be slightly off somewhere.

When I set my quadtree it is essentially a 2D quadtree covering the terrain in the x and z directions, by default the y values are left as zero and never changed. Could this be the cause of my clipping algorithm being slightly off? I figured it might be as the equation utilizes the x, y, and z coords of a point to test if its inside a plane or out.

If this is the cause of the problem is there any way that I can alter my frustum clipping to ignore the y data and clip based solely on the x and z data?

Thanks again for any replies
An object shouldn't need any mass to cull correctly. I don't know if the problem is related to it or not, but having the top and/or bottom of all points as zero would make no difference.

However, if your meshes are sticking up off of the ground, and you're culling them like they are flat, then yeah, it would definitely be noticable and it won't work correctly. If you don't want to scan for sizes, you can just give them really tall boxes, big enough to fit any size mesh in your game.

This topic is closed to new replies.

Advertisement