Games101 作业1 #旋转&投影
在作业1的代码框架中,需要我们进行操作的有这两个函数
get_model_matrix(float rotation_angle)
//逐个元素地构建模型变换矩
//阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵,
//而不用处理平移与缩放。
get_projection_matrix(float eye_fov, float aspect_ratio, floatzNear, float zFar)
//使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵。
在get_model_matrix()中,实现旋转操作
在三维实体中,旋转/缩放/位移都可以用齐次坐标来进行计算
在基础的作业1中,只需要实现对z轴的旋转,因此,只需要乘上矩阵Rz(α)即可
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
//初始化model矩阵,初始化之后,model矩阵是这样的形式:
//1 0 0 0
//0 1 0 0
//0 0 1 0
//0 0 0 1
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
Eigen::Matrix4f rota;
double angle=rotation_angle/180*MY_PI; //转化为弧度制
//实现在z轴上的旋转
rota<< cos(angle) , -sin(angle) , 0, 0 ,
sin(angle) , cos(angle) , 0, 0 ,
0 , 0 , 1 , 0 ,
0 , 0 , 0 , 1 ;
model = rota * model; //从右往左乘
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
return model;
}
实现了旋转之后,就是投影了
投影有两种方法,一种是正交投影,一种是透视投影
正交投影出来的结果是和实机等大小的,而透视投影的结果是近大远小
实现正交投影的方法:
把要投影的物体移动到世界坐标系的原点处(因为我们的 摄像机/屏幕 也在原点处),然后对它进行缩放,缩放到与设定的屏幕大小相等就可以了。(图示是把它缩放到了一个[-1,1]^3的空间中)
这里要用到透视投影
首先把图像的每一个点进行挤压,然后再进行正交投影即可
因为在我们把图形进行挤压之后,只需要再执行正交投影就可以达到透视投影的近大远小效果了。
挤压的方法:
用下图这个矩阵乘上每一个点,即可进行挤压
(具体的推导过程可以看看闫令琪老师的视频 https://www.bilibili.com/video/BV1X7411F744?t=4307&p=4
挤压之后,就进行正交投影,即 先位移到指定坐标,再进行缩放。(乘上Mortho矩阵)
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
float zNear, float zFar)
{
// Students will implement this function
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
Eigen::Matrix4f persp,trans,scale;
//进行挤压的矩阵
persp<< zNear , 0 , 0 , 0 ,
0 , zNear , 0 , 0 ,
0 , 0 , zNear+zFar , -zNear*zFar ,
0 , 0 , 1 , 0 ;
double angle,l,r,t,b;
angle = eye_fov/180.0*MY_PI;
t = -zNear*tan(angle/2); //y轴最大值
b = -t; //y轴最小值
r = t*aspect_ratio; //x轴最大值
l = -r; //x轴最小值
//最大最小值指的是从屏幕看这个图形的上下左右的最大值
//位移到原点
trans<< 1 , 0 , 0 , -(r+l)/2 ,
0 , 1 , 0 , -(t+b)/2 ,
0 , 0 , 1 , -(zNear+zFar)/2,
0 , 0 , 0 , 1 ;
//缩放为长度为2的正方体(在[-1,1]^3的空间内)
scale<< 2/(r-l) , 0 , 0 , 0 ,
0 , 2/(t-b) , 0 , 0 ,
0 , 0 , 2/(zNear-zFar) , 0 ,
0 , 0 , 0 , 1 ;
projection = scale * trans * persp * projection ;
// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.
return projection;
}
最终结果: