# 作业要求
完善以下函数:
get_model_matrix(float rotation_angle): 逐个元素地构建模型变换矩阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵,而不用处理平移与缩放。 | |
get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar): 使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵。 | |
在 main.cpp 中构造一个函数,该函数的作用是得到绕任意过原点的轴的旋转变换矩阵。 | |
Eigen::Matrix4f get_rotation(Vector3f axis, float angle) |
# 作业实现
# 旋转矩阵
绕 z 轴旋转的变换矩阵,只需写出旋转矩阵即可:
Eigen::Matrix4f get_model_matrix(float rotation_angle) { | |
Eigen::Matrix4f model = Eigen::Matrix4f::Identity(); | |
model << cos(rotation_angle / 180 * MY_PI), -sin(rotation_angle / 180 * MY_PI), 0, 0, | |
sin(rotation_angle / 180 * MY_PI), cos(rotation_angle / 180 * MY_PI), 0, 0, | |
0, 0, 1, 0, | |
0, 0, 0, 1; | |
return model; | |
} |
# 透视投影矩阵
-
先计算各个参数
const auto t = zNear * tan(eye_fov / 2 / 180 * MY_PI);
const auto r = t * aspect_ratio;
const auto l = -r;
const auto b = -t;
const auto f = -zFar;
const auto n = -zNear;
-
再构造正交投影矩阵
ortho_trans << 1, 0, 0, -(r + l) / 2,
0, 1, 0, -(t + b) / 2,
0, 0, 1, -(n + f) / 2,
0, 0, 0, 1;
ortho_scale << 2 / (r - l), 0, 0, 0,
0, 2 / (t - b), 0, 0,
0, 0, 2 / (n - f), 0,
0, 0, 0, 1;
ortho = ortho_scale * ortho_trans;
-
将正交投影矩阵转换为透视投影矩阵
persp_to_ortho << n, 0, 0, 0,
0, n, 0, 0,
0, 0, f + f, -n * f,
0, 0, 1, 0;
projection = ortho * persp_to_ortho;
# 任意轴旋转矩阵
使用 Rodrigues' rotation formula:
其中 是轴向量, 是旋转角度, 是单位矩阵。
Eigen::Matrix4f get_rotation(Vector3f axis, float angle) { | |
Eigen::Matrix4f rotation = Eigen::Matrix4f::Identity(); | |
//Rodrigues’ Rotation Formula | |
Eigen::Matrix3f N; | |
N << 0, -axis.z(), axis.y(), | |
axis.z(), 0, -axis.x(), | |
-axis.y(), axis.x(), 0; | |
rotation.block<3, 3>(0, 0) = Eigen::Matrix3f::Identity() * cos(angle) + (1 - cos(angle)) * axis * axis.transpose() + sin(angle) * N; | |
return rotation; | |
} |