实现 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;
}

效果图

随机推荐

  1. 【牛客刷题】HJ13 句子逆序

    题目链接 题目本身不难,但是牛客的输入样例很坑,因此只好使用bufio来进行输入了: package main import ( "bufio" "fmt" & ...

  2. git忽略文件夹中除了指定的文件外的其他所有文件

    **/test/* !**/test/a.py

  3. Java 查询 MMDB 数据库

    MMDB-Lookup | GitHub Lookup.java: import java.io.File; import java.net.InetAddress; import com.faste ...

  4. C 语言编译过程

    编译过程 编译过程是将高级编程语言(如 C 语言)写成的源代码转换成机器可以执行的低级机器语言(通常是二进制代码)的过程.这个过程一般可以分为几个阶段: 预处理(Preprocessing): 预处理 ...

  5. HarmonyOS NEXT未成年人模式无缝联动所有应用,过滤非适龄内容

    背景 随着消费电子产品和移动互联网的普及,未成年人互联网普及率96.8%,超过80%的未成年人都拥有自己的上网设备,而如何引导孩子正确上网一直是家长们的担忧.市场上很多电子设备.系统推出了一些未成年人 ...

  6. JSP中的JSTL 标签库

    目录 JSTL 标签库 JSTL 标签库的使用步骤 core 核心库使用 <c:set /> (使用很少) <c:if /> <c:choose><c:whe ...

  7. [Tkey] 黑兔子,白兔子

    CL-21 一般拿到这个题第一眼都应该能看出并查集,subtask1 是给并查集暴力修改的. 后面 subtask2 没有联通操作,是给纯线段树的,也算是启发正解了 再往下可以考虑操作 \(1\) 采 ...

  8. 第22天:安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用

    #数据库操作-mysqli函数&增删改查 PHP函数:连接,选择,执行,结果,关闭等 参考:https://www.runoob.com/php/php-ref-mysqli.html 常用: ...

  9. AD域下,没有登录服务器处理登录请求

    原因: IP地址配置有问题 或者 DNS : 解决办法: 重新设置 IP地址 和 DNS : 此案例中, 切换到 test 账户(域管理员)后发现 , 未配置 IP地址 和 DNS :

  10. Codeforces[CF1036B]Diagonal Walking v.2题解

    题目大意 很明显,这道题就是求 k 步之内到达点 \((a,b)\) ,然后尽量走对角线,求能走对角线的最大值. 做题思路 首先明白一个事实,即一个对角线可以通过增加一步而抵达点不变,如图: 我们可以 ...