1. hehe, hey, the Transformers used that line too!

I'm pretty sure I've said it before, but I haven't yet this thread. Pertty stuffs, Bubba.

2. Mixing outdoor/indoor scenes is a pain in the arse.

Seeing as how the xz of the grid is a constant size, I'm guessing that building the volumes of the quad tree is ultimateliy trivial (with a bsp compiler you have to examine geometry, potentially perform splitting or flagging that a face belongs to multiple nodes). I'm guessing that, at some point, you define what you want the size of a renderable leaf of data is. I don't think it should be terribly difficult for you to get culling to work again.

For dyanmic objects, well, I handle rendering those in a few ways. First, if I've only got a few objects, I don't even consider what leaf they are in: I just do the frustum test. Otherwise, you have to somehow link the entity to the world by finding what leafs it lays in. To make matters worse, an object can also overlap the splitter plane. Here is the code I use for finding the leaf nodes a sphere lays inside of...to get this to work for a bounding box, you can use the positive/negative vertices method similar to what you posted in your frustum culling code, e.g., the effective radius would be equal to:

//find the vector, made up of components of the mins/maxs, that effectively 'goes against' the plane normal
Vector3 tocheck;
for(int i = 0; i < 3; i++ //for each component
{
if(splitter_plane.normal[i] < 0)
tocheck[i] = box.maxs[i];
else
tocheck[i] = box.mins[i];
}

PHP Code:
``` void    SphereTouchNode(BSP*pBSP,int node,Vector3 *Start,float Radius, std::vector<int> &TouchedLeafs){    if(node < 0)    {        TouchedLeafs.push_back(~node);        return;    }            tBSPNode    *pNode  = &pBSP->mpNodes[node];    tBSPPlane    *pPlane = &pBSP->mpPlanes[    pNode->plane    ];    Vector3        *pNormal= &pPlane->vNormal;        float    StartD = DotProduct(pNormal,Start) - pPlane->d;    if(fabs(StartD) <= Radius)    //Intersects, traverse front and back, this sphere is not clearly in front of in back    {        SphereTouchNode(pBSP,pNode->front,Start,Radius,TouchedLeafs);        SphereTouchNode(pBSP,pNode->back,Start,Radius,TouchedLeafs);        return;    }    else    if(StartD    >    Radius) clearly in front    {        SphereTouchNode(pBSP,pNode->front,Start,Radius,TouchedLeafs);        return;    }    else    //clearly in back    {        SphereTouchNode(pBSP,pNode->back,Start,Radius,TouchedLeafs);        return;    }    }  ```
This code only works, of course, if you are traversing splitter planes...how, exactly, do you traverse the quad tree? Is it checking against planes, or are you checking against the boundaries of bounding boxes? As I understand it, your quad tree means that, if you look at the top down view of all the terrain, that gets split up into 4 boxes (very large boxes), then each of those boxes gets further split down into 4 more boxes, etc, until the size of the boxes left encloses the amount you want to render per node (I'm guessing you just need to intelligently choose this amount). With a BSP tree the leaf nodes to ultimately come down to convex regions (enclosed by splitter planes), but you arrive at these regions by traversing non-convex regions (front/back).

In the BSP code, you first find the leaf the camera is in, then you know the leafs that are potentially visible from this leaf (potential visibility set, stored in a bixfield matrix).

- Find the leaf you are in, send it to the renderer (I cache everything and render it later)
- For every leaf that is potentially visible (e.g. connected by an open doorway or something), test to see if the bounding volume (box) is outside of the frustum, if it is, just continue, else render this leaf.

NOTE: I wrote this reply like sometime last week, saved it in notepad, and haven't rigorously re-read it (which is why some of it might not make any sense, it may be unfinished).