games101_Homework6

实现 Ray-Bounding Volume 求交与 BVH 查找

在本次编程练习中,你需要实现以下函数:

• IntersectP(const Ray& ray, const Vector3f& invDir, const std::array<int, 3="">& dirIsNeg) in the Bounds3.hpp: 这个函数的 作用是判断包围盒 BoundingBox 与光线是否相交,你需要按照课程介绍的算 法实现求交过程。

• getIntersection(BVHBuildNode* node, const Ray ray)in BVH.cpp: 建 立 BVH 之后,我们可以用它加速求交过程。该过程递归进行,你将在其中调 用你实现的 Bounds3::IntersectP. 

IntersectP(const Ray& ray, const Vector3f& invDir, const std::array<int, 3="">& dirIsNeg) 

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

    Vector3f t_enter_xzy = (pMin - ray.origin) * invDir;
    Vector3f t_exit_xzy  = (pMax - ray.origin) * invDir;
    // 如果光线在某一个轴上的分量是负数,则对应轴上的面越大越先进入
    if(!dirIsNeg[0]) std::swap(t_enter_xzy.x, t_exit_xzy.x);
    if(!dirIsNeg[1]) std::swap(t_enter_xzy.y, t_exit_xzy.y);
    if(!dirIsNeg[2]) std::swap(t_enter_xzy.z, t_exit_xzy.z);

    float tenter = std::max(std::max(t_enter_xzy.x, t_enter_xzy.y), t_enter_xzy.z);
    float texit  = std::min(std::min(t_exit_xzy.x, t_exit_xzy.y), t_exit_xzy.z);
    
    return tenter < texit && texit >= 0;
}
View Code

getIntersection(BVHBuildNode* node, const Ray ray)

Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
{
    Intersection res;
    // TODO Traverse the BVH to find intersection
    
    // 如果光线与改包围盒无交点,直接返回false的res
    if(!node->bounds.IntersectP(ray, ray.direction_inv, std::array<int, 3> 
    {ray.direction.x > 0, ray.direction.y > 0, ray.direction.z > 0})){
        return res;
    }
    // 如果当前节点为叶子节点,遍历node中的每一个物体使之于光线求交
    if(node->object){
        return node->object->getIntersection(ray);
    }

    // 如果当前节点的盒子与光线相交则分别递归到左右
    Intersection l = getIntersection(node->left, ray);
    Intersection r = getIntersection(node->right, ray);
    
    //如果有两个交点,返回较近的那个交点
    return l.distance <= r.distance ? l : r;
}
View Code

效果图

 

posted @ 2024-04-14 22:24  七星易  阅读(13)  评论(0编辑  收藏  举报