Game101第一次作业思路
git路径
绕z轴旋转
由于绕z轴旋转相当于二维的绕原点旋转,直接套用二维的公式即可。关于二维旋转矩阵的推算过程可以参考第三节的 18分钟
这里跳过推算的过程,直接使用结果矩阵,参考上面get_view_matrix的方法,模拟写法。得出旋转矩阵的定义方法:
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
//实现思路,参考上面的函数,identity获取单位矩阵,不知道为什么要乘单位矩阵
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
//弧度制转换
float rr = (float)(rotation_angle / 180.0 * MY_PI);
Eigen::Matrix4f rotate;
// z轴旋转矩阵,由于是绕z轴转,仅x,y变化,可以直接使用二维旋转的公式+齐次坐标
//二维旋转矩阵推算 https://www.bilibili.com/video/BV1X7411F744?p=3&vd_source=657636f6c75d9280607e5f9ee048d9d4 18分钟
rotate << cos(rr), -sin(rr), 0, 0,
sin(rr), cos(rr), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
model = rotate * model;
return model;
}
转换标准[-1,1]的透视投影
按照闫老师的课程,透视投影转-1,1的标准立方体的做法是先转换成正交投影,再平移,再缩小长宽。
先做正交转换,转换推导可以参考:
https://blog.csdn.net/qq_38904659/article/details/107523815
这里涉及到第四节课跟第五节课两节课的内容
大致思路是利用等比条件算出x,y轴的矩阵关系,然后根据远近平面上的点投射到自身平面时等于本平面推出矩阵第三行。
zNear, 0, 0, 0,
0, zNear, 0, 0,
0, 0, zNear + zFar, -zNear * zFar,
0, 0, 1, 0
完成正交转换后,现在有视野角度,相机与近平面距离,宽高比,根据tan推算出 top,bottom的位置,再根据长宽比推出left,right
//根据三角形定理,求出left top bottom right
float fov= eye_fov / 2;//投影平面与视野呈垂直,平面到眼睛连线,到顶部,底部的夹角为角度/2
float fovr = (float)(fov * MY_PI / 180.0); //求弧度制
float t = zNear * tan(fovr);//视角到顶点距离 对边/直角边=tan 对边=tan*直角边
float b = -t;//同上 top为正方向 bottom负方向
float r = aspect_ratio * t;//可视平面宽高比获取左右方位长度 w/h=aspect w=aspect*h r=w/2
float l = -r;//同上 right正方向 left负方向
先做平移,要让原点处中心,x=-(r+l)/2,y=-(b+t)/2 z=-(f+n)/2
做缩放,映射到-1,1的范围
x=2/(r-l) y=2/(b-t) z=2/(n-f)
但是发现三角形倒过来了,具体原因闫老师课程有说是使用的坐标系不相同,那我们把x,y 再乘-1就可以倒过来了
最终是:
//作业要求时这里生成标准化矩阵
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();
//透视投影,先把透视转成正交投影,再变回透视投影显示,利用相似三角形推算出x,y的数值
Eigen::Matrix4f ortho;
//公式推导 第四节 https://www.bilibili.com/video/BV1X7411F744?p=4&vd_source=657636f6c75d9280607e5f9ee048d9d4 1小时01分左右
ortho << zNear, 0, 0, 0,
0, zNear, 0, 0,
0, 0, zNear + zFar, -zNear * zFar,
0, 0, 1, 0;
//根据三角形定理,求出left top bottom right
float fov= eye_fov / 2;//投影平面与视野呈垂直,平面到眼睛连线,到顶部,底部的夹角为角度/2
float fovr = (float)(fov * MY_PI / 180.0); //求弧度制
float t = zNear * tan(fovr);//视角到顶点距离 对边/直角边=tan 对边=tan*直角边
float b = -t;//同上 top为正方向 bottom负方向
float r = aspect_ratio * t;//可视平面宽高比获取左右方位长度 w/h=aspect w=aspect*h r=w/2
float l = -r;//同上 right正方向 left负方向
Eigen::Matrix4f trans, scale,upend;
//到原点
trans << 1, 0, 0, -(r + l) / 2,
0, 1, 0, -(t + b) / 2,
0, 0, 1, -(zNear + zFar) / 2,
0, 0, 0, 1;
//压缩到-1,1的矩阵
scale << 2 / (r - l), 0, 0, 0,
0, 2 / (t - b), 0, 0,
0, 0, 2 / (zNear - zFar), 0,
0, 0, 0, 1;
//内容上下颠倒 坐标系变换下
upend<<-1,0,0,0,
0,-1,0,0,
0,0,1,0,
0,0,0,1;
projection = upend*scale*trans*ortho*projection;
return projection;
// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.
}