图形学 旋转与投影矩阵—1

game101 第二次作业; webgl 实现

目录

  • 图形学 旋转与投影矩阵—1
  • 基础变换
  • 缩放变换
  • 旋转变换
  • 平移变换
  • 结论

使用 THREEJS 作为基础框架,构建各类矩阵,自定义矩阵运算,最终完成

  1. 正确构建模型矩阵
  2. 正确构建透视投影矩阵
  3. 看到变换后的三角形
  4. 按 A 和 D 三角形能够进行旋转
  5. 按 Q 和 E 三角形能够绕任意过原点的向量进行旋转

最终效果

基础变换

以二维坐标系举例,变换分为三种,缩放变换:能够让图形宽高缩放指定倍数,旋转变换:让图形绕原点逆时针旋转任意角度,平移变换:让图像向某个方向移动指定的量。下文描述三种变换的矩阵形式。

缩放变换

\[\left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} S_x & 0 \\ 0 & S_y \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \end{matrix} \right] \\ 公式一: 旋转矩阵变换 \]

变换后的坐标简单写成 [x‘, y’] (实际上所有的坐标都是以列向量进行存储,这里特别说明),变换前的坐标为 [x, y]。变换时的数值运算如下

\[\left\{ \begin{array}{} x'=S_x \times x \\ y'=S_y \times y \end{array} \right. \\ 公式一补充 \\ S_x: 表示宽缩放比例 \\ S_y: 表示高缩放比例 \]

表示缩放就可以用 [Sx, Sy] ,对应矩阵为公式一中的旋转矩阵

旋转变换

旋转变换求解相对困难,此时可以采用代点求值,如下所示

有个大小为 1*1 的正方形绕原点旋转 θ 角度得到第二个正方形,图上标示了两个红点,这两个红点就是可以代入进行计算的点,将旋转前的 [x, y] 与旋转后的 [x', y'] 代入下述方程中,解出旋转变换矩阵

\[设置旋转矩阵的每个参数分别为\: a, b, c, d \\ 第一步: 列出方程\\ \left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \end{matrix} \right] \\ \\ 第二步:代入两个代表点的变换\\ \left[ \begin{matrix} 1 \\ 0 \end{matrix} \right] = \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] \times \left[ \begin{matrix} \cos(\theta) \\ \sin(\theta) \end{matrix} \right] \\ \\ \left[ \begin{matrix} 0 \\ 1 \end{matrix} \right] = \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] \times \left[ \begin{matrix} -\sin(\theta) \\ \cos(\theta) \end{matrix} \right] \\ \\ 第三步: 得到结果 \\ \left[ \begin{matrix} a & b \\ c & d \end{matrix} \right] = \left[ \begin{matrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{matrix} \right] \\ \\ \left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \end{matrix} \right] \]

由于采用代入法求解,将 [0, 1] 和 [1, 0] 点代入方程,最终求得了旋转矩阵中 a, b, c, d 的值。旋转矩阵求解的问题就得到了解决。

平移变换

由前两节可以看出来,将一个点设为 [x, y],将其与 2*2 的矩阵相乘,是无法得到 [x+a, y+b] 的代数式,只能得到 [a*x, b*y] 这种形式的坐标

针对 2*2 的矩阵无法求得 [x+a, y+b] 形式的坐标问题,有两种解决方法,思路如下

\[思路一: \: \left[ \begin{matrix} x' \\ y ' \end{matrix} \right] = \left[ \begin{matrix} x \\ y \end{matrix} \right] + \left[ \begin{matrix} t_x \\ t_y \end{matrix} \right] \\ t_x: 在x轴上移动的距离 \\ t_y: 在y轴上移动的距离 \\ \\ 思路二: \: \left[ \begin{matrix} x' \\ y ' \\ 1 \end{matrix} \right] = \left[ \begin{matrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] \\ 增加一个维度实现平移 \]

由于第二个思路可以转换为矩阵相乘,与旋转和缩放形式类似,因此最好选用思路二,统一运算公式 变换后点坐标 = 变换矩阵 * 变换前坐标,选用思路二需要设定一些规则

  1. 点的表示 [x, y, 1]
  2. 向量的表示 [x, y, 0]

这样做的好处就是不用单独为平移变换计算变换的公式,全部采用通用公式,虽然增加了一个维度,但是计算起来更加方便,可以看出如下几样好处

  1. 分辨出了点和向量的差别
  2. 点 + 向量 = [2x, 2y, 1],依然是点,符合要求,减法也一样
  3. 向量 + 向量 = [2x, 2y, 0],依然是向量,符合要求,减法也一样
  4. 点 + 点 = [2x, 2y, 2],第三个参数默认是 1,因此它被等效于 [x, y, 1],这时还可以发现,求出的是两点连线的中点,符合要求

结论

表示基础变换时,我们可以用矩阵表示 缩放 和 旋转 ,不能表示平移,为了能让公式统一,多用了一个维度表示点的信息,虽然多花费了一些空间,但是得到了更多的好处:分辨了点和向量,统一了计算公式

由于想输出的太多,只写一篇文章应该会太长,因此大概分为三篇,第一篇讲在二维坐标下的矩阵变换,第二篇和第三篇讲在三维坐标下的变换,视图矩阵,投影矩阵的构造以及代码实现

希望读者在看完后能提出意见, 点个赞, 鼓励一下, 我们一起进步. 加油 !!