(注:此文以个人知识框架为基础拓开,为方便后期回顾,在保留原课程内容框架的基础上,个别概念的介绍可能过于简单,感兴趣读者可到 GAMES 平台深入学习)
目录
2D Transform(rotation, scale, shear)
2D Transform(rotation, scale, shear)
-
Scale(缩放变换):
-
Reflection Matrix(反射变换):
-
Shear Matrix(切变):
Rotation Matrix(旋转):
注:T*A = A' => (T(-1))*A' = A 对矩阵A作变换T,得到A';对应的还原为:对A'作 矩阵的逆。
Homogeneous coordinates(齐次坐标)
-
引入:解决图像平移问题
-
仿射变换:
-
仿射=线性 + 平移
-
将二维平面需要组合的平移操作,用一个3阶矩阵表示(问题:引入额外维度增加存储开销;已知仿射变换,尾阶默认(0,0,1),即 可忽略):
-
Composite transform(变换组合)
- 矩阵乘法:右乘,满足结合律,分配律,不满足交换律。
- 顺序:1.先线性;2.再平移;
3D transformations
正交矩阵
- R(T) = R(-1);矩阵的转置 等价于 矩阵的逆;
3D Rotations
- xyz轴对应的旋转矩阵:
注:关于Y轴不一样的解释:二维矩阵 {cos,-sin,sin,cos} {cos,sin,-sin,cos}互逆。(右手坐标系,右手螺旋定则(旋转角度不超过180°),cross 表示叉积);
1.默认逆时针为正方向,看向对应轴负方向;
2. x.cros(y) =z,旋转角x->y,90°;
y.cross(z) = x,旋转角y->z,90°;
x.cross(z) = y, 旋转角x->z,270°;>180°;所以正确的写法应该是 z.cross(x) = y;
z->x,alpha°<=>x->z,-alpha°,所以变换矩阵就成了 {cos(-a),-sin(-a),sin(-a),cos(-a)},也就是{cos(a),sin(a),-sin(a),cos(a)};
欧拉角
- yaw,roll, pitch(鸭肉-佩奇~~)
- Rodrigues’ Rotation Formula(罗德里格旋转公式):欧拉角到矩阵的转换
注:n:过远点的旋转轴;
Viewing transformation
- View / Camera transformation
M(view) = T(view) * R(view);
T(view) 为相机坐标,直接通过齐次坐标写出:
R(view) 为相机的视角变换,结果已知,可以通过先求逆变换,再对其做转置算出:
- Projection transformation
- Orthographic projection(正交投影)
- 成像空间为 长宽高均为1的 cube,坐标原点与 cube 中心重合;远近一致,先平移到原点,再做缩放:
注:l(left),r(right),t(top),b(bottom),n(near),f(far);
- Perspective projection(透视投影)
- 推到过程略,直接给出结论:
- n(z轴近平面),f(z轴远平面)
作业1:
题目简单介绍:
模拟一个基于CPU 的光栅化渲染器的简化版本,对于给定点的三角形,进行模型、视图、投影、视口等变换来将三角形显示在屏幕上(具体参考连接内pdf 说明文档)。
核心代码:
- 1.绕z轴旋转:
/// <summary>
/// 绕z轴旋转
/// </summary>
/// <param name="rotation_angle">旋转角度</param>
/// <returns></returns>
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
float angle = rotation_angle;
Eigen::Matrix4f rotation;
angle = angle * MY_PI / 180.f;
rotation << cos(angle), -sin(angle), 0, 0,
sin(angle), cos(angle), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
return rotation;
}
2.透视投影变换:
/// <summary>
/// 对三角形做透视投影变换,因右手坐标系,zFar<zNear
/// </summary>
/// <param name="eye_fov">垂直的可视角度</param>
/// <param name="aspect_ratio">显示宽高比</param>
/// <param name="zNear">z轴近平面坐标</param>
/// <param name="zFar">z轴远平面坐标</param>
/// <returns></returns>
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 angle = eye_fov * MY_PI / 180.f;
float top = -zNear * tan(angle / 2);//此处为负!!!!
float bottom = -top;
float right = top * aspect_ratio;
float left = -right;
Eigen::Matrix4f M_pers,M_origin,M_scaling;
// 1.perspective transform
M_pers << zNear, 0, 0, 0,
0, zNear, 0, 0,
0, 0, zNear + zFar, -zNear * zFar,
0, 0, 1, 0;
// orthographic projection
// 2.move the centre point to (0,0,0)
M_origin << 1, 0, 0, -(right + left) / 2,
0, 1, 0, -(top + bottom) / 2,
0, 0, 1, -(zFar + zNear) / 2,
0, 0, 0, 1;
// 3.scaling to unit space
M_scaling << 2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, 2 / (zNear - zFar), 0,
0, 0, 0, 1;
projection = M_scaling * M_origin * M_pers;
return projection;
}
3.绕过原点的任意轴旋转:
Eigen::Matrix4f get_rotation(Vector3f axis, float angle) {
Eigen::Matrix4f M_axis;
float nx = axis.x();
float ny = axis.y();
float nz = axis.z();
angle = angle * MY_PI / 180.f;
// 公式及推到参考:https://zhuanlan.zhihu.com/p/56587491
M_axis << nx * nx * (1 - cos(angle)) + cos(angle), nx* ny* (1 - cos(angle)) + nz * sin(angle), nx* nz* (1 - cos(angle)) - ny * sin(angle), 0,
nx* ny* (1 - cos(angle)) - nz * sin(angle), ny* ny* (1 - cos(angle)) + cos(angle), ny* nz* (1 - cos(angle)) + nx * sin(angle), 0,
nx* nz* (1 - cos(angle)) + ny * sin(angle), ny* nz* (1 - cos(angle)) - nx * sin(angle), nz* nz* (1 - cos(angle)) + cos(angle),0,
0, 0, 0, 1;
Eigen::Matrix4f M_axis0 = M_axis.inverse();//求逆,本课程为右手坐标系,公式为左手坐标系,直接套用公式旋转会反向。
return M_axis0;
}
效果图
(三角形坐标为:v0(2.0, 0.0,−2.0), v1(0.0, 2.0,−2.0), v2(−2.0, 0.0,−2.0),,观测点{0, 0, 5},观测方向:-z):
正常效果:
饶Z轴旋转10度:
绕轴(0,0,-1)旋转10度:
和图2刚好相反!