本文目录
引言
- 在学习完LearnOpenGL的入门章节后,对其转换矩阵的生成原理、渲染pipeline原理很好奇,所以暂停LearnOpenGL光照章节的学习,先学习GAMES101的对应章节并记录。
- 本文为该系列第一篇,记录GAMES101 Lecture03和04的关键知识点及作业。
1. 重要知识点及存在的疑惑
1.1 向量的点积和叉积的作用?
- 点积的作用
1. 求两个向量的夹角
2. 求一个向量在另一个向量上的投影,从而将该向量分解为两个相互垂直的向量(即可以通过正交基来表示任一向量)
3. 判两个向量同向/反向(角度的接近程度)
- 叉积的作用
1. 决定两个向量的左右,从而决定一个点是否在三个向量围成的三角形内。
1.2 齐次坐标中的点和向量增加的维度为什么分别是1/0?
-
-
此外,从向量和点之间的计算也可以看出齐次坐标这样设计的妙处。
- 点+点 = 点(需要除w,让齐次坐标的w位为1,此时的xy才是求和得到点的xy)
- 点+向量 = 点 (代表从一个点超向量的方向、步长走到一个新的点)------->这一点很重要,当时学LearnOpenGL时Lookat矩阵的第二个参数一直搞不懂就是因为这个没想明白!
- 向量+向量 = 向量
- 点-点 = 向量(指向被减点)
1.3 如何绕任意一个给定点(Cx,Cy)旋转?
- 先平移回原点,然后旋转,然后移回去
1.4 三维空间中,绕三个轴旋转时的旋转矩阵,为什么绕y轴的和其他两个相反?
- 这点一直不理解为什么,但目前就课程中所讲和网上博客所查的原因就是这个,暂且只能这样记住说服自己,如果有大佬有更好的解释还望告知!
1.5 如何拍一张照片?(如何生成view观察矩阵)
- 找一个位置放相机(世界坐标系原点)
- 把相机朝一个方向看去(相机的方向向量camera_front,最原始的就是-z方向)
- 调整一下俯仰角(up向量,最原始的就是(0,1,0))
这个例子非常生动的说明了LearnOpenGL中生成Lookat矩阵的函数为什么是相机位置、目标位置、up向量这三个参数(由1.2可知,目标位置就是相机位置+相机方向向量)。
1.6 如何求透视投影中的缩放矩阵(透视投影可以分解为先缩放再正交投影)以及经过从近平面到远平面上的任一点经过缩放矩阵后是被拉近还是被推远了?
进行推导前要知道两个前提!
①我们架设近平面上的点经过缩放矩阵后仍是自身(不知道为什么,但老师是这么讲的,公式也是根据这个条件列出第一个式子)
②远平面的中心点经过缩放矩阵后xy坐标不变
- 缩放矩阵求解过程
- (近平面,远平面 ]上的任意一点经过缩放矩阵会远离近平面
2. Lecture04/05对应的HW0实现
- HW0源码(这里有一个疑问,如何释放new的eigen对象内存?因此暂未实现析构函数)
#include<cmath> #include<eigen3/Eigen/Core> #include<eigen3/Eigen/Dense> #include<iostream> /************************************************************************************************************************************* * HW0 Describe: * + input: a point P = (2,1) * + function: Counter clockwise rotation angle 45, then translate (1,2),calculate the transformed coordinates (in homogeneous) * + output: a point P' = (x,y) * * Author: * + Kkaiw * Date: * + 2023.3.15 * * Environment: * + ubuntu20.04 + vscode + cmake **************************************************************************************************************************************/ class point{ Eigen::Vector3d coord; public: point(double x,double y,double z):coord(x,y,z){} point(const Eigen::Vector3d& point):coord(point){} point& rotate(const double& angle); point& rotate(const Eigen::Matrix3d& rotat); point& translate(const double& _x,const double& _y); point& translate(const Eigen::Matrix3d& translat); inline void showCoord(){ int n=coord.size(); for(int i=0;i<n;++i) std::cout<<coord[i]<<" "; std::cout<<std::endl; } }; point& point::rotate(const double& angle){ //接收一个角度转换成弧度,然后生成旋转矩阵,最后执行旋转 double radian = angle/180*M_PI; Eigen::Matrix3d rotate_matrix; rotate_matrix << cos(radian), -1.0*sin(radian), 0, sin(radian), cos(radian), 0, 0, 0, 1; this->coord = rotate_matrix * this->coord; return *this; } point& point::rotate(const Eigen::Matrix3d& rotat){ this->coord= rotat * this->coord; return *this; } point& point::translate(const double& _x,const double& _y){ Eigen::Matrix3d translate_matrix; translate_matrix << 1, 0, _x, 0, 1, _y, 0, 0, 1; this->coord = translate_matrix * this->coord; return *this; } point& point::translate(const Eigen::Matrix3d& translat){ this->coord = translat * this->coord; return *this; } int main(){ //select1: point p(2.0f,1.0f,1.0f); //select2: //Eigen::Vector3d poin(2.0f,1.0f,1.0f); //point p(poin); p.showCoord(); //select1: /* //定义旋转矩阵 Eigen::Matrix3d rotat; double radian = 45.0/180*M_PI;// 1.旋转矩阵中要用弧度 2.默认就是逆时针,所以不用负号 rotat << cos(radian), -1.0*sin(radian), 0, sin(radian), cos(radian), 0, 0, 0, 1; p = p.rotate(rotat); p.showCoord(); //定义平移矩阵 Eigen::Matrix3d translat; translat << 1, 0, 1, 0, 1, 2, 0, 0, 1; p = p.translate(translat); */ //select2: p.rotate(45); p.translate(1,2); p.showCoord(); return 0; }
- HW0实验结果