2683 字
13 分钟
计算机图形学—数学基础—变换

你应该具备的基础知识#

  • Vectors 向量及其基础运算
  • Dot Product 点乘
  • Cross Product 叉乘
  • Matrices 矩阵

变换是计算机图形学中最基础的部分了,就像加减乘除之于数学。二维和三维图形的平移、旋转、缩放和投影;把一个对象从一个位置、尺寸或方向转换到另一个等等。通过变换,我们可以创建出各种复杂的图形效果:动画、变形和透视等。变换还可以用于相机视图的调整,以及在三维场景中实现物体的移动、旋转和缩放等操作。

二维变换#

让我们先从简单的二维变换开始

缩放(以原点为中心)#

image

可以用矩阵表示为:

image-0

对于不同比例的缩放:

image-1

同样的可以推出翻转

image-2

对于这种切变

image-3

如果我们有一个点P(x, y),应用上面的切变变换后,它的y坐标始终不变,只有x在水平方向上发生变化;而且当y=0时,水平方向上的变化为0,y=1时,水平方向上的变化为a。我们可以取(0,1) -> (a,1)这一点的变换来推出矩阵:

{x=a=0+1ay=y=1\begin{cases} x' = a = 0 + 1*a \\ y' = y = 1 \end{cases}

你可以试试其他点,都符合这个规律。

其中矩阵的第一行表示x轴方向上的变换,第二行表示y轴方向上的变换。切变矩阵中的元素s表示在x轴方向上的切变比例。当s为正值时,表示向右上方切变;当s为负值时,表示向左上方切变。

接下来是重头戏:旋转(以原点为中心)#

image-4

我们还是取特殊点:(1,0)(0,1)的变化来推导 对于(1,0)点,它在旋转 θ 角后变成了(cosθ,sinθ)

{x=1cosθ+0unknowny=1sinθ+0unknown\begin{cases} x' = 1 * cosθ + 0 * unknown \\ y' = 1 * sinθ + 0 * unknown \end{cases}

写成矩阵就是:

[xy]=[cosθunknownsinθunknown][xy]\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} cosθ & unknown \\ sinθ & unknown \end{bmatrix} \cdot \begin{bmatrix} x \\ y \end{bmatrix}

而对于(0,1)点,它在旋转 θ 角后变成了(-sinθ,cosθ)

{x=0unknown+1(sinθ)y=0unknown+1cosθ\begin{cases} x' = 0 * unknown + 1 * (-sinθ) \\ y' = 0 * unknown + 1 * cosθ \end{cases}

写成矩阵就是:

[xy]=[unknownsinθunknowncosθ][xy]\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} unknown & -sinθ \\ unknown & cosθ \end{bmatrix} \cdot \begin{bmatrix} x \\ y \end{bmatrix}

把他们合并起来:

[xy]=[cosθsinθsinθcosθ][xy]\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} cosθ & -sinθ \\ sinθ & cosθ \end{bmatrix} \cdot \begin{bmatrix} x \\ y \end{bmatrix}

所以旋转矩阵就是:

image-5
Tips#

如果我们想要绕这个点旋转θ-\theta角,按照前面的方法得出的矩阵就是:

Rθ=[cosθsinθsinθcosθ]R_{-\theta} = \begin{bmatrix} cosθ & sinθ \\ -sinθ & cosθ \end{bmatrix}

可以看到Rθ=RθTR_{-\theta} = {R_\theta}^{T},同时我们知道一个变换的逆变换就是对应矩阵的逆,于是可以得出:

Rθ=RθT=Rθ1R_{-\theta} = {R_\theta}^{T} = {R_\theta}^{-1}

这个矩阵的逆等于它的转置,所以它是一个正交矩阵

有旋转就有平移#

image-6

看起来很容易不是吗? 但是如果一个物体既会旋转又要平移,该怎么表示?

image-7

平移变换无法用矩阵相乘的形式表示出来,所以我们不得不采用上面这种方式来表示它。

但是这太不优雅了!而且,我们也不希望平移成为一种特例,这样对计算机和人来说,表示和计算起来都十分麻烦。有没有一种统一的方式,能够让我们来表示所有的转换? 让我们转变思路,进行“升维打击”:

齐次坐标系#

齐次坐标系(Homogeneous Coordinates)是一种在计算机图形学和计算机视觉中常用的表示点、向量和变换的方法。通过引入一个额外的维度,我们能够让点和向量可以用更简洁的方式表示,并且能够方便地进行坐标变换。

对二维坐标系来说,一个点通常由其 x、y 表示。但是,在齐次坐标系中,我们增加一个第三维度:

  • 对于二维点,我们将其表示为
(x,y,1)T(x, y, 1)^T
  • 对于二维向量,我们将其表示为
(x,y,0)T(x, y, 0)^T

为什么要这样做? 想一想点和向量的运算:

