GAMES101 作业1 闫令琪图形学

tech2026-04-25  1

本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。给定三维下三个 点 v0(2.0,0.0,−2.0),v1(0.0,2.0,−2.0),v2(−2.0,0.0,−2.0), 你需要将这三个点的坐 标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形 (在代码框架中,我们已 经提供了 draw_triangle 函数,所以你只需要去构建变换矩阵即可)。简而言之, 我们需要进行模型、视图、投影、视口等变换来将三角形显示在屏幕上。在提供 的代码框架中,我们留下了模型变换和投影变换的部分给你去完成。 如果你对上述概念有任何不清楚或疑问,请复习课堂笔记或询问助教。 以下是你需要在 main.cpp 中修改的函数(请不要修改任何的函数名和其他 已经填写好的函数,并保证提交的代码是已经完成且能运行的): • get_model_matrix(float rotation_angle): 逐个元素地构建模型变换矩 阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵, 而不用处理平移与缩放。 • get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar):使用给定的参数逐个元素地构建透视投影矩阵并返回 该矩阵。 • [Optional] main(): 自行补充你所需的其他操作。 2 当你在上述函数中正确地构建了模型与投影矩阵,光栅化器会创建一个窗口 显示出线框三角形。由于光栅化器是逐帧渲染与绘制的,所以你可以使用 A 和 D 键去将该三角形绕 z 轴旋转 (此处有一项提高作业,将三角形绕任意过原点的 轴旋转)。当你按下 Esc 键时,窗口会关闭且程序终止。

#include "Triangle.hpp" #include "rasterizer.hpp" #include <eigen3/Eigen/Eigen> #include <iostream> #include <opencv2/opencv.hpp> constexpr double MY_PI = 3.1415926; Eigen::Matrix4f get_view_matrix(Eigen::Vector3f eye_pos) { Eigen::Matrix4f view = Eigen::Matrix4f::Identity(); Eigen::Matrix4f translate; translate << 1, 0, 0, -eye_pos[0], 0, 1, 0, -eye_pos[1], 0, 0, 1, -eye_pos[2], 0, 0, 0, 1; view = translate * view; return view; } 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::Matrix4f rotation; float rotate = rotation_angle / 180.0 * MY_PI; rotation << cos(rotate),-1.0*sin(rotate), 0,0, sin(rotate), cos(rotate), 0,0, 0,0,1,0, 0,0,0,1; model = rotation * model; return model; } 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(); // TODO: Implement this function // Create the projection matrix for the given parameters. // Then return it. float halfeyefov = (eye_fov / 360.0)*MY_PI; Eigen::Matrix4f p20 = Eigen::Matrix4f::Identity(); p20 << zNear, 0, 0,0, 0, zNear,0,0, 0,0,zNear+zFar,-1.0 * (zNear*zFar), 0,0,1,0; float t = zNear * std::tan(halfeyefov); float r = t * aspect_ratio; float l = (-1) * r; float b = (-1) * t; Eigen::Matrix4f orthol1 = Eigen::Matrix4f::Identity(); orthol1 << (r-l)/2, 0, 0, 0, 0, (t-b)/2, 0, 0, 0, 0, 0, (zNear - zFar)/2, 0, 0, 0, 0; Eigen::Matrix4f orthol2 = Eigen::Matrix4f::Identity(); orthol2 << 1, 0, 0, (-1.0)*(r+l)/2, 0, 1, 0, (-1.0)*(t+b)/2, 0, 0, 1, (-1.0)*(zNear + zFar)/2, 0, 0, 0, 1; projection = orthol1 * orthol2 * p20 * projection; return projection; } int main(int argc, const char** argv) { float angle = 0; bool command_line = false; std::string filename = "output.png"; if (argc >= 3) { command_line = true; angle = std::stof(argv[2]); // -r by default if (argc == 4) { filename = std::string(argv[3]); } else return 0; } rst::rasterizer r(700, 700); Eigen::Vector3f eye_pos = {0, 0, 5}; std::vector<Eigen::Vector3f> pos{{2, 0, -2}, {0, 2, -2}, {-2, 0, -2}}; std::vector<Eigen::Vector3i> ind{{0, 1, 2}}; auto pos_id = r.load_positions(pos); auto ind_id = r.load_indices(ind); int key = 0; int frame_count = 0; if (command_line) { r.clear(rst::Buffers::Color | rst::Buffers::Depth); r.set_model(get_model_matrix(angle)); r.set_view(get_view_matrix(eye_pos)); r.set_projection(get_projection_matrix(45, 1, 0.1, 50)); r.draw(pos_id, ind_id, rst::Primitive::Triangle); cv::Mat image(700, 700, CV_32FC3, r.frame_buffer().data()); image.convertTo(image, CV_8UC3, 1.0f); cv::imwrite(filename, image); return 0; } while (key != 27) { r.clear(rst::Buffers::Color | rst::Buffers::Depth); r.set_model(get_model_matrix(angle)); r.set_view(get_view_matrix(eye_pos)); r.set_projection(get_projection_matrix(45, 1, 0.1, 50)); r.draw(pos_id, ind_id, rst::Primitive::Triangle); cv::Mat image(700, 700, CV_32FC3, r.frame_buffer().data()); image.convertTo(image, CV_8UC3, 1.0f); cv::imshow("image", image); key = cv::waitKey(10); std::cout << "frame count: " << frame_count++ << '\n'; if (key == 'a') { angle += 10; } else if (key == 'd') { angle -= 10; } } return 0; }
最新回复(0)