WebGL 图形变换理论篇

齐次坐标

简介

说到图形的几何变换,就离不开“齐次坐标”这个神奇的东西,所谓“齐次坐标”,就是将一个原本n维的向量用一个n+1维的向量来表示。比如向量:(x1,x2,...,xn)(x_1, x_2, ..., x_n) 的齐次坐标可表示为: (hx1,hx2,...,hxn,h)(hx_1, hx_2, ..., hx_n, h)

其中h是一个实数。显然一个向量的齐次坐标的表示是不唯一的,齐次坐标中的h取不同的值都表示的是同一个点,例如齐次坐标[8, 4, 2], [4, 2, 1]表示的都是二维点(2, 1)

优势

  1. “齐次坐标”提供了用矩阵运算把二维、三维甚至更高维空间中的一个点集从一个坐标变换到另一个坐标系的有效方法;
  2. 其次还可以表示无穷远的点,n+1维的“齐次坐标”中如果h=0,实际上就表示了n维空间的一个无穷远的点。对于“齐次坐标”[a, b, h],保持ab不变,h -> 0的过程就表示了二维坐标系中的一个点沿着直线ax + by = 0逐渐走向无穷远处的过程。

解释一下:在笛卡尔坐标中无穷远处的点表示为(∞, ∞),而一个实数除以0是趋向于的,所以在“齐次坐标”中(1/h, 2/h, h )h -> 0时,齐次坐标表示的点也趋向于无穷。

二维图形的几何变换

图形的几何变换主要包括:平移、缩放、旋转三种最基本的变换形式;其中有比较特殊的如对称变换、错切变换、复合变换等。下面将会对以上的变换方式进行逐一的介绍。

在介绍之前要先说一下“二维齐次坐标变换”的矩阵形式:

[abcdefghi] \begin{bmatrix} a & b & | & c \\ d & e & | & f \\ - & - & | & - \\ g & h & | & i \end{bmatrix}

将矩阵分为4部分,第一部分[a, b, d, e]可以控制图形的缩放、旋转、对称和错切的变换;[c, f]是对图形进行平移变换;[g, h]是对图形作投影变换;[i]则是控制图形整体的缩放变换。

以下几何变换都会采用齐次坐标进行运算。

平移变换

平移变换是将坐标的[x, y]进行加法运算,平移由[c, f]进行控制:

[xy1]=[1,0,tx0,1,ty0,0,1][xy1]=[x+tx,y+ty,1]=T(tx,ty)[xy1] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} 1, 0, t_x \\ 0, 1, t_y \\ 0, 0, 1 \end{bmatrix}\begin{bmatrix} x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} x + t_x, \\ y + t_y, \\ 1 \end{bmatrix} = T(t_x, t_y)\begin{bmatrix} x \\ y \\ 1 \end{bmatrix}

如图:
WebGL 图形变换理论篇

缩放变换

缩放变换是对坐标进行一定比例的缩放,由[a, b, d, e]控制:

[xy1]=[sx,0,00,sy,00,0,1][xy1]=[sxxsyy1]=S(sx,sy)[xy1] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} =\begin{bmatrix} s_x, 0, 0 \\ 0, s_y, 0 \\ 0, 0, 1 \end{bmatrix}\begin{bmatrix} x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} s_x * x \\ s_y * y \\ 1 \end{bmatrix} = S(s_x, s_y)\begin{bmatrix} x \\ y \\ 1 \end{bmatrix}

如图:
WebGL 图形变换理论篇

旋转变换

在直角坐标平面中,将二维图形绕原点旋转θ角的变换形式如下:

[xy1]=[cosθ,sinθ,0sinθ,cosθ,00,0,1][xy1]=[xcosθysinθxsinθ+ycosθ1]=R(θ)[xy1] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} cosθ, -sinθ, 0 \\ sinθ, cosθ, 0 \\ 0, 0, 1 \end{bmatrix}\begin{bmatrix} x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} xcosθ - ysinθ \\ xsinθ + ycosθ \\ 1 \end{bmatrix} = R(θ)\begin{bmatrix} x \\ y \\ 1 \end{bmatrix}

