图形学 旋转与投影矩阵—1
game101 第二次作业; webgl 实现
使用 THREEJS 作为基础框架,构建各类矩阵,自定义矩阵运算,最终完成
- 正确构建模型矩阵
- 正确构建透视投影矩阵
- 看到变换后的三角形
- 按 A 和 D 三角形能够进行旋转
- 按 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] \\
增加一个维度实现平移
\]
由于第二个思路可以转换为矩阵相乘,与旋转和缩放形式类似,因此最好选用思路二,统一运算公式 变换后点坐标 = 变换矩阵 * 变换前坐标
,选用思路二需要设定一些规则
- 点的表示 [x, y, 1]
- 向量的表示 [x, y, 0]
这样做的好处就是不用单独为平移变换计算变换的公式,全部采用通用公式,虽然增加了一个维度,但是计算起来更加方便,可以看出如下几样好处
- 分辨出了点和向量的差别
- 点 + 向量 = [2x, 2y, 1],依然是点,符合要求,减法也一样
- 向量 + 向量 = [2x, 2y, 0],依然是向量,符合要求,减法也一样
- 点 + 点 = [2x, 2y, 2],第三个参数默认是 1,因此它被等效于 [x, y, 1],这时还可以发现,求出的是两点连线的中点,符合要求
结论
表示基础变换时,我们可以用矩阵表示 缩放 和 旋转 ,不能表示平移,为了能让公式统一,多用了一个维度表示点的信息,虽然多花费了一些空间,但是得到了更多的好处:分辨了点和向量,统一了计算公式
由于想输出的太多,只写一篇文章应该会太长,因此大概分为三篇,第一篇讲在二维坐标下的矩阵变换,第二篇和第三篇讲在三维坐标下的变换,视图矩阵,投影矩阵的构造以及代码实现
希望读者在看完后能提出意见, 点个赞, 鼓励一下, 我们一起进步. 加油 !!