Games101作业6(BVH的构建和遍历)

BVH的构建

在这里插入图片描述
在场景中只有一个物体时,直接对该物体进行划分

对应代码

 node->bounds = objects[0]->getBounds();
        node->object = objects[0];
        node->left = nullptr;
        node->right = nullptr;
        node->area = objects[0]->getArea();
        return node;

在这里插入图片描述
在场景中有两个物体时,将两个物体包围起来,再分别进行划分,对于代码
在这里插入图片描述

		node->left = recursiveBuild(std::vector{objects[0]});
        node->right = recursiveBuild(std::vector{objects[1]});

        node->bounds = Union(node->left->bounds, node->right->bounds);
        node->area = node->left->area + node->right->area;
        return node;

当场景中有多个物体时,先找到xyz哪一项加起来的值最大,以最大的坐标进行排序,进行划分,以下图为例,如果X的和最大,即对X进行划分
在这里插入图片描述
在这里插入图片描述
对应代码

    else {
        Bounds3 centroidBounds;
        for (int i = 0; i < objects.size(); ++i)
            centroidBounds =
                Union(centroidBounds, objects[i]->getBounds().Centroid());
        // 判断xyz哪个坐标最大
        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().x;
            });
            break;
        case 1:
            std::sort(objects.begin(), objects.end(), [](auto f1, auto f2) {
                return f1->getBounds().Centroid().y <
                       f2->getBounds().Centroid().y;
            });
            break;
        case 2:
            std::sort(objects.begin(), objects.end(), [](auto f1, auto f2) {
                return f1->getBounds().Centroid().z <
                       f2->getBounds().Centroid().z;
            });
            break;
        }

        auto beginning = objects.begin();
        auto middling = objects.begin() + (objects.size() / 2);
        auto ending = objects.end();

        auto leftshapes = std::vector<Object*>(beginning, middling);
        auto rightshapes = std::vector<Object*>(middling, ending);

        assert(objects.size() == (leftshapes.size() + rightshapes.size()));

        node->left = recursiveBuild(leftshapes);
        node->right = recursiveBuild(rightshapes);

        node->bounds = Union(node->left->bounds, node->right->bounds);
        node->area = node->left->area + node->right->area;

代码冗余部分
在recursiveBuild中,有如下代码,bounds对象创建而未使用

Bounds3 bounds;
    for (int i = 0; i < objects.size(); ++i)
        bounds = Union(bounds, objects[i]->getBounds());

bounds对象的目的,找到该区域的包围盒,但可以通过方式找到包围盒,这种遍历方式较为耗时建议删除。
在这里插入图片描述

BVH的遍历

对BVH的结构的理解,在BVH的非叶子节点中,都有多个物体,所以走到只有叶子节点的时候才会真正的与物体求交,因此我们需要从根节点遍历到叶子节点,才进行与物体的求交

代码如下


Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
{
    // TODO Traverse the BVH to find intersection
    if (node == nullptr)
    {
        return Intersection();
    }

    std::array<int, 3> dirIsNeg;
    dirIsNeg[0] = (ray.direction[0] > 0);
    dirIsNeg[1] = (ray.direction[1] > 0);
    dirIsNeg[2] = (ray.direction[2] > 0);

    if ((node->bounds.IntersectP(ray, ray.direction_inv, dirIsNeg)) == false)
    {
        return Intersection();
    }

    // 在叶子结点
    if (node->left == nullptr && node->right == nullptr)
    {
        return node->object->getIntersection(ray);
    }

    Intersection left = getIntersection(node->left, ray);
    Intersection right = getIntersection(node->right, ray);

    if (left.distance < right.distance)
    {
        return left;
    }

    return right;

}

IntersectP是与包围盒如何求交,和课上内容一致,不做展开

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值