Games101Homework【6】Acceleration structure(Including framework analysis)
Code Analysis:
friend:
C++中友元(友元函数和友元类)的用法和功能_friend class a<b>-CSDN博客
[C++:不如Coding](11):友元函数与友元类_哔哩哔哩_bilibili
Here is a simple explanation:
By using the mechanism of classes, data hiding and encapsulation are achieved. Data members of a class are usually defined as private, while member functions are generally defined as public, thus providing an interface for communication between the class and the outside world. However, sometimes it is necessary to define functions that are not part of the class but need frequent access to the class's data members. In such cases, these functions can be defined as friend functions of the class. In addition to friend functions, there are also friend classes, both of which are collectively referred to as friends. The purpose of friends is to improve the efficiency of the program (by reducing the time overhead of type checking and security checks, etc.). However, they undermine the encapsulation and hiding of the class, allowing non-member functions to access the class's private members.
Why use friends: You don't have to write a public method for a special case separately (for example, for a man and a woman, there is a marry method that is generally called only once during the lifecycle of these two classes. If you give the man or woman class a public method, marry, it is unnecessary and would make the class overly complex).
Operator overloading:
C++运算符重载_哔哩哔哩_bilibili
std::Move:
The functionality of std::move is to convert a left-value into an r-value reference, and return that r-value reference, allowing the value to be used via the r-value reference for move semantics (move constructor or move assignment operator).
std::move()与移动构造函数_std::move的作用-CSDN博客
Architecture:
Let's look at the picture first:

The logical architecture is exceptionally clear now, and I've placed the source code (with comments) in another blog.
Games101Homework【6】Code Part-CSDN博客
Principle:
Checking if a ray intersects with a plane.:

Determine the entry point and exit point:

BVH Core Algorithm (Recursive):

