Quadtree/Octree question...
#1 Members - Reputation: 164
Posted 28 June 2011 - 10:23 PM
Thanks in advance...
#2 Members - Reputation: 571
Posted 28 June 2011 - 10:36 PM
Unless I completally misunderstood your question. Is there some other part of dealing with quadtrees that you are calling sorting?
#3 Members - Reputation: 164
Posted 28 June 2011 - 10:57 PM
#5 Members - Reputation: 252
Posted 29 June 2011 - 12:08 AM
#7 Members - Reputation: 571
Posted 29 June 2011 - 05:54 AM
void recursiveNodeHandler(vec2 pos,vec2 size,int level)
{
if(level>THRESHOLD || box of size at pos is completally visible)
drawStuffInNode();
if(box of size at pos is partially visible)
{
recursiveNodeHander(pos,size/2,level+1);//upper left
recursiveNodeHander(vec2(pos.x,pos.y+size.y/2),size/2,level+1);//lower left
for each of the 4 quarters of the current node
}
}then you just call it with level=0
pos=the top left of your world,
and size=size of your world
This will split the world in to 4 separate sections, and then test each one, going THRESHOLD levels deep, and once it reaches that many levels, it just draws the stuff, but if at any level a node isnt visible, it stops.
#8 Members - Reputation: 3827
Posted 29 June 2011 - 07:11 AM
Each node of the tree can be in one of three states:
- Fully outside the frustum
- Fully inside the frustum
- Intersecting the frustum
- If a node is fully inside the frustum then all of it's children are also fully inside the frustum and don't need to be tested (trivial accept).
- If a node is fully outside the frustum then all of it's children are also fully outside the frustum and don't need to be tested (trivial reject).
- If a node intersects the frustum then it's children may be in any one of the three states, so you need to test them all.
- The top node will always intersect the frustum as it contains all of your geometry.
Pseudocode might look like this:
void TraverseQuadTree (node *n, int frustumcheck)
{
// if this has been cleared then the node's parent was fully inside the frustum
if (frustumcheck)
{
for (int planenum = 0; planenum < 6; planenum++)
{
// the parent node was fully inside the frustum on this plane so don't check
if (!(frustumcheck & (1 << planenum))) continue;
// we don't yet know...
int sidestate = UNDEFINED_UNKNOWN;
// ...so check; if it's fully outside we reject this node and all of it's children
if ((sidestate = FrustumPlaneTest (n, planenum)) == FULLY_OUTSIDE_FRUSTUM) return;
// if the node was fully inside the frustum on this plane all of it's children are
// also fully inside on this plane, so clear this plane from the list to check for them
if (sidestate == FULLY_INSIDE_FRUSTUM) frustumcheck &= ~(1 << planenum);
}
}
// do stuff here
// traverse child nodes
TraverseQuadTree (n->children[0], frustumcheck);
TraverseQuadTree (n->children[1], frustumcheck);
TraverseQuadTree (n->children[2], frustumcheck);
TraverseQuadTree (n->children[3], frustumcheck);
}
// check all 6 planes for the top node (63 == 111111)
TraverseQuadTree (topnode, 63);
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#10 Members - Reputation: 3827
Posted 29 June 2011 - 08:32 AM
You know the dimensions of your world, say it's 8192 units in each direction. This becomes your top node.
Divide this into 4 (for a quadtree) or 8 (for an octree) roughly equal sized areas; these are your top node's children.
Divide each of these recursively until you hit your threshold beyond which you don't divide any more.
So now we've got an empty tree structure that we need to populate. In order to do this we go through each object in the scene and figure which node it belongs in (Google for "octree insertion" for lots on info about this; also look for "loose octrees" which is a useful technique), then add it to a list of objects for that node.
In general terms you'll have three types of object:
- Static (unmoving) objects which just get added once (at load time); once you've added them you don't need to worry about them any more so far as this part of the job is concerned.
- Dynamic (moving) objects which need to be added every frame (or every time they move) and removed from their previous node (if they moved).
- Objects which you're not going to bother using the tree for because you've profiled and determined that it's faster to just draw them all; this might include particles.
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#11 Members - Reputation: 839
Posted 29 June 2011 - 10:40 AM
I'm a little bored and this is only a minor correction to the otherwise excellent explanation above:The top node will always intersect the frustum as it contains all of your geometry.
The top node will of course not always intersect the frustum, but it should always be evaluated in order for one to determine whether anything in the tree is visible. Obviously, mhagain suggests that if we need to check if a state is one of the 3 mentioned states, the root node could be set to the intersect state before every tree evaluation, to simplify things.
#12 Members - Reputation: 164
Posted 29 June 2011 - 11:08 AM
You know the dimensions of your world, say it's 8192 units in each direction.
I'm guessing this means that if my world is a giant box 10k*10k*10k then that's what I split my nodes up into? Split that up into consecutively smaller sections of 4 (or 8)? So if a node is within my view frustrum it gets drawn and all it's children nodes get checked and drawn (if visible) until we run out of nodes or the nodes are no longer visible? Is that right?
#13 Members - Reputation: 3827
Posted 29 June 2011 - 11:34 AM
I'm a little bored and this is only a minor correction to the otherwise excellent explanation above:
The top node will always intersect the frustum as it contains all of your geometry.
The top node will of course not always intersect the frustum, but it should always be evaluated in order for one to determine whether anything in the tree is visible. Obviously, mhagain suggests that if we need to check if a state is one of the 3 mentioned states, the root node could be set to the intersect state before every tree evaluation, to simplify things.
Absolutely correct, maybe something like "the top node is treated as if it intersects all 6 frustum planes"?
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#14 Members - Reputation: 3827
Posted 29 June 2011 - 11:39 AM
I guess I'm just not getting this. I understand checking the tree against the view frustrum. I'm not understanding how you build this tree.
You know the dimensions of your world, say it's 8192 units in each direction.
I'm guessing this means that if my world is a giant box 10k*10k*10k then that's what I split my nodes up into? Split that up into consecutively smaller sections of 4 (or 8)? So if a node is within my view frustrum it gets drawn and all it's children nodes get checked and drawn (if visible) until we run out of nodes or the nodes are no longer visible? Is that right?
That sounds roundabout right. Your top node will enclose a 10k*10k*10k volume, and (assuming an octree) each child at the next level is 5k*5k*5k.
The key bit of info that I skipped over above is that you test bounding boxes of nodes against the frustum, not bounding boxes of objects. The bounding box of an object is just used for inserting the object into the correct node, and from there you'll have groups of multiple objects in each node. By testing node bounding boxes you get to accept or reject multiple objects in one fell swoop.
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#15 Members - Reputation: 164
Posted 29 June 2011 - 02:39 PM
1: This one you already answered to a degree. What do you do with large objects? You (mhagain) said use an objects bounding box to determine the correct node to insert it in. That makes sense for objects whose centers are outside of view frustrum but protrude into the visible scene anyways. It makes sense that you'd want your largest models in your largest nodes. I'll get to my question for this is a second...
2: I can see how Quad-tree/Octree frustrum culling would be great for large static scenes. How about scenes with a LOT of moving objects? Unless there is a method here I'm not seeing, rebuilding your tree every frame would get expensive in a hurry and undo whatever optimization you might otherwise get.
I guess that pretty much sums it up for now; How do you handle your trees with a constantly changing scene?
#16 Members - Reputation: 3827
Posted 29 June 2011 - 03:55 PM
Large objects are a special case; with a traditional octree they tend to "bubble up" to larger nodes which reduces the effectiveness of the octree. Loose octrees (good description here) are a solution to this. They're also good for your last question - moving objects - as inserting an object into a node is faster than with a traditional octree.
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.






