【GAMES101】作业6 加速结构
一.作业描述
二.作业解析
1. 递归构造BVH树分析
看视频学习后过了太久,BVH树怎么构造已经忘记了,这里重新根据作业提供的代码整理了一下思路,重新学习了。后面要递归BVH树去判断相交,所以了解一下BVH树的结构也是很必要的。
BVH树节点node属性:
Bound:包围盒;
left,right:左右指针;
object:Object类;
递归实现:
1.递归出口:
当场景中物体总数=1时,包围盒为当前物体的包围盒,左右节点为NULL,返回当前节点;
2.当场景中物体总数=2时,取两个物体的边界并集作为当前节点的包围盒,左右节点分别再进行一次递归;
3.一般递归思路:
取当前所有物体的包围盒并集作为当前节点的总包围盒大小,求出总包围盒大小三维(x,y,z)中长度最大的一个维度dim,并将所有物体的质心坐标在维度dim上的值进行排序,将排序后的前1/2物体和后1/2的物体分别作为左右子集继续进行递归。
归纳一下,BVH树叶节点中存储比较重要的信息就是包围盒bounds。
在遍历BVH树判断相交时,如果发现当前节点的左右指针均为空,就说明当前节点的包围盒大小已经不可再分了。
递归构造的代码在这里mark一下。
BVHBuildNode* BVHAccel::recursiveBuild(std::vector<Object*> objects)
{
BVHBuildNode* node = new BVHBuildNode();
// Compute bounds of all primitives in BVH node
Bounds3 bounds;
for (int i = 0; i < objects.size(); ++i)
bounds = Union(bounds, objects[i]->getBounds());
if (objects.size() == 1) {
// Create leaf _BVHBuildNode_
node->bounds = objects[0]->getBounds();
node->object = objects[0];
node->left = nullptr;
node->right = nullptr;
return node;
}
else if (objects.size() == 2) {
node->left = recursiveBuild(std::vector{
objects[0]});
node->right = recursiveBuild(std::vector{
objects[1]});
node->bounds = Union(node->left->bounds, node->right->bounds);
return node;
}
else {
Bounds3 centroidBounds;
for (int i = 0; i < objects.size(); ++i)
centroidBounds =
Union(centroidBounds, objects[i]->getBounds().Centroid());
int dim = centroidBounds.maxExtent();
switch (dim) {
case 0:
std::sort(objects.begin(), objects.end(), [](auto f1, auto f2) {
return f1->getBounds().Centroid().x <
f2->getBounds().Centroid