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; }
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; }
效果图