如图:
WebGL 图形变换理论篇
首先描述一下上图中的情境,三角形绕原点逆时针由β角又旋转了θ

下面,我将会给大家证明一下绕原点旋转θ角的矩阵形式(规定:逆时针旋转θ取正值,顺时针旋转θ取负值),只证明一个点即可,其余两个点同理:

β+θr(rcos(β+θ),rsin(β+θ)){x=rcos(β+θ)=rcosβcosθrsinβsinθy=rsin(β+θ)=rsinβcosθ+rcosβsinθ(1)x=rcosβ,y=rsinβ(1){x=xcosθysinθy=xsinθ+ycosθ[cosθsinθsinθcosθ] 由题意可知:旋转之后的角度为β+θ,顶点距离原点的距离为r \\ 故顶点旋转后的坐标为(rcos(β+θ), rsin(β+θ)) \\ 即:\begin{cases} x' = rcos(β+θ) = rcosβcosθ - rsinβsinθ \\ y' = rsin(β+θ) = rsinβcosθ + rcosβsinθ \\ \end{cases} (1) \\ 又因为x = rcosβ, y = rsinβ \\ 故(1)等于: \\ \begin{cases} x' = xcosθ - ysinθ \\ y' = xsinθ + ycosθ \\ \end{cases} 即得旋转的矩阵形式为: \\ \begin{bmatrix} cosθ & -sinθ \\ sinθ & cosθ \end{bmatrix}

还是有点怀疑?那我们来验证一下,既然顶点都是围绕着原点进行旋转,那么也就表示顶点的运动轨迹是一个以原点(0, 0)为圆心,以r为半径的圆形,那么我们旋转前后,距离原点的距离应该是一样的:

(x,y)(0,0)x2+y2(x,y)(0,0)(xcosθysinθ)2+(xsinθ+ycosθ)2=x2cos2θ2xysinθcosθ+y2sin2θ+x2sin2θ+2xysinθcosθ+y2cosθ=x2cos2θ+y2sin2θ+x2sin2θ+y2cos2θ=(sin2θ+cos2θ)x2+(sin2θ+cos2θ)y2=x2+y2 旋转前,(x, y)距离(0, 0)的距离为:\sqrt{x^2 + y^2} 旋转后,(x', y')距离(0, 0)的距离为: \\ \sqrt{(xcos\theta - ysin\theta)^2 + (xsin\theta + ycos\theta)^2} \\ = \sqrt{x^2cos^2\theta - 2xysin\theta cos\theta + y^2sin^2\theta + x^2sin^2\theta + 2xysin\theta cos\theta + y^2cos^\theta} \\ = \sqrt{x^2cos^2\theta + y^2sin^2\theta + x^2sin^2\theta + y^2cos^2\theta} \\ = \sqrt{(sin^2\theta + cos^2\theta)x^2 + (sin^2\theta + cos^2\theta)y^2} \\ = \sqrt{x^2 + y^2}

可以看出,旋转前后距离原点的距离是没有改变的!

三维图形的几何变换

对于三维图形的几何变换来说,与二维图形基本一致,只不过在三维图形的世界中多了z轴,也正是z的存在才使得三维世界中的图形有了远近、透视等表现。三维图形的变换矩阵就会变成:

[a11a12a13a14a21a22a23a24a31a32a33a34a41a42a43a44] \begin{bmatrix} a_{11} & a_{12} & a_{13} & | & a_{14} \\ a_{21} & a_{22} & a_{23} & | & a_{24} \\ a_{31} & a_{32} & a_{33} & | & a_{34} \\ - & - & - & | & - \\ a_{41} & a_{42} & a_{43} & | & a_{44} \\ \end{bmatrix}

其中,左上角的部分负责产生缩放、旋转和错切等几何变换;右上角的[a_14, a_24, a_34]产生平移变换;左下角的[a_41, a_42, a_43]产生投影变换,而最后部分的[a_44]会产生整体的缩放变换。三维图形的平移变换与二维图形一致在此不再赘述,下面我们说一下缩放变换、绕坐标轴的旋转变换以及复合变换。

缩放变换

假设有参考点:F(xf,yf,zf)F(x_f, y_f, z_f),我们要对其进行缩放变换,那么步骤如下:

  1. 将参考点平移到坐标原点;
  2. 进行缩放变换;
  3. 将参考点移回原位置。

则变换矩阵为:

[100xf010yf001zf0001][sx0000sy0000sz00001][100xf010yf001zf0001]=[sx00(1sx)xf0sy0(1sy)yf00sz(1sz)zf0001] \begin{bmatrix} 1 & 0 & 0 & x_f \\ 0 & 1 & 0 & y_f \\ 0 & 0 & 1 & z_f \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}\begin{bmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & -x_f \\ 0 & 1 & 0 & -y_f \\ 0 & 0 & 1 & -z_f \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}=\begin{bmatrix} s_x & 0 & 0 & (1-s_x)x_f \\ 0 & s_y & 0 & (1-s_y)y_f \\ 0 & 0 & s_z & (1-s_z)z_f \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}

