GAMES101——作业1 旋转与投影(含提高:罗德里格斯旋转公式)

目录

任务

实现

get_model_matrix

get_projection_matrix

提高项:get_rotation

结果


任务

本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。这里仅仅专注于如何得到矩阵,具体的渲染流程会在作业2中详解。
        get_model_matrix(float rotation_angle): 逐个元素地构建模型变换矩阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵,而不用处理平移与缩放。
        get_projection_matrix(float eye_fov, float aspect_ratio, float  zNear, float zFar): 使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵。
        
        所有的和数学有关的推导,这里不再说明,基本直接套用结果,不清楚可以重新看一遍games101的课程对应的知识。之后的文章亦是如此。

实现

get_model_matrix
绕x,y,z轴的变换矩阵如下,算出两个三角函数值后直接代入即可
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();    //创建一个单位矩阵

    float angle = rotation_angle / 180.0f * MY_PI;     //将角度制的角度转化为弧度制的角度,因为c++默认的三角函数用的是弧度制
    float s = std::sin(angle);
    float c = std::cos(angle);
    model << c, -s, 0, 0, s, c, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0;   //根据旋转矩阵的公式,直接给模型矩阵赋值

    return model;
}
get_projection_matrix

zNear是近平面到摄像机的距离,已知视角,可以根据正切函数求出一半的高度,最后乘2就可以得到近平面的高度,根据宽高比,求出近平面的宽度。再根据推导出的矩阵,代入数据即可求得所需的结果。

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
                                      float zNear, float zFar)
{
    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    Eigen::Matrix4f persp_to_ortho;         //公式中的persp->ortho矩阵
    Eigen::Matrix4f ortho;                  //ortho矩阵
    float height = zNear*std::tan(eye_fov/2) * 2;   //视锥体挤成立方体,立方体的高
    float width = height * aspect_ratio;                                //立方体的宽

    persp_to_ortho << zNear, 0, 0, 0,               //根据公式求得persp->ortho矩阵
                      0,zNear,0,0,
                      0,0,zNear + zFar,-zNear*zFar,
                      0,0,1,0;

    ortho << 2.0/width , 0 ,0, 0,                   //根据公式求得ortho矩阵,这里直接将平移和缩放两步写在一起了
             0, 2.0/height,0,0,
             0,0,2.0/(zNear-zFar),-(zNear+zFar)/(zNear-zFar),
             0,0,0,1;

    projection = ortho * persp_to_ortho * projection;   

    return projection;
}
提高项:get_rotation

这里采用罗德里格斯旋转公式,代码如下

旋转函数

Eigen::Matrix4f get_rotation(Eigen::Vector3f n,float angle){
    float cos_a = std::cos(angle);
    float sin_a = std::sin(angle);
    Eigen::Matrix3f I = Eigen::Matrix3f::Identity();
    Eigen::Matrix3f t;
    t << 0 , -n.z() , n.y(),
        n.z() , 0 , -n.x(),
        -n.y() , n.x(), 0;
    
    Eigen::Matrix3f rotateMatrix = cos_a * I +(1-cos_a)*n*n.transpose() + sin_a*t;
    Eigen::Matrix4f finalMatrix = Eigen::Matrix4f::Identity();
    finalMatrix.block<3,3>(0,0) = rotateMatrix;     //这里以矩阵0,0位置开始,将3*3的位置写入rotateMatrix
    return finalMatrix;
}

修改后的模型矩阵函数,这里绕着指定的轴(0.5000,0.2000,0.8426)旋转

Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();    //创建一个单位矩阵

    float angle = rotation_angle / 180.0f * MY_PI;     //将角度制的角度转化为弧度制的角度,因为c++默认的三角函数用的是弧度制

    Eigen::Vector3f n = {0.5000,0.2000,0.8426};
    Eigen::Matrix4f model = get_rotation(n,angle);

    return model;
}

结果

初始的状态

绕z轴旋转

绕指定的轴n旋转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值