zoukankan      html  css  js  c++  java
  • GAMES101 作业1

    请用来检验答案是否正确

    思路

    根据Games101第四讲的内容来写即可,核心的部分还是M(p) = M(o) * M(p->o),具体的推动过程课程内讲的很详细,点赞~
    这里有一点需要注意的是,get_projection_matrix传入的参数是“距离值”,因此是正的,但计算过程中需要考虑方向,而在右手坐标系下我们推导过程默认相机看向方向是-Z,因此这里需要对传入值进行取负操作。

    Code

    #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.
        float a = rotation_angle * MY_PI / 180;
        model << cos(a), -sin(a), 0, 0,
            sin(a), cos(a), 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1;
        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 fov = eye_fov * MY_PI / 180;
        // 右手坐标系 看向方向z为负
        float n = -zNear;
        float f = -zFar;
        float t = tan(0.5 * fov) * abs(n);
        float r = aspect_ratio * t;
        float l = -r;
        float b = -t;
    
        // 正交投影-平移
        Eigen::Matrix4f orthT = Eigen::Matrix4f::Identity();
        orthT << 1, 0, 0, -(r + l) / 2,
            0, 1, 0, -(t + b) / 2,
            0, 0, 1, -(n + f) / 2,
            0, 0, 0, 1;
    
        // 正交投影-缩放
        Eigen::Matrix4f orthS = Eigen::Matrix4f::Identity();
        orthS << 2 / (r - l), 0, 0, 0,
            0, 2 / (t - b), 0, 0,
            0, 0, 2 / (n - f), 0,
            0, 0, 0, 1;
    
        // 透视模型 挤压到 正交模型
        Eigen::Matrix4f p2o = Eigen::Matrix4f::Identity();
        p2o << n, 0, 0, 0,
            0, n, 0, 0,
            0, 0, n + f, -n * f,
            0, 0, 1, 0;
    
        // Mo * Mp2o 最后得到Mp
        projection = orthS * orthT * p2o;
        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++ << '
    ';
    
            if (key == 'a')
            {
                angle += 10;
            }
            else if (key == 'd')
            {
                angle -= 10;
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    MybatisProperties注册IOC容器和初始化
    Springboot源码之application.yaml读取过程
    DataSource的注册容器和初始化
    修改ha_config配置文件
    读书笔记--Python基础教程 001
    Python实现购物车小程序
    Python3实现三级菜单
    实现用户登录并且输入错误三次后锁定该用户
    day1-python 的基础部分
    翻译:《实用的Python编程》06_02_Customizing_iteration
  • 原文地址:https://www.cnblogs.com/ruoh3kou/p/15484741.html
Copyright © 2011-2022 走看看