{vector+vector=vector(0+0=0)point+vector=point(1+0=1)pointpoint=vector(11=0)\begin{cases} vector + vector = vector & (0+0=0)\\ point + vector = point & (1+0=1)\\ point - point = vector & (1-1=0) \end{cases}

在齐次坐标系下,

[xyw],就是点[x/wy/w1](w0)点 \begin{bmatrix} x \\ y \\ w \end{bmatrix} ,就是点 \begin{bmatrix} x / w \\ y / w \\ 1 \end{bmatrix}(w \neq 0)对于point+point这种情况:对于point+point这种情况:[x1y11]+[x2y21]=[x1+x2y1+y22]=[(x1+x2)/2(y1+y2)/21]=Point\begin{bmatrix} x_1 \\ y_1 \\ 1 \end{bmatrix} + \begin{bmatrix} x_2 \\ y_2 \\ 1 \end{bmatrix} = \begin{bmatrix} x_1 + x_2 \\ y_1 + y_2 \\ 2 \end{bmatrix} = \begin{bmatrix} (x_1 + x_2) / 2 \\ (y_1 + y_2) / 2 \\ 1 \end{bmatrix} = Point

说了这么多,这次我们回头再看之前的变换,就可以用一个统一的线性变换表示出来:

image-8

这样二维空间下的坐标变换就可以用一种统一的方式来表示了

image-9
Tips#
  • 矩阵没有交换律:同时需要平移和线性变换的时候,需要先线性变换再平移
  • 仿射变换=线性变换+平移

顺序很重要#

10

先旋转再平移和先平移再旋转显然是不同的,变换矩阵是从右向左逐个应用的(下图为先旋转再平移):

11

前面我们已经讲过了绕原点旋转,如果我们想绕任一点旋转应该怎么做?

  1. 将旋转点平移到原点
  2. 绕原点旋转
  3. 平移回去

12

三维变换#

表示#

与二维同理,只不过多了一个维度:

13

齐次坐标系也多了一维(像二维变换一样,先线性变换再平移):

14

旋转#

到了旋转这里,比二维要稍微多一些东西。绕三维空间的某一个轴旋转 α\alpha 角,写成旋转矩阵就像下图:

15

xxzz 轴旋转都很好理解,但是为什么绕 yy 轴旋转成了转置呢?

按照右手螺旋定则绕 x y z 轴进行旋转:

161817

X×Y=ZX \times Y = ZY×Z=XY \times Z = X , 然而 X×Z=YX \times Z = - Y ,所以在 XoZXoZ 坐标系下旋转是反的,你也可以看作绕y轴的旋转矩阵左上角的3x3矩阵是循环移位后得到的。

欧拉角#

我们前面讨论的主要是绕某个固定轴的旋转,那么如果我们想要实现绕任意角度和任意轴的旋转,该如何处理呢?在这种情况下,我们可以引入一种更为灵活的旋转描述方法:欧拉角。欧拉角通过一系列顺序的轴旋转,能够表示任意方向的旋转,为我们提供了一种简单且直观的方式来处理复杂的旋转变换。

19

在欧拉角的表示中,常见的一种定义方式是使用 Roll(滚转)Pitch(俯仰)Yaw(偏航) 三个角度来描述物体的旋转。这三个角度分别对应于围绕物体自身的三个主要轴的旋转。


视图变换#

在前面的部分中,我们讨论了二维和三维空间中的各种几何变换,如平移、旋转、缩放等。这些变换主要用于改变物体在空间中的位置和形状。然而仅仅描述物体的空间位置和形状是不够的。为了将三维场景正确地投影到二维屏幕上,我们还需要引入一种新的变换:视图变换

什么是视图变换#

如果现在我们想拍一张照片,我们至少要做三件事,这对应着视图变换的三个部分:

  • 找一个风景不错的地方,让模特摆好姿势(模型变换 Model transformation
  • 找一个好角度并放好相机(视图变化 View transformation
  • 按下快门(投影变换 Projection transformation

如何定义相机#

要做出视图变换之前,我们还得先知道相机的位姿。我们可以用三个量定义相机:

  • position(相机在哪)
  • look-at direction(朝哪个方向)
  • up direction(向上的方向:相机的歪斜程度)
定义相机

如果相机和物体做相同的运动,那么拍出来的图片肯定是完全一样的:

21

这样的话我们可以将相机放在一个固定位置上,方便后续的变换。

我们把相机原点移动到坐标原点处,令Y为向上方向,让相机视线朝向-Z,并随摄像机变换其他的对象。

22

将任意相机移到原点位置#

相机的变换矩阵可以写成 Mview=RviewTviewM_{view}=R_{view}\cdot T_{view}

我们先将相机平移到坐标原点:

23

将相机从一个随机的位姿旋转到坐标轴上(向上方向到Y,相机视线朝向-Z)显然是十分困难的;不过,我们可以逆向思维,先求出从原点到相机的旋转矩阵,再求逆就可以得到我们想要的结果:

24
计算机图形学—数学基础—变换
https://fuwari.vercel.app/posts/计算机图形学-数学基础-变换/
作者
Lrinaus
发布于
2024-07-08
许可协议
CC BY-NC-SA 4.0