基于SAH的BVH

const int nBuckets=12;
std::vector<Bounds3> buckets(nBuckets);
std::vector<int> numbuckets(nBuckets);

BVHBuildNode* BVHAccel::recursiveSAHBuild(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());
     int dim = bounds.maxExtent();
     int b=0;

      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 = recursiveSAHBuild(std::vector{objects[0]});
        node->right = recursiveSAHBuild(std::vector{objects[1]});

        node->bounds = Union(node->left->bounds, node->right->bounds);
        return node;
    }
    else{
    for(int i=0;i<objects.size();++i){
        switch(dim){
            case 0:
                b=nBuckets*bounds.Offset(objects[i]->getBounds().Centroid()).x;
                break;
            case 1:
                b=nBuckets*bounds.Offset(objects[i]->getBounds().Centroid()).y;
                break;
            case 2:
                b=nBuckets*bounds.Offset(objects[i]->getBounds().Centroid()).z;
                break;
        }
        
        if(b==nBuckets) b=nBuckets-1;
        numbuckets[b]= numbuckets[b]+1;
        buckets[b]=Union(buckets[b],objects[i]->getBounds());
    }

    float cost[nBuckets-1];
    for(int i=0;i<nBuckets-1;++i){
        Bounds3 b0,b1;
        int count0=0,count1=0;
        for(int j=0;j<=i;++j){
            b0=Union(b0,buckets[j]);
            count0+=numbuckets[j];
        }
        for(int j=i+1;j<nBuckets;++j){
            b1=Union(b1,buckets[j]);
            count1+=numbuckets[j];
        }
        cost[i]=1+(count0*b0.SurfaceArea()+count1*b1.SurfaceArea())/bounds.SurfaceArea();
    }
    float minCost=cost[0];
    int minCostSplitBucket=0;
    for(int i=1;i<nBuckets-1;++i){
        if(cost[i]<minCost){
            minCost=cost[i];
            minCostSplitBucket=i;
        }
    }

    int split=0;
    for(int m=0;m<=minCostSplitBucket;++m)
        split+=numbuckets[m];
   
        auto beginning = objects.begin();
        auto middling = objects.begin() + (split);
        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 = recursiveSAHBuild(leftshapes);
        node->right = recursiveSAHBuild(rightshapes);

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

    return node;
}

 

实现基于SAH的BVH构建。
①基于表面积的启发式评估划分方法(Surface Area Heuristic,SAH),
这种方法通过对求交代价和遍历代价进行评估,给出了每一种划分的代价(Cost),
而我们的目的便是去寻找代价最小的划分。
Cost=Ctrav+(S(A)*a+S(B)*b)/S(C);
其中S(A),S(B)分别为当前划分方式下左右两个包围盒的面积,S(C)为当前结点包含所有图元的包围盒面积;
a,b分别为左右两个包围盒分别包含的图元数;
Ctrav为遍历树状结构的代价,此处设置为1
②在实现的时候,相比于计算可能划分的代价然后寻找代价最小的划分,
一种更好的办法是将节点 所包围的空间沿着跨度最长的那个坐标轴的方向将空间均等的划分为若干个桶(Buckets),
划分只会出现在桶与桶之间的位置上。本算法中设置的桶的个数为12.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值