IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> games101_作业2 -> 正文阅读

[数据结构与算法]games101_作业2

题目:
需要填写的函数有以下两个:

  • rasterize_triangle(): 执行三角形栅格化算法

在上次作业中,虽然我们在屏幕上画出一个线框三角形,但这看起来并不是 那么的有趣。所以这一次我们继续推进一步——在屏幕上画出一个实心三角形, 换言之,栅格化一个三角形。上一次作业中,在视口变化之后,我们调用了函数 rasterize_wireframe(const Triangle& t)。但这一次,你需要自己填写并调用函数 rasterize_triangle(const Triangle& t)。

该函数的内部工作流程如下:

  1. 创建三角形的 2 维 bounding box。
  2. 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中
    心的屏幕空间坐标来检查中心点是否在三角形内。
  3. 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度
    缓冲区 (depth buffer) 中的相应值进行比较。
  4. 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (depth buffer)。
  • static bool insideTriangle(): 测试点是否在三角形内。你可以修改此函
    数的定义,这意味着,你可以按照自己的方式更新返回类型或函数参数。

测试点是否在三角形内的函数:

//x,y是观测点的x和y值
static bool insideTriangle(double x, double 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]
	Eigen::Vector2f p;	//检测目标
	p << x, y;
	
	//.head(2):取向量的前两个数值
	Eigen::Vector2f AB = _v[1].head(2) - _v[0].head(2);//AB = B - A  即A->B,后面以此类推
	Eigen::Vector2f BC = _v[2].head(2) - _v[1].head(2);
	Eigen::Vector2f CA = _v[0].head(2) - _v[2].head(2);

	Eigen::Vector2f AP = p - _v[0].head(2);	//各个顶点到观测点的向量
	Eigen::Vector2f BP = p - _v[1].head(2);
	Eigen::Vector2f CP = p - _v[2].head(2);
	
	// 做向量叉积,返回值为判断结果是否为相同符号,判断每个z坐标是否统一。
	return AB[0] * AP[1] - AB[1] * AP[0] > 0 
		&& BC[0] * BP[1] - BC[1] * BP[0] > 0
		&& CA[0] * CP[1] - CA[1] * CP[0] > 0;
}

光栅化函数:

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();//这里是把三角形结构体换成三个顶点如(x1,y1,z1,1),最后的1表示它是一个点,用于齐次坐标
			   
    //bounding box
    float min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));
    float max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));
    float min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));
    float max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));

    min_x = static_cast<int>(std::floor(min_x));
    min_y = static_cast<int>(std::floor(min_y));
    max_x = static_cast<int>(std::ceil(max_x));
    max_y = static_cast<int>(std::ceil(max_y));

	//左边界小数部分全部直接舍,右边界小数部分直接入,确保单元边界坐标都是整数,三角形一定在bounding box内。

    bool MSAA = true;//MSAA是否启用

    if (MSAA)
    {
        std::vector<Eigen::Vector2f> pos
        {                               //对一个像素分割四份 当然你还可以分成4x4 8x8等等甚至你还可以为了某种特殊情况设计成不规则的图形来分割单元
            {0.25,0.25},                //左下
            {0.75,0.25},                //右下
            {0.25,0.75},                //左上
            {0.75,0.75}                 //右上
        };
        for (int i = min_x; i <= max_x; ++i)
        {
            for (int j = min_y; j <= max_y; ++j)
            {
                int count = 0;
                float minDepth = FLT_MAX;
                for (int MSAA_4 = 0; MSAA_4 < 4; ++MSAA_4)
                {
                    if (insideTriangle(static_cast<float>(i+pos[MSAA_4][0]), static_cast<float>(j+pos[MSAA_4][1]),t.v))
                    {
			    		auto[alpha, beta, gamma] = computeBarycentric2D(static_cast<float>(i + pos[MSAA_4][0]), static_cast<float>(j + pos[MSAA_4][1]), 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;

                        minDepth = std::min(minDepth, z_interpolated);
                        ++count;
                    }
                }
                if (count)
                {
                    if (depth_buf[get_index(i, j)] > minDepth)
                    {
                        depth_buf[get_index(i, j)] = minDepth;//更新深度

                        Eigen::Vector3f color = t.getColor() * (count / 4.0);//对颜色进行平均,使得边界更平滑,也是一种模糊的手段
                        Eigen::Vector3f point;
                        point << static_cast<float>(i), static_cast<float>(j), minDepth;
                        set_pixel(point, color);//设置颜色
                    }
                }
            }
        }
    }
    else
    {
		for (int i = min_x; i <= max_x; ++i)
		{
			for (int j = min_y; j <= max_y; ++j)
			{
				if (insideTriangle(static_cast<float>(i+0.5), static_cast<float>(j+0.5),t.v))
				{
					auto [alpha, beta, gamma] = computeBarycentric2D(static_cast<float>(i + 0.5), static_cast<float>(j + 0.5), 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;

					if (depth_buf[get_index(i, j)] > z_interpolated)
					{
						depth_buf[get_index(i, j)] = z_interpolated;//更新深度
						Eigen::Vector3f color = t.getColor();
						Eigen::Vector3f point;
						point << static_cast<float>(i), static_cast<float>(j), z_interpolated;
						set_pixel(point, color);//设置颜色
					}
				}
			}
		}
	}
}


在一开始的时候三角形是黄色三角形在后,蓝色三角形在前。并且两个三角形都是朝下方向,在上网查询后发现可能出错的原因是:

  • opencv左上为原点,课程中左下为原点,所以导致y,z两轴是反着的。

最后的效果:
上下未修正
这是最后的效果,本来两个三角形的顺序是相反的,发现pdf要求的不一样,又上网查阅,更改了get_projection_matrix()函数的zNear和zFar,让这两个参数在形参列表的位置互换。

但又在我想更改上下方向的时候,也就是更改了get_projection_matrix()函数中的

  • zNear/zFar *=-1;
  • float top = – tan(halve)*zNear;

发现出现了下图的效果:
在这里插入图片描述
目前这个bug还未修正,等以后学习更多再回来思考更改。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 13:00:34  更:2021-11-17 13:01:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:44:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码