作业目标是把三角形投影到屏幕上,并绕z轴旋转(进阶:绕任意轴旋转)。
get_model_matrix
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
/**
* @brief 控制model旋转的矩阵
* @note
* @param rotation_angle: 绕z轴旋转角度
* @retval model矩阵
*/
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
float theta=rotation_angle/180*MY_PI;//弧度制转角度制
model<<
cos(theta),-sin(theta),0.0,0.0,
sin(theta),cos(theta),0.0,0.0,
0.0,0.0,1.0,0.0,
0.0,0.0,0.0,1.0;
return model;
}
/**
* @brief 绕旋转轴dir旋转rotation_angle度,dir过圆心
* @note 直接套罗戈里德斯公式
* @param dir: 过圆心的旋转轴
* @param rotation_angle: 旋转角度
* @retval
*
*/
Eigen::Matrix4f get_model_matrix(Eigen::Vector3f dir,float rotation_angle)
{
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
float theta=rotation_angle/180*MY_PI;
float nx=dir(0);
float ny=dir(1);
float nz=dir(2);
Eigen::Matrix3f N = Eigen::Matrix3f::Identity();
N<<
0.0,-nz,ny,
nz,0.0,-nx,
-ny,nx,0.0;
Eigen::Matrix3f matrix = Eigen::Matrix3f::Identity();
matrix = cos(theta) * Eigen::Matrix3f::Identity() + (1-cos(theta)) * dir * dir.transpose() + sin(theta) * N;
// 转为齐次座标
model <<
matrix(0,0), matrix(0,1), matrix(0,2), 0,
matrix(1,0), matrix(1,1), matrix(1,2), 0,
matrix(2,0), matrix(2,1), matrix(2,2), 0,
0,0,0,1;
return model;
}
get_projection_matrix
推导透视投影转为正方体过程中得用到齐次座标才能解出来(也就是必须按照闫佬讲的那个过程),直接解的话解不出来。
// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.
/**
* @brief 将透视投影转为[-1,1]xyz范围内的正方体(正交投影)
* @note
* @param eye_fov: 相机的fov
* @param aspect_ratio: 宽度和高度比
* @param zNear: 距离相机的Near平面距离
* @param zFar: 距离相机的Far平面距离
* @retval 透视投影投影矩阵转为正方体(正交投影)的矩阵
*/
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
float zNear, float zFar)
{
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
// 视锥变为长方体: near平面的座标不变,far平面的z座标不变,(x0,y0,z0)->(n/f*x0,n/f*y0,z0)
Eigen::Matrix4f matrix1 = Eigen::Matrix4f::Identity();
matrix1<<
zNear,0.0,0.0,0.0,
0.0,zNear,0.0,0.0,
0.0,0.0,zFar+zNear,-zNear*zFar,
0.0,0.0,1.0,0.0;
// 变为xyz[-1,1]范围内的正方体
// 先把长方体移动到原点
Eigen::Matrix4f matrix2= Eigen::Matrix4f::Identity();
matrix2<<
1.0,0.0,0.0,0.0,
0.0,1.0,0.0,0.0,
0.0,0.0,1.0,(zNear+zFar)/2,
0.0,0.0,0.0,1.0;
// 缩放
float theta=eye_fov/180*MY_PI;// fov的角度
float h=2*tan(theta/2)*zNear;
float w=h*aspect_ratio;
Eigen::Matrix4f matrix3= Eigen::Matrix4f::Identity();
matrix3<<
2/h,0.0,0.0,0.0,
0.0,2/w,0.0,0.0,
0.0,0.0,2/(zFar-zNear),0.0,
0.0,0.0,0.0,1.0;
projection=matrix3*matrix2*matrix1;
return projection;
}
倒三角形问题
一开始运行的时候,会得到一个倒三角(自己画一下会发现应该是正的):
倒三角形问题我认为是相机向上的定义没写清楚,应该在get_view_matrix中确定相机向上的向量
Eigen::Matrix4f get_view_matrix(Eigen::Vector3f eye_pos)
{
Eigen::Matrix4f view = Eigen::Matrix4f::Identity();
view(1,1)=-1.0;// 这里确定相机向上的那个向量 不然投影出来的三角形是反的
Eigen::Matrix4f translate;
translate << 1, 0, 0, -eye_pos[0], 0, 1, 0, -eye_pos[1], 0, 0, 1,
-eye_pos[2], 0, 0, 0, 1;
view = translate * view;
return view;
}
运行结果: