【GAMES101学习笔记】hw01 - 视图变换

1. 作业简介

该次作业考察的是课程《Lecture 04 Transformation Cont》的内容:

  • x x x 轴旋转的旋转变换矩阵
  • 正交投影矩阵
  • 透视投影矩阵

1.1 作业要求

给定三维下的三个点 v 0 ( 2.0 , 0.0 , − 2 , 0 ) v_0(2.0, 0.0, -2,0) v0(2.0,0.0,2,0) v 0 ( 0.0 , 2.0 , − 2 , 0 ) v_0(0.0, 2.0, -2,0) v0(0.0,2.0,2,0) v 0 ( − 2.0 , 0.0 , − 2 , 0 ) v_0(-2.0, 0.0, -2,0) v0(2.0,0.0,2,0) ,你需要将这三个点的坐标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形。

1.2 相关函数

需要在文件 main.cpp 中修改下列函数:

get_model_matrix(float rotation_angle);
  • 逐个元素地构建模型变换矩阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z z z 轴旋转的变换矩阵,而不用处理平移与缩放。
get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar);
  • 使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵。
[Optional] main();
  • 自行补充你所需的其他操作。

2. 作业代码分析

2.1 get_model_matrix()

// 实现三维中绕 z 轴旋转的变换矩阵
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();

    Eigen::Matrix4f rotateZ;
    float theta = rotation_angle / 180.0 * MY_PI;

    //绕 z 轴的旋转矩阵
    rotateZ << cos(theta), -sin(theta), 0, 0,
        sin(theta), cos(theta), 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1;
    model = rotateZ * model;
    return model;
}

给定一个旋转的角度,实现绕 z z z 轴旋转的旋转矩阵:

R z = [ cos ⁡ α − sin ⁡ α 0 0 sin ⁡ α cos ⁡ α 0 0 0 0 1 0 0 0 0 1 ] R_z = \begin{bmatrix} \cos{\alpha} & - \sin{\alpha} & 0 & 0 \\ \sin{\alpha} & \cos{\alpha} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} Rz=cosαsinα00sinαcosα0000100001

2.2 get_projection_matrix()

参 数含 义
eye_fov垂直可视角
aspect_ratio宽高比
zNear距离 Camera 较近的边界
zFar距离 Camera 较远的边界
// 使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵
// eye_fov : 垂直可视角
// aspect_ratio : 宽高比
// zNear : 距离 Camera 较近的边界
// zFar : 距离 Camera 较远的边界
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
                                      float zNear, float zFar)
{
    // 返回的是透视投影矩阵
    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    // 构造 透视投影 to 正交投影 的矩阵
    Eigen::Matrix4f M_PerspToOrtho = Eigen::Matrix4f::Identity();
    M_PerspToOrtho << zNear, 0, 0, 0,
        0, zNear, 0, 0,
        0, 0, zNear + zFar, - zFar * zNear,
        0, 0, 1, 0;

    // 垂直可视角的一半
    float halfEyeAngelRadian = (eye_fov / 2.0) * (MY_PI / 180.0);

    // top y轴的最高点
    float t = zNear * std::tan(halfEyeAngelRadian);
    // right x轴的最大值
    float r = t * aspect_ratio;
    //left x轴最小值
    float l = - r;
    //bottom y轴的最大值
    float b = - t;

    // 构造矩阵的第一部分:先将中心点平移至原点
    Eigen::Matrix4f M_Ortho1 = Eigen::Matrix4f::Identity();
    M_Ortho1 << 1, 0, 0, (-1)* (r + l) / 2,
        0, 1, 0, - (t + b) / 2,
        0, 0, 1, - (zNear + zFar) / 2,
        0, 0, 0, 1;

    // 构造矩阵的第二部分:再将 length/width/height 缩放至 2
    Eigen::Matrix4f M_Ortho2 = Eigen::Matrix4f::Identity();
    M_Ortho2 << 2 / (r - l), 0, 0, 0,
        0, 2 / (t - b), 0, 0,
        0, 0, 2 / (zNear - zFar), 0,
        0, 0, 0, 1;
    
    Eigen::Matrix4f M_Ortho = M_Ortho2 * M_Ortho1;
    projection = M_Ortho * M_PerspToOrtho;
    
    return projection;
}

透视投影矩阵 的实现:

  • 透视投影到正交投影的“挤压”矩阵的构造

M P e r s p → O r t h o = [ n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ] M_{Persp \to Ortho} = \begin{bmatrix} n & 0 & 0 & 0 \\[1.5ex] 0 & n & 0 & 0 \\[1.5ex] 0 & 0 & n + f & -nf \\[1.5ex] 0 & 0 & 1 & 0 \end{bmatrix} MPerspOrtho=n0000n0000n+f100nf0

  • 正交投影矩阵 构造的第一部分:先将中心点平移至原点

M O r t h o 1 = [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] M_{Ortho1} = \begin{bmatrix} 1 & 0 & 0 & -\frac{r+l}{2} \\[1.5ex] 0 & 1 & 0 & -\frac{t+b}{2} \\[1.5ex] 0 & 0 & 1 & -\frac{n+f}{2} \\[1.5ex] 0 & 0 & 0 & 1 \end{bmatrix} MOrtho1=1000010000102r+l2t+b2n+f1

  • 正交投影矩阵 构造的第二部分:将 length/width/height 缩放至 2

M O r t h o 2 = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] M_{Ortho2} = \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & 0 \\[1.5ex] 0 & \frac{2}{t-b} & 0 & 0 \\[1.5ex] 0 & 0 & \frac{2}{n-f} & 0 \\[1.5ex] 0 & 0 & 0 & 1 \end{bmatrix} MOrtho2=rl20000tb20000nf200001

  • 透视投影 的构造

M P e r s p = M O r t h o 2 ⋅ M O r t h o 1 ⋅ M P e r s p → O r t h o M_{Persp} = M_{Ortho2} \cdot M_{Ortho1} \cdot M_{Persp \to Ortho} MPersp=MOrtho2MOrtho1MPerspOrtho

NOTE

3. 测试样例

  • 初始渲染

01.png

  • a 键进行逆时针旋转

02.png

  • d 键进行顺时针旋转

03.png

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值