1. 作业简介
该次作业考察的是课程《Lecture 04 Transformation Cont》的内容:
绕 x x x 轴旋转的旋转变换矩阵
正交投影矩阵
透视投影矩阵
1.1 作业要求
给定三维下的三个点 v 0 ( 2.0 , 0.0 , − 2 , 0 ) v_0(2.0, 0.0, -2,0) v 0 ( 2 . 0 , 0 . 0 , − 2 , 0 ) ,v 0 ( 0.0 , 2.0 , − 2 , 0 ) v_0(0.0, 2.0, -2,0) v 0 ( 0 . 0 , 2 . 0 , − 2 , 0 ) ,v 0 ( − 2.0 , 0.0 , − 2 , 0 ) v_0(-2.0, 0.0, -2,0) v 0 ( − 2 . 0 , 0 . 0 , − 2 , 0 ) ,你需要将这三个点的坐标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形。
1.2 相关函数
需要在文件 main.cpp
中修改下列函数:
1 get_model_matrix(float rotation_angle);
逐个元素地构建模型变换矩阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z z z 轴旋转的变换矩阵,而不用处理平移与缩放。
1 get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar);
使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵。
2. 作业代码分析
2.1 get_model_matrix()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Eigen::Matrix4f get_model_matrix (float rotation_angle) { Eigen::Matrix4f model = Eigen::Matrix4f::Identity(); Eigen::Matrix4f rotateZ; float theta = rotation_angle / 180.0 * MY_PI; rotateZ << cos (theta), -sin (theta), 0 , 0 , sin (theta), cos (theta), 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 ; model = rotateZ * model; return model; }
给定一个旋转的角度,实现绕 z z z 轴旋转的旋转矩阵:
R z = [ cos α − sin α 0 0 sin α cos α 0 0 0 0 1 0 0 0 0 1 ] R_z =
\begin{bmatrix}
\cos{\alpha} & - \sin{\alpha} & 0 & 0 \\
\sin{\alpha} & \cos{\alpha} & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
R z = ⎣ ⎢ ⎢ ⎡ cos α sin α 0 0 − sin α cos α 0 0 0 0 1 0 0 0 0 1 ⎦ ⎥ ⎥ ⎤
2.2 get_projection_matrix()
参 数
含 义
eye_fov
垂直可视角
aspect_ratio
宽高比
zNear
距离 Camera 较近的边界
zFar
距离 Camera 较远的边界
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Eigen::Matrix4f get_projection_matrix (float eye_fov, float aspect_ratio, float zNear, float zFar) { Eigen::Matrix4f projection = Eigen::Matrix4f::Identity(); Eigen::Matrix4f M_PerspToOrtho = Eigen::Matrix4f::Identity(); M_PerspToOrtho << zNear, 0 , 0 , 0 , 0 , zNear, 0 , 0 , 0 , 0 , zNear + zFar, - zFar * zNear, 0 , 0 , 1 , 0 ; float halfEyeAngelRadian = (eye_fov / 2.0 ) * (MY_PI / 180.0 ); float t = zNear * std ::tan (halfEyeAngelRadian); float r = t * aspect_ratio; float l = - r; float b = - t; Eigen::Matrix4f M_Ortho1 = Eigen::Matrix4f::Identity(); M_Ortho1 << 1 , 0 , 0 , (-1 )* (r + l) / 2 , 0 , 1 , 0 , - (t + b) / 2 , 0 , 0 , 1 , - (zNear + zFar) / 2 , 0 , 0 , 0 , 1 ; Eigen::Matrix4f M_Ortho2 = Eigen::Matrix4f::Identity(); M_Ortho2 << 2 / (r - l), 0 , 0 , 0 , 0 , 2 / (t - b), 0 , 0 , 0 , 0 , 2 / (zNear - zFar), 0 , 0 , 0 , 0 , 1 ; Eigen::Matrix4f M_Ortho = M_Ortho2 * M_Ortho1; projection = M_Ortho * M_PerspToOrtho; return projection; }
透视投影矩阵 的实现:
M P e r s p → O r t h o = [ n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ] M_{Persp \to Ortho} =
\begin{bmatrix}
n & 0 & 0 & 0 \\[1.5ex]
0 & n & 0 & 0 \\[1.5ex]
0 & 0 & n + f & -nf \\[1.5ex]
0 & 0 & 1 & 0
\end{bmatrix}
M P e r s p → O r t h o = ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ n 0 0 0 0 n 0 0 0 0 n + f 1 0 0 − n f 0 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
正交投影矩阵 构造的第一部分:先将中心点平移至原点
M O r t h o 1 = [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] M_{Ortho1} =
\begin{bmatrix}
1 & 0 & 0 & -\frac{r+l}{2} \\[1.5ex]
0 & 1 & 0 & -\frac{t+b}{2} \\[1.5ex]
0 & 0 & 1 & -\frac{n+f}{2} \\[1.5ex]
0 & 0 & 0 & 1
\end{bmatrix}
M O r t h o 1 = ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ 1 0 0 0 0 1 0 0 0 0 1 0 − 2 r + l − 2 t + b − 2 n + f 1 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
正交投影矩阵 构造的第二部分:将 length/width/height 缩放至 2
M O r t h o 2 = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] M_{Ortho2} =
\begin{bmatrix}
\frac{2}{r-l} & 0 & 0 & 0 \\[1.5ex]
0 & \frac{2}{t-b} & 0 & 0 \\[1.5ex]
0 & 0 & \frac{2}{n-f} & 0 \\[1.5ex]
0 & 0 & 0 & 1
\end{bmatrix}
M O r t h o 2 = ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ r − l 2 0 0 0 0 t − b 2 0 0 0 0 n − f 2 0 0 0 0 1 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
M P e r s p = M O r t h o 2 ⋅ M O r t h o 1 ⋅ M P e r s p → O r t h o M_{Persp} = M_{Ortho2} \cdot M_{Ortho1} \cdot M_{Persp \to Ortho}
M P e r s p = M O r t h o 2 ⋅ M O r t h o 1 ⋅ M P e r s p → O r t h o
NOTE :
3. 测试样例