要注意哦,计算变换矩阵是从右向左乘

绕坐标轴的旋转变换

三维坐标空间的旋转相对要复杂一些,考虑右手坐标系下相对坐标原点绕坐标轴旋转θ角的变换。

  1. 绕x轴旋转:

[xyz1]=[10000cosθsinθ00sinθcosθ00001][xyz1]=Rx(θ)[xyz1] \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix}=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & cos\theta & -sin\theta & 0 \\ 0 & sin\theta & cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}=R_x(\theta)\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}

  1. 绕y轴旋转:

[xyz1]=[cosθ0sinθ00100sinθ0cosθ00001][xyz1]=Ry(θ)[xyz1] \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix}=\begin{bmatrix} cos\theta & 0 & sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ -sin\theta & 0 & cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}=R_y(\theta)\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}

  1. 绕z轴旋转:

[xyz1]=[cosθsinθ00sinθcosθ0000100001][xyz1]=Rz(θ)[xyz1] \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix}=\begin{bmatrix} cos\theta & -sin\theta & 0 & 0 \\ sin\theta & cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}=R_z(\theta)\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}

复合变换

设旋转轴AB由任意一点 A(xa,ya,za)A(x_a, y_a, z_a),及其方向数(a, b, c)定义,空间一点 P(xp,yp,zp)P(x_p, y_p, z_p) 绕AB轴旋转θ角到点 P(xp,yp,zp)P'(x_p', y_p', z_p')。则:

[xpypzp]=Rab(θ)[xpypzp] \begin{bmatrix} x_p' \\ y_p' \\ z_p' \end{bmatrix}=R_{ab}(\theta)\begin{bmatrix} x_p \\ y_p \\ z_p \end{bmatrix}

可以通过下列步骤来实现P点的旋转:

  1. 将A点移动到坐标原点;
  2. 使AB分别绕x轴、y轴旋转适当的角度与z轴重合;
  3. 将AB绕z轴旋转θ角;
  4. 作上述操作的你操作,使AB回到原来的位置。

Rab(θ)=T1(xa,ya,za)Rx1(α)Ry1(β)Rz(θ)Ry(β)Rx(α)T(xa,ya,za) R_{ab}(\theta)=T^{-1}(-x_a, -y_a, -z_a)R_x^{-1}(\alpha)R_y^{-1}(\beta)R_z(\theta)R_y(\beta)R_x(\alpha)T(-x_a, -y_a, -z_a)

三维图形变换的示意图画起来比较复杂,偷个懒就靠大家自行脑补一下????在Markdown中写矩阵的数学表达式写的有点烦躁~

结束语

有趣的图形变换就介绍到这里啦,后续会出更多好玩并且有用的文章分享给大家!

欢迎关注公众号:Refactor,感谢阅读!
WebGL 图形变换理论篇