games101 第一次作业 三角形的光栅化

第一次games101的课程作业

 

非常简单,涉及投影变换和罗德里格斯旋转公式

 

注意,我已经添加了提高内容,加入了罗德里格斯旋转公式:

 

核心代码修改如下:

底下这个代码块为提高部分,实现罗德里格斯旋转公式:

 

Eigen::Matrix4f get_rotation(Eigen::Vector4f axis,float rotation_angle)
{
    rotation_angle = rotation_angle/180*3.1415926;
    Eigen::Matrix4f rotation = Eigen::Matrix4f::Identity();
    Eigen::Matrix4f tmp;
    tmp<<0,-axis[2],axis[1],0,axis[2],0,-axis[0],0,-axis[1],axis[0],0,0,0,0,0,1;
    rotation = std::cos(rotation_angle)*rotation + (1-std::cos(rotation_angle))*axis*axis.transpose()+std::sin(rotation_angle)*tmp;
    return rotation;
}

下面是普通的旋转矩阵:

可以看到,是绕z轴的旋转

Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
    Eigen::Matrix4f Rotated;
    rotation_angle = rotation_angle/180*3.1415926;
    Rotated << std::cos(rotation_angle), -sin(rotation_angle), 0, 0, std::sin(rotation_angle), std::cos(rotation_angle), 0, 0, 0, 0, 1,
        0, 0, 0, 0, 1;

    model = model*Rotated;   

    // TODO: Implement this function
    // Create the model matrix for rotating the triangle around the Z axis.
    // Then return it.

    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 pi = 3.1415926;
    float t = std::tan(eye_fov/2/180.0f*pi)*zNear;
    float r = t*aspect_ratio;
    float l = -r;
    float b = -t;
    Eigen::Matrix4f Mtranslate;
    Mtranslate <<1,0,0,-(r+l)/2,0,1,0,-(t+b)/2,0,0,1,-(zNear+zFar)/2,0,0,0,1;
    Eigen::Matrix4f Mortho;
    Mortho << 2/(r-l),0,0,0,0,2/(t-b),0,0,0,0,2/(zNear-zFar),0,0,0,0,1;
    Mortho = Mortho*Mtranslate;
    Eigen::Matrix4f Mpers;
    Mpers<<zNear,0,0,0,0,zNear,0,0,0,0,zNear+zFar,-(zNear*zFar),0,0,1,0;
    projection=projection*Mortho*Mpers;
    return projection;
}

因为我已经做了提高部分,其实可以对比一下普通的部分,其实实现的效果是一样的

注意主函数,我修改了其中两行,使用我自己的get_rotation函数

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;
     Eigen::Vector4f a(0,0,1,0);
    if (command_line) {
        r.clear(rst::Buffers::Color | rst::Buffers::Depth);
       
        r.set_model(get_rotation(a,angle));
       // 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_rotation(a,angle));
       // 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;
}

最后实现效果如下

成功实现三角形的绘制

而且可以旋转

 

posted @ 2021-01-22 23:01  coolwx  阅读(548)  评论(0编辑  收藏  举报