知识补充:
在旋转里,旋转矩阵的逆矩阵就是这个矩阵的转置(这样的矩阵叫做正交矩阵)
3D(实际世界)到2D(我们视野)的变换的处理有三步:
模型变换(m),视图变换(v),投影变换(p)
-
模型变换(modeling tranformation):将一个物体自身进行变换(缩放、旋转、位移),上一节介绍了此变换方法。
特别的:三维空间中的旋转
记忆理解:绕着转的那个轴的值不会变,所以只考虑另外两个轴,这时候就变成了2D
注意绕y轴的旋转是特殊的
2.视角变换(view tranformation):根据眼睛(相机)来判断物体的相对位置。
定义相机的三要素:相机位置position(向量e),相机面向方向gaze direction(单位向量g),相机上下方向up direction(单位向量t)。
为了方便计算,我们应设定相机处于原点(0,0,0),并让t指向Y轴方向,g指向-Z方向。如此,我们应该先进行相机平移;后进行相机的旋转:将单位向量g转到-Z轴方向,将单位向量t转到Y轴方向,那么顺理成章的 gXt即指向X轴方向。
我们要做的:
把相机移到原点:
接下来就是旋转
我们想:
但是把一个向量转到一个单位向量很难
逆向想:把一个单位向量转到一个已知的向量很简单
那么
就是上图矩阵的转置矩阵
3.投影变换
(1)正交变换
变换过程:把立方体的中心通过平移移到原点,再通过缩放将其压缩成每个边范围是[-1,1]的正则立方体(注意并不是1*1*1)
(2)投影变换
相当于先压缩成上边正交变换这个待变换的立方体,再把其进行正交变换
先压缩远平面把frustum变成下图这个
那么,怎么压缩呢?
进行完persp-->ortho,再进行ortho的变换即可
最终推导出
[作业1]
//逐个元素地构建模型变换矩阵并返回该矩阵。
//在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵,
//而不用处理平移与缩放
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
float angle = rotation_angle * MY_PI / 180.0f; //角度制转弧度制
//绕z轴旋转的矩阵
Matrix4f M_r;
M_r<<
cos(angle), sin(angle), 0, 0,
-sin(angle), cos(angle), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
model = M_r * model; //旋转
return model;
}
//使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
float zNear, float zFar)
{
Matrix4f projection = Matrix4f::Identity(); //要返回的透视投影矩阵
Matrix4f orth = Matrix4f::Identity(); //正交矩阵
Matrix4f ProjectToOrth = Matrix4f::Identity(); //透视投影到正交投影
//求PToO
float angle = (eye_fov / 2) * MY_PI / 180.0f; //一半的eyeFov
float n = -1.0 * zNear;
float f = -1.0 * zFar; //这里默认是朝-z看
float t = f * tan(angle);
float b = -1.0 * t;
float r = aspect_ratio * t;
float l = -1.0 * r;
ProjectToOrth <<
n, 0, 0, 0,
0, n, 0, 0,
0, 0, n + f, -1.0 * n * f,
0, 0, 1,0;
//只需负责缩放
orth <<
2.0 / r - l, 0, 0, 0,
0, 2.0 / t - b, 0, 0,
0, 0, 2.0 / f - n, 0,
0, 0, 0, 1;
projection = orth*ProjectToOrth;
return projection;
}