题目:
本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。给定三维下三个
点 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()函数
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轴的朝向,我一开始并没有注意这个问题,所以一开始画出来的图形是一个倒三角形,但正确图形应该是一个正三角形。
请注意:
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;
}