作业6 BVH包围盒加速

作业6介绍加速结构

enter image description here

求BVH

是前面几天前写的代码,但是今天才写笔记。

这几天实验室网线没网。自己拖了,然后也耽搁了。

凭着自己的理解,然后看看网上人家的代码的思路。

首先是修改作业5的一个函数
inline Intersection Triangle::getIntersection(Ray ray)
{
    Intersection inter;

    if (dotProduct(ray.direction, normal) > 0)
        return inter;
    double u, v, t_tmp = 0;
    Vector3f pvec = crossProduct(ray.direction, e2);
    double det = dotProduct(e1, pvec);
    if (fabs(det) < EPSILON)
        return inter;

    double det_inv = 1. / det;
    Vector3f tvec = ray.origin - v0;
    u = dotProduct(tvec, pvec) * det_inv;
    if (u < 0 || u > 1)
        return inter;
    Vector3f qvec = crossProduct(tvec, e1);
    v = dotProduct(ray.direction, qvec) * det_inv;
    if (v < 0 || u + v > 1)
        return inter;
    t_tmp = dotProduct(e2, qvec) * det_inv;

    // TODO find ray triangle intersection
    //和作业5差不多,需要讲一些值赋给Intersection。
    if(t_tmp>EPSILON&&u>EPSILON&&v>EPSILON&&1-u-v>EPSILON) {
        inter.happened = true;
        inter.coords = ray.origin+t_tmp*ray.direction;
        inter.normal = normal;
        inter.distance = t_tmp;
        inter.obj = this;
        inter.m = m;
    }

    return inter;
}
判断与包围盒是否相交
inline bool Bounds3::IntersectP(const Ray& ray, const Vector3f& invDir,
                                const std::array<int, 3>& dirIsNeg) const
{
    // invDir: ray direction(x,y,z), invDir=(1.0/x,1.0/y,1.0/z), use this because Multiply is faster that Division,光线,光线方向的倒数,光线的方向是否是反的
    // dirIsNeg: ray direction(x,y,z), dirIsNeg=[int(x>0),int(y>0),int(z>0)], use this to simplify your logic
    // TODO test if ray bound intersects就是求每个面的进入时间、离开时间,然后进入时间取最大,离开时间取最小,然后判断,课上讲过,知道参数代表的意义,容易写出来。
    float t_mi_x = (pMin.x-ray.origin.x)*invDir[0];
    float t_mi_y = (pMin.y-ray.origin.y)*invDir[1];
    float t_mi_z = (pMin.z-ray.origin.z)*invDir[2];
    
    float t_ma_x = (pMax.x-ray.origin.x)*invDir[0];
    float t_ma_y = (pMax.y-ray.origin.y)*invDir[1];
    float t_ma_z = (pMax.z-ray.origin.z)*invDir[2];

    if(!dirIsNeg[0]) {
        float tmp = t_mi_x;
        t_mi_x = t_ma_x;
        t_ma_x = tmp;
    }

    if(!dirIsNeg[1]) {
        float tmp = t_mi_y;
        t_mi_y = t_ma_y;
        t_ma_y = tmp;
    }

    if(!dirIsNeg[2]) {
        float tmp = t_mi_z;
        t_mi_z = t_ma_z;
        t_ma_z = tmp;
    }

    float t_enter = fmax(t_mi_x,fmax(t_mi_y,t_mi_z));
    float t_exit = fmin(t_ma_x,fmin(t_ma_y,t_ma_z));
    if(t_enter<=t_exit&&t_exit>=0) return true;
    return false;
}
BVH加速求交
Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
{
    // TODO Traverse the BVH to find intersection
    // 首先是个递归的过程,还是先要把光线方向的正反求出来。然后
    // 如果这个节点和光线不相交,直接返回
    // 如果这个节点是叶子节点,那么直接计算和这个节点的物体的相交。
    // 然后分别求左儿子右儿子的相交,返回距离小的一个,因为光线先打到距离小的那个嘛。
    std::array<int,3> dirIsNeg;
    dirIsNeg[0] = (ray.direction[0]>0);
    dirIsNeg[1] = (ray.direction[1]>0);
    dirIsNeg[2] = (ray.direction[2]>0);

    Intersection inter;
    if(!node->bounds.IntersectP(ray,ray.direction_inv,dirIsNeg)) {
        return inter;
    }
    if(node->left==nullptr&&node->right==nullptr) {
        return node->object->getIntersection(ray);
    }
    Intersection lson = getIntersection(node->left,ray);
    Intersection rson = getIntersection(node->right,ray);
    if(lson.distance<rson.distance) return lson;
    else return rson;
}