5 hours ago, VanillaSnake21 said:
Oh traversing? I use this method:
Ok, so i see this is clear to you. Then maybe the reason for the initial confusion must me something else, but there is no reason for that anyways.
About your tree construction code, there is the problem you sort just once, but you have to select the splitting axis for each individual split and resort.
Here an 2D example with 3 levels:
![image.png.7e02dc1a3ed43cad457aa1e32ecf2c81.png](https://uploads.gamedev.net/monthly_2019_08/image.png.7e02dc1a3ed43cad457aa1e32ecf2c81.png)
1. Box is wider than high so choose X axis to split the root.
2. Both childs are now higher than wide, so choose Y now for both.
3. After calculating the bounding boxes, we see that 3 children are wider than high, but one became higher because there are no triangles in the top right area. So 3 children will use X, but one Y for the next split.
This is why you have to alternate splitting axis, and for the same reason the contained triangles need to be resorted again for each split as well along that changing axis.
The approach you seem to use would work only in the 1D case, but it's not enough for 2D/3D.
Some other, minor things:
There should be no need to handle the root node with special code neither for building nor for traversal (can be simplified).
Allocating new nodes with new (assuming there is no overloaeded momory management by your side here) can place them in fragmented memory positions. Instead you may want to write them just to an array or std::vector, so the nodes keep together. Order will be fine automatically. Both child nodes can be stored one after another, and you could use indices instead pointers. But you can care later for such optimizations.
Casting to float for rounding is not better than just numTrianglesInRange/2 ![;) ;)](https://uploads.gamedev.net/emoticons/medium.wink.webp)
About the traversal:
Again no need to handle root node differently.
Bug: You return after the query point has been found to be in one of the children. But BVH bounds will overlap! So you still have to test and process the other child as well!
![image.png.6fa07217e117dc54e440c756e2010109.png](https://uploads.gamedev.net/monthly_2019_08/image.png.6fa07217e117dc54e440c756e2010109.png)
Example, bloe bot is the query point, if you would return after assigning it to theleft green child node, you would miss the collision with the box contained in right green child.
So, unfortunately with BVH or loose octree you have to traverse multiple branches because of overlaps.
Minor, but worth to mention: You use recursion for both traversal and build, this way the programming language manages the stack for you. I started with this too, but it may be not the best way to learn it, and it is not the most efficient way either. Managing the stack yourself lets you see what happens better. Difference between breath first / depth first becomes more clear, caching is better, dynamic allocation can be avoided.
The point query would look like this, as an example:
std::vector<int> stack (totalNumberOfNodes); // don't need the stack to be so huge, but to keep it simple
stack[0] = root;
int tail = 1;
for (int i=0; i<tail; i++)
{
int current = stack[i]; // pop current node from stack, initially the root
int child = nodes[current].child; // left child
if (child == -1) continue; // skip if there are no children (i assume there are alwayes either both or none)
if (nodes[child].bBox.Contains(queryPoint)) stack[tail++] = child; // push child to stack
child++; // make it the right child
if (nodes[child].bBox.Contains(queryPoint)) stack[tail++] = child;
}
I hope i did that correctly. If so, after the traversal has completed the stack contains all nodes that enclose the query point. Just to show going without recusrion is not more complex or difficult, and having access to the stack is useful. Notice this is breadth first while your recursion leads to depth first. For RT the latter can be better.
But just to say - make it work first the way it's easiest for you and care for such things later.
5 hours ago, VanillaSnake21 said:
@Gnollrunner I see what you mean, I actually do have a collision box associated with a character, I suppose I can just check the triangles inside the BVH volume that my character is in for collision instead of just using a ray? At this moment I'm just using a single point to see if I can get the BVH to work correctly.
Not quite. If your character is more than just a point, it will end up being in multiple nodes (even if node bounds would not overlap). So you need to find all nodes that intersect, and test against all contained triangles.
But otherwise you are right, and if your character is made by a capsule it would work like so: Calc bounding box over the capsule, use it as query box to find all overlapping BVH nodes and test all triangles from that for intersection with the capsule.