GAMES101 HW1
这里回顾GAMES101 HW1,这次的作业主题是旋转与投影 。
课程主页:
课程作业:
课程视频:
这次作业主要是实现get_model_matrix和get_projection_matrix函数。
get_model_matrix
这里需要实现的是一种特殊情况,绕着$z$轴旋转,其一般情形为课程中介绍的罗德里格斯公式(公式的具体推导见后续的课程笔记):
其中$n$为轴的平行单位向量,$\alpha$为旋转角度。
利用上述公式,实现起来是很简洁的:
Eigen::Matrix4f get_rotation(Vector3f axis, float angle) {
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
Eigen::Matrix3f rotate = Eigen::Matrix3f::Zero();
Eigen::Matrix3f tmp;
tmp << 0, -axis.z(), axis.y(),
axis.z(), 0, -axis.x(),
-axis.y(), axis.x(), 0;
float alpha = angle / 180 * MY_PI;
rotate += std::cos(alpha) * Eigen::Matrix3f::Identity() +
(1 - std::sin(alpha)) * axis * axis.transpose() + \
std::sin(alpha) * tmp;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3;j ++) {
model(i, j) = rotate(i, j);
}
}
return model;
}
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
// Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
Eigen::Vector3f z(0, 0, 1);
Eigen::Matrix4f model = get_rotation(z, rotation_angle);
return model;
}
get_projection_matrix
投影变换的目标是将立方体[l, r] x [b, t] x [f, n]映射到$[-1, 1]^3$,分为两步:
- Perspective Projection
- Orthographic Projection
Orthographic Projection比较简单,公式为:
Perspective Projection比较复杂,其计算公式为:
最后的结果为:
函数传入的参数为:
- eye_fov
- aspect_ratio
- zNear (n)
- zFar (f)
要和[l, r] x [b, t] x [f, n]对应上,需要使用下图:
因此(注意作业中假设$r+l =0, t+b=0$):
- $t= |n|\tan \frac{fovY}{2}$
- $b =-t$
- $r= t\times aspect$
- $l=-r$
注意,由于可视化的原因,实际中$t$的计算方式为:
整体代码如下:
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
// TODO: Copy-paste your implementation from the previous assignment.
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.
// persp
Eigen::Matrix4f persp2ortho = Eigen::Matrix4f::Zero();
// 保证为负数
float n = zNear;
float f = zFar;
float A = n + f;
float B = - n * f;
persp2ortho << n, 0, 0, 0,
0, n, 0, 0,
0, 0, A, B,
0, 0, 1, 0;
// orth
Eigen::Matrix4f scale = Eigen::Matrix4f::Zero();
Eigen::Matrix4f tran = Eigen::Matrix4f::Identity();
// 不加-图形为反向
float t = -std::tan(eye_fov / 180 * MY_PI / 2) * std::abs(n);
float r = aspect_ratio * t;
float l = -r;
float b = -t;
scale << 2 / (r - l), 0, 0, 0,
0, 2 / (t - b), 0, 0,
0, 0, 2 / (n - f), 0,
0, 0, 0, 1;
tran << 1, 0, 0, -(r + l) / 2,
0, 1, 0, -(t + b) / 2,
0, 0, 1, -(n + f) / 2,
0, 0, 0, 1;
// final result
projection = scale * tran * persp2ortho;
return projection;
}
编译并运行:
make -j4
./Rasterizer -r 20 image.png
./Rasterizer -r 0 origin.png
可视化结果:
origin.png:
image.png:
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere