games101 作业2
题目
光栅化一个三角形
1. 创建三角形的 2 维 bounding box。
2. 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中心的屏幕空间坐标来检查中心点是否在三角形内。
3. 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度缓冲区 (depth buffer) 中的相应值进行比较。
4. 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (depth buffer)。
题解
本次作业需要实现代码框架中的两个接口:
void rst::rasterizer::rasterize_triangle(const Triangle& t);
static bool insideTriangle(int x, int y, const Vector3f* _v);
1. 在2D空间中,计算一个三角形的轴对称boundbox
只需要计算出三角形的三个顶点坐标中,x最大最小值,y最大最小值。即 ( x m i n , y m i n ) , ( x m a x , y m a x ) (x_{min},y_{min}),(x_{max},y_{max}) (xmin,ymin),(xmax,ymax)
使用<math.h>库实现如下:
int xMin, yMin, xMax, yMax;xMin = std::floor(std::min(std::min(v[0].x(),v[1].x()),v[2].x()));yMin = std::floor(std::min(std::min(v[0].y(), v[1].y()), v[2].y()));xMax = std::ceil(std::max(std::max(v[0].x(), v[1].x()), v[2].x()));yMax = std::ceil(std::max(std::max(v[0].y(), v[1].y()), v[2].y()));
注意:顶点坐标都是浮点数,但是我们计算出的包围盒必须是整型。左上角下取整,右下角上去整。
2. 判断像素的中心点是否在三角形内部
其实方法有很多种,具体可以参考这个博客。
最常用最高效的有两种:重心坐标法和向量叉积。
本次作业选用向量叉积法:
代码如下
static bool insideTriangle(int x, int y, const Vector3f* _v)
{ // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]auto v0_v1 = _v[1] - _v[0];auto v1_v2 = _v[2] - _v[1];auto v2_v0 = _v[0] - _v[2];auto v0_P = Vector3f(x, y, _v[0].z()) - _v[0];auto v1_P = Vector3f(x, y, _v[1].z()) - _v[1];auto v2_P = Vector3f(x, y, _v[2].z()) - _v[2];auto v0pCross = v0_v1.cross(v0_P);auto v1pCross = v1_v2.cross(v1_P);auto v2pCross = v2_v0.cross(v2_P);if (v0pCross.dot(v1pCross) >= 0 && v0pCross.dot(v2pCross) >= 0)return true;return false;
}
因为我们判断的是一个像素的中心点是否在三角形内部,所以需要给x,y 分别加0.5,即insideTriangle(x+0.5,y+0.5,t.v)
注意:Vector3f Triangle::v[3] 中存放的就是三角形的三个顶点。
3.根据插值得到的深度值和深度缓冲的深度值比较。
插值运算使用代码框架,所以这块比较简单。
代码如下
for (int i = xMin; i <= xMax; i++){for (int j = yMin; j <= yMax; j++){if (insideTriangle(i+0.5f, j+0.5f,t.v)){auto[alpha, beta, gamma] = computeBarycentric2D(i, j, t.v);float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();z_interpolated *= w_reciprocal;int index = get_index(i, j);if (depth_buf[index] > z_interpolated){depth_buf[index] = z_interpolated; // 更新深度缓冲区set_pixel(Vector3f(i,j,z_interpolated),t.getColor());}}}}
注意:如果当前z值小于深度缓冲区的深度值,一定要更新深度缓冲区。
结果
代码:
static bool insideTriangle(int x, int y, const Vector3f* _v)
{ // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]auto v0_v1 = _v[1] - _v[0];auto v1_v2 = _v[2] - _v[1];auto v2_v0 = _v[0] - _v[2];auto v0_P = Vector3f(x, y, _v[0].z()) - _v[0];auto v1_P = Vector3f(x, y, _v[1].z()) - _v[1];auto v2_P = Vector3f(x, y, _v[2].z()) - _v[2];auto v0pCross = v0_v1.cross(v0_P);auto v1pCross = v1_v2.cross(v1_P);auto v2pCross = v2_v0.cross(v2_P);if (v0pCross.dot(v1pCross) >= 0 && v0pCross.dot(v2pCross) >= 0)return true;return false;
}void rst::rasterizer::rasterize_triangle(const Triangle& t) {auto v = t.toVector4();int xMin, yMin, xMax, yMax;xMin = std::floor(std::min(std::min(v[0].x(),v[1].x()),v[2].x()));yMin = std::floor(std::min(std::min(v[0].y(), v[1].y()), v[2].y()));xMax = std::ceil(std::max(std::max(v[0].x(), v[1].x()), v[2].x()));yMax = std::ceil(std::max(std::max(v[0].y(), v[1].y()), v[2].y()));for (int i = xMin; i <= xMax; i++){for (int j = yMin; j <= yMax; j++){if (insideTriangle(i+0.5f, j+0.5f,t.v)){auto[alpha, beta, gamma] = computeBarycentric2D(i, j, t.v);float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();z_interpolated *= w_reciprocal;int index = get_index(i, j);if (depth_buf[index] > z_interpolated){depth_buf[index] = z_interpolated;set_pixel(Vector3f(i,j, z_interpolated),t.getColor());}}}}
}
参考文献
判断点是否在三角形内
相关文章:
games101 作业2
题目 光栅化一个三角形 1. 创建三角形的 2 维 bounding box。 2. 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中心的屏幕空间坐标来检查中心点是否在三角形内。 3. 如果在内部,则将其位置处的插值深度值 (…...
二叉树链式存储结构
目录 1.二叉树链式存储结构 2.二叉树的遍历 2.1 前、中、后序遍历 2.2 层序遍历 3.二叉树的其他递归问题 3.1 二叉树的结点个数 3.2 二叉树的叶子结点个数 3.3 二叉树第k层结点个数 3.4 二叉树的深度 3.5 二叉树查找 3.6 二叉树销毁 4.二叉树的基础OJ题 4.1 单值…...
Claude 使用指南 | 可与GPT-4媲美的语言模型
本文全程干货,让你轻松使用上claude,这也是目前体验cluade的唯一途径!废话不多说,直接上教程,cluade的能力不逊于GPT4,号称是ChatGPT4.0最强竞品。相对Chatgpt来说,Claude不仅是完全免费的&…...
【汇编】微处理器
【汇编】微处理器 文章目录 【汇编】微处理器1、微处理器概念1.1 关键词1.2 分类 2、微处理器结构2.1 寄存器2.2 寄存器&汇编助记符2.3 寄存器组成结构 3、地址空间3.1 存储空间3.1.1 虚拟空间(编程空间)3.1.2 线性空间 3.2 I/O空间 4、工作模式4.1 …...
按键点亮led灯
原理图: K0这个按键按下时,开发板D1这个灯亮,松开,灯灭 代码如下: #include "stm32f4xx.h" void LED_Init(void) {//1.定义一个GPIO外设的结构体变量 GPIO_InitTypeDef GPIO_InitStructure;//RCC_AHB1PeriphClockCmd(RCC_AHB1Pe…...
Java常见面试题
目录 1、mysql并发事务会带来哪些问题,如何解决?2、请详细描述Redis持久化机制?3、简述Redis缓存雪崩和缓存穿透的问题和解决方案?4、RabbitMQ消息丢失及对应解决方案5、什么叫线程安全?举例说明6、举例说明常用的加密…...
笔记1.5:计算机网络体系结构
从功能上描述计算机网络结构 分层结构 每层遵循某个网络协议完成本层功能 基本概念 实体:表示任何可发送或接收信息的硬件或软件进程。 协议是控制两个对等实体进行通信的规则的集合,协议是水平的。 任一层实体需要使用下层服务,遵循本层…...
【Python】Python 连接字符串应优先使用 join 而不是 +
Python 连接字符串应优先使用 join 而不是 简介 字符串处理在大多数编程程序语言中都不可避免,字符串的连接也是在编程过程中经常需要面对的问题。 Python中的字符串与其他一些程序语言如C、Java有一些不同,它为不 可变对象。 一旦创建便不能改变&…...
uniapp 小程序 父组件调用子组件方法
答案:配合小程序API > this.selectComponent(""),来选择组件,再使用$vm选择组件实例,再调用方法,或者data 1 设置组件的id,如果你的多端,请跟据情况设置ref,class,id,以便通过小…...
Vue-01:MVVM数据双向绑定与Vue的生命周期
一、Vue介绍 1.1 什么是Vue ? Vue是一个渐进式的JavaScript框架,用于构建用户界面。"渐进式"意味着Vue的设计理念是逐步增强应用的功能和复杂性,而不是一次性地引入所有功能。这使得开发者可以根据项目需求选择性地使用Vue的不同特…...
数据通信网络之OSPFv3基础
文章及资源归档至【AIShareLab】,回复 通信系统与网络 可获取。 文章目录 一、目的二、拓扑三、需求四、步骤 一、目的 掌握路由器的IPv6 基础配置。掌握OSPFv3(单区域)的基础配置。 二、拓扑 如图1 所示,三台路由器R1、R2 和R…...
FPGA-结合协议时序实现UART收发器(五):串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive
FPGA-结合协议时序实现UART收发器(五):串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive 串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive,功能实现。 文章目录 FPGA-结合协议时序实现UART收发器(五&…...
我学编程全靠B站了,真香-国外篇(第三期)
你好,我是Martin。 今天来点猛料,给大家推荐点我的压箱收藏-国外知名大学的公开课。 我推荐的不多,本着少就是多的原则,只给大家推荐我看过最好的五门视频,主要是来自两所国外高校:MIT美国麻省理工、CMU卡…...
c++ 变量常量指针练习题
Q1:在win32 x86模式下,int *p; int **pp; double *q; 请说明p、pp、q各占几个字节的内存单元。 p 占 4 个字节 pp 占 4 个字节 q 占 4 个字节 Q2常量1、1.0、“1”的数据类型是什么? 1 是 整形 int 1.0 是 浮点型 double “1” 是 const char * Q3 语句&…...
Linux底层基础知识
一.汇编,C语言,C,JAVA之间的关系 汇编,C语言,C可以通过不同的编译器,编译成机器码。而java只能由Java虚拟机识别。Java虚拟机可以看成一个操作系统,Java虚拟机是由汇编,C,…...
JUC并发编程--------线程安全篇
目录 什么是线程安全性问题? 如何实现线程安全? 1、线程封闭 2、无状态的类 3、让类不可变 4、加锁和CAS 并发环境下的线程安全问题有哪些? 1、死锁 2、活锁 3、线程饥饿 什么是线程安全性问题? 我们可以这么理解&#…...
机器视觉之Basler工业相机使用和配置方法(C++)
basler工业相机做双目视觉用,出现很多问题记录一下: 首先是多看手册:https://zh.docs.baslerweb.com/software 手册内有所有的源码和参考示例,实际上在使用过程中,大部分都是这些源码,具体项目选择对应的…...
Centos nginx配置文档
1、安装nginx: yum install nginx 2、Nginx常用命令 查看版本:nginx -v 启动:nginx -c /etc/nginx/nginx.conf 重新加载配置:nginx -s reload 停止:nginx -s stop 3、Nginx反向代理配置 nginx配置详解 1、Nginx配置图 详情可以查看:http://nginx.org/ru/docs/example…...
2023/9/14 -- C++/QT
作业: 仿照Vector实现MyVector,最主要实现二倍扩容 #include <iostream>using namespace std;template <typename T> class MyVector { private:T *data;size_t size;size_t V_capacity; public://无参构造MyVector():data(nullptr),size(…...
golang在goland编译时获取环境变量失效
在golang中, 我们通常使用os包来获取环境变量,如: os.Getenv() os.LookupEnv() 等。 但如果我们使用goland编译器,在编译是,这时操作环境变量,会发现os包读取到的环境变量值不变: 新增后&am…...
一款非常容易上手的报表工具,简单操作实现BI炫酷界面数据展示,驱动支持众多不同类型的数据库,可视化神器,免开源了
一款非常容易上手的报表工具,简单操作实现BI炫酷界面数据展示,驱动支持众多不同类型的数据库,可视化神器,免开源了。 在互联网数据大爆炸的这几年,各类数据处理、数据可视化的需求使得 GitHub 上诞生了一大批高质量的…...
蓝桥杯 题库 简单 每日十题 day3
01 约数个数 题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 1200000 有多少个约数(只计算正约数)。 解题思路 枚举,从1开始一直到1200000本身都作为1200000的除数,…...
基于SSM+Vue的高校实验室管理系统的设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用Vue技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...
C语言天花板——指针(初阶)
🌠🌠🌠 大家在刚刚接触C语言的时候就肯定听说过,指针的重要性以及难度等级,以至于经常“谈虎色变”,但是今天我来带大家走进指针的奇妙世界。🎇🎇🎇 一、什么是指针&…...
关于第一届全球电子纸创新应用金奖征集评选及报名指南
重要通知 |关于第一届全球电子纸创新应用金奖征集评选及报名指南https://mp.weixin.qq.com/s/RWsZtmJ20-NZXMG0k0rwPA?wxwork_useridEPIA 从2004年,Sony推出全球首款电纸书阅读器至今20载,这期间,到底诞生了多少种创新产品&#…...
idea搭建项目找不到Tomcat
idea搭建项目找不到Tomcat_idea没有tomcat配置项_ZYRL的博客-CSDN博客...
类和对象三大特性之继承
全文目录 继承的概念定义格式继承关系和访问限定符final 基类和派生类对象赋值转换继承中的作用域派生类的六个默认成员函数构造函数拷贝构造函数operator析构函数 友元和静态成员友元静态成员 各种继承形式菱形继承虚继承菱形虚拟继承对象模型 继承和组合 继承的概念 通过继承…...
Debian 12安装Docker
1.更新系统包 #apt update 2.安装依赖包 #apt install apt-transport-https ca-certificates curl gnupg lsb-release 3.添加Docker源 (1)添加Docker 官方GPG密钥 #curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/s…...
小谈设计模式(4)—单一职责原则
小谈设计模式(4)—单一职责原则 专栏介绍专栏地址专栏介绍 单一职责原则核心思想职责的划分单一变化原则高内聚性低耦合性核心总结 举例图书类(Book)用户类(User)图书管理类(Library)…...
ATF(TF-A) EL3 SPMC威胁模型-安全检测与评估
安全之安全(security)博客目录导读 ATF(TF-A) 威胁模型汇总 目录 一、简介 二、评估目标 1、数据流图 三、威胁分析 1、信任边界 2、资产 3、威胁代理 4、威胁类型 5、威胁评估 5.1 端点在直接请求/响应调用中模拟发送方FF-A ID 5.2 端点在直接请求/响应调用中模拟…...
个人做流量大的网站/成都最新动态
业务逻辑:表myupload做了增加、修改、删除时,在表myuploaddaybook新增一条用来记录myupload表变化的行。myupload表CREATE TABLE myupload (uploadid int(11) NOT NULL AUTO_INCREMENT,bookid int(11) DEFAULT NULL,numb int(11) DEFAULT NULL,saleuseri…...
淘宝网的网站设计方案/河北百度seo关键词
《中国古代文学(六)》作业 一、填空题 1、在晚明文学领域中,公安派提出了一系列体现晚明文学新价值观的理论主张,( )为其理论内核。 2、( “ ” )是明代创作成就最高的白话短篇小说…...
ie浏览器网址入口/沈阳seo关键字优化
我搜索了相关的帖子并尝试了一些方法,但是在使用Python3语法时,我仍然收到Vim中的语法错误。在接收错误的代码:types_of_people 10; f"There are {types_of_people} types of people."运行$ vim --version的输出:^{pr2…...
做整合营销的网站/温州最好的seo
8.3 Spring Boot集成Scala混合Java开发 本章我们使用Spring Boot集成Scala混合Java开发一个Web性能测试平台。 使用到的相关技术: 后端: phantomjsscalajavaspringbootvelocityjpamavenmysql前端: jquerybootstrapadminLTEhtml/cssScala是一门…...
婺源旅游攻略/网站关键词优化网站推广
学习要点 初识PHP基础语法变量常量运算符表达式学习目标 掌握PHP基础语法掌握PHP变量掌握PHP常量掌握PHP表达式掌握PHP运算符初识PHP 第一个PHP程序 编写代码1、使用记事本编写代码,保存为hello.php。 2、文件保存在D:\wamp\www目录 3、IE地址栏访问:htt…...
快速学制作网站/阿里指数
最近工作的事情比较忙,导致CLR很久没有更新了,恰巧周五听了涛涛的关于GC和内存管理的技术分享,想了下自己对CLR的学习得跟上,另外之前武哥推荐了一本书叫《码农翻身》,是一个IBM架构师写的,读了几页觉的非常…...