games101_作业1

题目:
本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。给定三维下三个
点 v0(2.0, 0.0, −2.0), v1(0.0, 2.0, −2.0), v2(−2.0, 0.0, −2.0), 你需要将这三个点的坐
标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形 (在代码框架中,我们已
经提供了 draw_triangle 函数,所以你只需要去构建变换矩阵即可)。简而言之,
我们需要进行模型、视图、投影、视口等变换来将三角形显示在屏幕上。在提供
的代码框架中,我们留下了模型变换和投影变换的部分给你去完成。
如果你对上述概念有任何不清楚或疑问,请复习课堂笔记或询问助教。
以下是你需要在 main.cpp 中修改的函数(请不要修改任何的函数名和其他
已经填写好的函数,并保证提交的代码是已经完成且能运行的):

  • get_model_matrix(float rotation_angle): 逐个元素地构建模型变换矩
    阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵,
    而不用处理平移与缩放。
  • get_projection_matrix(float eye_fov, float aspect_ratio, float
    zNear, float zFar): 使用给定的参数逐个元素地构建透视投影矩阵并返回
    该矩阵。

这里的具体过程可以参考我写的笔记来完成:网页链接

这里直接贴代码,会在代码中进行一些注释:

get_model_matrix()函数

Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
	Eigen::Matrix4f model = Eigen::Matrix4f::Identity();//新建一个4x4的矩阵
	rotation_angle = (rotation_angle / 180.0) * MY_PI;//角度转弧度
	Eigen::Matrix4f translate;
	translate << cos(rotation_angle), -sin(rotation_angle), 0, 0,
		 sin(rotation_angle), cos(rotation_angle), 0, 0,
		 0, 0, 1.0f, 0,
		 0, 0, 0, 1.0f;
	//PS:绕X、Z轴旋转的旋转矩阵同理,绕Y轴的旋转矩阵略有不同,sin和-sin的位置会互换
	model = translate * model;
	return model;
}

在这里我想要插入一张图片,这里有一个非常需要注意的地方是关于z轴的朝向,我一开始并没有注意这个问题,所以一开始画出来的图形是一个倒三角形,但正确图形应该是一个正三角形。
在这里插入图片描述请注意:

  • 摄像机上方是y正半轴,右边是x正半轴、看向z负半轴
  • 现在假设我们站在x正半轴 看向x负半轴
  • eye_fov:视角,摄像机最上方能看到的角度到最下方能看到的角度
  • aspect_ratio:矩形宽高比
  • zNear、zFar:近处面的z值,远处面的z值,注意,朝向z负半轴,即两者均为负值

get_projection_matrix()函数

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
	Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

	//透视图,近大远小,是个视锥  此矩阵是一个公式
	Eigen::Matrix4f pto = Eigen::Matrix4f::Identity();//将透视矩阵挤压成正交矩阵
	pto << zNear, 0, 0, 0,
		0, zNear, 0, 0,
		0, 0, zNear + zFar, - zFar * zNear,
		0, 0, 1.0, 0;

	float halfAngle = (eye_fov / 2.0 / 180.0) * MY_PI; //视角的一半
	float top = -1.0f * zNear * tan(halfAngle);//y轴正方向值 = 显示视口的一半高度
	float right= top * aspect_ratio;
	float bottom = -top;
	float left = -right;

	//构造缩放矩阵,使视口大小等同窗口大小
	Eigen::Matrix4f m_s = Eigen::Matrix4f::Identity();
	m_s << 2 / (right - left), 0, 0, 0,			//将中心视为原点,则窗口的三维方向值域均为[-1,1] 
			0, 2 / (top - bottom), 0, 0,				//缩放的倍数为 期望值/当前值
			0, 0, 2 / (zNear - zFar), 0,				//所以缩放的倍数为 (1+1)/某一维度的当前值
			0, 0, 0, 1;

	//构造平移矩阵,将视口左下角移动到原点
	Eigen::Matrix4f m_t = Eigen::Matrix4f::Identity();
	
	//左下角的点原本为 (x_left,y_down,zNear)
	//注意!此时已经经过了缩放,所以左下角的点的位置已经变化
	//左下角的点现在为 (-1,-1,zNear)
	//即其实可以不用管x和y轴,比较尺寸已经和窗口匹配了
	//左侧+右侧或者上侧+下侧,结果都是0,但这里为了便于理解或者防止参数变动之后会产生的一系列变化还是选用公式的写法
	m_t << 1, 0, 0, -(left+right)/2.0f,					
			0, 1, 0, -(top+bottom)/2.0f,					
			0, 0, 1, -(zNear+zFar)/2.0f,
			0, 0, 0, 1;
	
	projection = m_s * m_t * pto * projection;
	
	return projection;
}


结果显示为下图:
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值