Code:
Render():
Transform the manually added vectors into a new Ray object:
void Renderer::Render(const Scene& scene)
{std::vector<Vector3f> framebuffer(scene.width * scene.height);float scale = tan(deg2rad(scene.fov * 0.5));float imageAspectRatio = scene.width / (float)scene.height;Vector3f eye_pos(-1, 5, 10);int m = 0;for (uint32_t j = 0; j < scene.height; ++j) {for (uint32_t i = 0; i < scene.width; ++i) {// generate primary ray directionfloat x = (2 * (i + 0.5) / (float)scene.width - 1) *imageAspectRatio * scale;float y = (1 - 2 * (j + 0.5) / (float)scene.height) * scale;// TODO: Find the x and y positions of the current pixel to get the// direction// vector that passes through it.// Also, don't forget to multiply both of them with the variable// *scale*, and x (horizontal) variable with the *imageAspectRatio*Ray ray(eye_pos, normalize(Vector3f(x, y, -1)));// Don't forget to normalize this direction!framebuffer[m++] =scene.castRay(ray,scene.maxDepth);}UpdateProgress(j / (float)scene.height);}UpdateProgress(1.f);// save framebuffer to fileFILE* fp = fopen("binary.ppm", "wb");(void)fprintf(fp, "P6\n%d %d\n255\n", scene.width, scene.height);for (auto i = 0; i < scene.height * scene.width; ++i) {static unsigned char color[3];color[0] = (unsigned char)(255 * clamp(0, 1, framebuffer[i].x));color[1] = (unsigned char)(255 * clamp(0, 1, framebuffer[i].y));color[2] = (unsigned char)(255 * clamp(0, 1, framebuffer[i].z));fwrite(color, 1, 3, fp);}fclose(fp);
}
Triangle::getIntersection():
Calculate intersection information:
/*** 获取射线与三角形的交点信息* * @param ray 射线对象,包含射线的起点和方向* @return Intersection 结构体,包含交点是否发生、交点坐标、交点到射线起点的距离、* 对应的物体指针、交点处的法向量和材质信息*/
inline Intersection Triangle::getIntersection(Ray ray)
{Intersection inter; // 初始化交点信息结构体// 如果射线方向与三角形法向量的点积大于0,则射线方向与三角形面向反,不产生交点if (dotProduct(ray.direction, normal) > 0)return inter;double u, v, t_tmp = 0;// 计算pvec,这是进行交点计算的一部分Vector3f pvec = crossProduct(ray.direction, e2);// 计算行列式值det,用于后续交点计算double det = dotProduct(e1, pvec);// 如果行列式的绝对值小于EPSILON,表示方向向量几乎平行,不产生交点if (fabs(det) < EPSILON)return inter;// 计算行列式的倒数,用于简化后续计算double det_inv = 1. / det;// 计算tvec,这是计算u参数的一部分Vector3f tvec = ray.origin - v0;// 计算参数u,如果u不在0到1之间,则交点不在三角形上u = dotProduct(tvec, pvec) * det_inv;if (u < 0 || u > 1)return inter;// 计算qvec,用于计算v参数Vector3f qvec = crossProduct(tvec, e1);// 计算参数v,如果v不在0到1之间,或u+v不在0到1之间,则交点不在三角形上v = dotProduct(ray.direction, qvec) * det_inv;if (v < 0 || u + v > 1)return inter;// 计算临时距离参数t_tmp,用于进一步判断交点是否成立t_tmp = dotProduct(e2, qvec) * det_inv;// 判断t_tmp是否小于0,若小于0,则交点在射线的起点之后,不成立if(t_tmp<0){return inter;}// 如果以上所有条件都满足,则更新交点信息为有效交点inter.happened = true;inter.coords = ray(t_tmp); // 计算交点坐标inter.distance = t_tmp; // 保存交点到射线起点的距离inter.obj = this; // 保存对应的三角形对象指针inter.normal = normal; // 保存交点处的法向量inter.m = m; // 保存材质信息return inter;
}
IntersectP():
"Solve equations to calculate tEnter and tExit. Based on the direction of the ray, if it is emitted in the non-positive direction, then the smaller negative t is the exit point, and the larger one is the entry point (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 intersectsVector3f tEnter,tExit;tEnter= (pMin-ray.origin)*invDir;tExit = (pMax-ray.origin)*invDir;if(!dirIsNeg[0]){std::swap(tEnter.x,tExit.x);}if(!dirIsNeg[1]){std::swap(tEnter.y,tExit.y);}if(!dirIsNeg[2]){std::swap(tEnter.z,tExit.z);}float tenter,texit;tenter=std::max(tEnter.x,std::max(tEnter.y,tEnter.z));texit=std::min(tExit.x,std::min(tExit.y,tExit.z));return tenter<=texit&&texit>=0;}
getIntersection():
Implementing the core algorithm:
Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
{Intersection isect;// TODO Traverse the BVH to find intersectionif(!node->bounds.IntersectP(ray,ray.direction_inv,std::array<int,3>{ray.direction.x>0,ray.direction.y>0,ray.direction.z>0})) return isect;if((!node->left)&&(!node->right)){return node->object->getIntersection(ray);}auto hit1=getIntersection(node->left,ray);auto hit2=getIntersection(node->right,ray);return hit1.distance<hit2.distance?hit1:hit2;
}
Result:

cool!
相关文章:
Games101Homework【6】Acceleration structure(Including framework analysis)
Code Analysis: friend: C中友元(友元函数和友元类)的用法和功能_friend class a<b>-CSDN博客 [C:不如Coding](11):友元函数与友元类_哔哩哔哩_bilibili Here is a simple…...
应用运维文档1
统一nginx接入配置指南 Nginx配置规范 1:不带微服务编码上下文至后端,以metadata-ui为例 location段配置信息,location配置中维护微服务编码上下文信息 # app_code: metadata-ui 流水线名称: metadata-ui location ~ ^/metadata-ui/(?P.*) {set $app_code metadata-ui;p…...
手机如何在线制作gif?轻松一键在线操作
现在大家都喜欢使用手机来拍摄记录有趣的事物,但是时间长了手机里的视频越来越多导致手机存储空间不够了,这些视频又不想删除时应该怎么办呢?这个很简单,下面就给大家分享一款不用下载手机就能操作的视频转gif网站-GIF中文网&…...
ChatGPT 在做什么,为什么有效?
原文:What Is ChatGPT Doing … and Why Does It Work? 译者:飞龙 协议:CC BY-NC-SA 4.0 序言 这本简短的书试图从第一原理解释 ChatGPT 是如何工作的。在某种程度上,这是关于技术的故事。但它也是关于科学的故事。以及关于哲学…...
Linux实验2 初步使用shell
一:实验目的 学习Linux下的文件系统结构,了解最基本的Linux下的shell命令操作,例如ls, cd, cat等各种指令操作。 学习vim编辑器的使用方式,学习如何使用ssh连接远程服务器。 二:实验内容 1.请指出下面每…...
甘特图/横道图制作技巧 - 任务组
在甘特图中通过合理的任务分组可以让项目更加清晰,修改也更方便。 列如下面的甘特图一眼不太容易看清楚整体的进度。或者需要把所有的任务整体的延迟或者提前只能这样一个一个的任务调整,就比较麻烦。 通过给任务分组,看这上面整体的进度就…...
Web题记
反序列化补充知识: private变量会被序列化为:\x00类名\x00变量名 protected变量会被序列化为: \x00\*\x00变量名 public变量会被序列化为:变量名web254 这个逻辑不难,自己刚看的时候还奇怪是不是自己哪里想错了,因为…...
学习java第三十六天
Spring 官网列出的 Spring 的 6 个特征: 核心技术 :依赖注入(DI),AOP,事件(events),资源,i18n,验证,数据绑定,类型转换,SpEL。 测试 :模拟对象,…...
0205矩阵分块法-矩阵及其运算-线性代数
文章目录 1 分块矩阵的定义2 分块矩阵的运算(性质)3 按列分块与按行分块 结语 1 分块矩阵的定义 将矩阵A用若干条纵线和横线分成许多个小矩阵,每一个小矩阵称为A的子快,以子块为元素的形式上的矩阵称为分块矩阵。 2 分块矩阵的运算…...
1、java语法入门(找工作版)
文章目录 一、Java简介二、Java常量与变量1、标识符2、关键字3、变量4、类的命名规则5、数据类型6、基本数据类型字面值7、变量的定义与初始化8、ASCII码和Unicode编码9、转义字符10、类型转换11、常量 三、Java运算符1、算术运算符2、赋值运算符3、关系运算符4、逻辑运算符5、…...
arm的状态寄存器
目录 一、arm 的 PSRs二、CPSR2.1 CPSR_cxsf 三、SPSR四、APSR 一、arm 的 PSRs arm 中有很多程序状态寄存器(Program Status Registers,PSRs)用于存储处理器的状态信息,包括 CPSR\SPSR\FPSR\APSR 等: CPSRÿ…...
2024 蓝桥打卡Day34
20240406蓝桥杯备赛 1、学习蓝桥云课省赛冲刺课 【1-手写与思维】【2-递归与递推】2、学习蓝桥云课Java省赛无忧班 【1-语言基础】3、代码练习字符串排序大小写转换 (ccfcsp之前要是学了我就能上200了 啊啊啊啊 错过啊)斐波那契数列 递归解法纸张尺寸问题…...
华为海思校园招聘-芯片-数字 IC 方向 题目分享——第九套
华为海思校园招聘-芯片-数字 IC 方向 题目分享(有参考答案)——第九套 部分题目分享,完整版获取(WX:didadidadidida313,加我备注:CSDN huawei数字芯片题目,谢绝白嫖哈) 单选 1&…...
如何创建虚拟环境打包py文件
Python 项目通常依赖于特定的库和版本。不同的项目可能依赖于相同库的不同版本,这可能导致冲突。使用虚拟环境,你可以为每个项目创建一个独立的 Python 环境,每个环境都有自己的库和版本,从而避免了依赖冲突。 采用虚拟环境打包P…...
CSS 学习笔记 总结
CSS 布局方式 • 表格布局 • 元素定位 • 浮动布局(注意浮动的负效应) • flex布局 • grid布局(感兴趣的可以看下菜鸟教程) 居中设置 元素水平居中 • 设置宽度后,margin设置为auto • 父容器设置text-alig…...
基于Swin Transformers的乳腺癌组织病理学图像多分类
乳腺癌的非侵入性诊断程序涉及体检和成像技术,如乳房X光检查、超声检查和磁共振成像。成像程序对于更全面地评估癌症区域和识别癌症亚型的敏感性较低。 CNN表现出固有的归纳偏差,并且对于图像中感兴趣对象的平移、旋转和位置有所不同。因此,…...
MySQL主从的介绍与应用
mysql主从 文章目录 mysql主从1. 主从简介1.1 主从作用1.2 主从形式 2. 主从复制原理3. 主从复制配置3.1 mysql安装(两台主机安装一致,下面只演示一台主机操作)3.2 mysql主从配置3.2.1 确保从数据库与主数据库里的数据一样3.2.2 在主数据库里…...
pytest中文使用文档----12缓存:记录执行的状态
1. cacheprovider插件 1.1. --lf, --last-failed:只执行上一轮失败的用例1.2. --ff, --failed-first:先执行上一轮失败的用例,再执行其它的1.3. --nf, --new-first:先执行新加的或修改的用例,再执行其它的1.4. --cache…...
【代码随想录】哈希表
文章目录 242.有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和454. 四数相加 II383. 赎金信15. 三数之和18. 四数之和 242.有效的字母异位词 class Solution {public boolean isAnagram(String s, String t) {if(snull || tnull || s.length()!t.length()){return …...
绘图工具 draw.io / diagrams.net 免费在线图表编辑器
拓展阅读 常见免费开源绘图工具 OmniGraffle 创建精确、美观图形的工具 UML-架构图入门介绍 starUML UML 绘制工具 starUML 入门介绍 PlantUML 是绘制 uml 的一个开源项目 UML 等常见图绘制工具 绘图工具 draw.io / diagrams.net 免费在线图表编辑器 绘图工具 excalidr…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
