日期:2021年5月29日标签:Computer Graphics

3D图形学中的矩阵变换(二) #

在之前的一篇文章中,我介绍了平移、旋转和缩放矩阵的证明,简单的讲解了如何证明绕任意轴旋转的旋转矩阵的证明思路。没有看过的朋友可以在这里看到。

这篇文章主要讲解下我理解的矩阵和矩阵的基变换,并简单介绍下LookAt矩阵。

一. 摄像机 #

这里涉及到三维图形学中的摄像机的概念。大家肯定都玩过游戏,现在游戏发展速度都特别快,很多游戏世界都是3D的,例如国外的荒野大镖客、巫师以及国内最近比较火的原神。游戏世界中所有的物体,例如桌子、树木、动物以及交通工具等等,它们在游戏世界中都有一个特定的位置,这个位置就是它们在游戏世界中的坐标,我们把它们在游戏世界中的位置称为世界坐标。假如同时有两个玩家A和B在游戏世界中漫游,那么这两个玩家的屏幕肯定显示的是不一样的,因为玩家在世界坐标系中的位置(世界坐标)不一样,并且视线的方向也不同,所以他们看到的屏幕肯定是不一样的。这里的A和B玩家,其实就是摄像机。假设我们以摄像机(玩家)为原点创建一个新的坐标系,可以称它为摄像机坐标系(观察空间坐标系)。那么同样的物体在世界坐标系中坐标为(300,200),那么它用摄像机坐标系如何表示呢?我用二维图形描述下这个问题。

image-20210526223206977

假设平面中有一点A,此时点A的坐标为(1, 1),表示A点在如图所示的坐标系中在原点右侧1个单位,上方1个单位。如果将这个坐标系旋转45度,变成另一个坐标系X2Y2,那么在新的坐标系X2Y2中如何表示A点呢?

image-20210526224510669

旋转45度,很容易计算出来A点在 X2Y2X_2Y_2 坐标系中的坐标为 (2,0)(\sqrt{2}, 0)。那么有没有一个矩阵 AA 可以使得$A \cdot P_1 = P_2$,也就是经过矩阵 AA 的变换,P1P_1 坐标变成了 P2P_2。这里 P1P_1 表示在原来的坐标系中的坐标,P2P_2 表示在新的坐标系中同一个点的坐标表示。其实这里的 AA 就是本篇文章要讨论的lookAt矩阵。

LookAt矩阵的作用就是,将世界坐标系中的物体坐标转换为用摄像机坐标系统描述,说白了就是在不同坐标系中描述同一个位置。

下面是learnopengl_cn官网给出的解释:

当我们讨论摄像机/观察空间(Camera/View Space)的时候,是在讨论以摄像机的视角作为场景原点时场景中所有的顶点坐标:观察矩阵把所有的世界坐标变换为相对于摄像机位置与方向的观察坐标。

二. 深入线性变换矩阵 #

首先我给大家讲述一个很重要的事实,在我上篇文章中说的几个变换矩阵,线性变换矩阵的每一列表示的都是变换后的坐标系的x、y、z轴的单位向量的表示,即 i,j,k\vec{i}, \vec{j}, \vec{k}。请牢牢记住这一重要特性,因为这一个特性真的很重要,它会直接影响你的线性代数的思维。你可能现在还没有认识到这一特征,没关系,请继续阅读。

image-20210529095906096

还是以之前的A点的例子为例,来说明这一思想。A点坐标是 (1,1)(1, 1), 向量 OA\vec{OA}也是 (1,1)(1, 1),用 i,j,k\vec{i}, \vec{j}, \vec{k}表示的话 OA=1i+1j\vec{OA} = 1 * \vec{i} + 1 * \vec{j}

image-20210529100455563

此时,我们将坐标系旋转45度,变成下图所示。这里我顺便小小的提一下,线性变换就是保证我画的网格线平行且等距分布,这也是为什么我会画一些网格在图中,上一篇文章讲解的几个变换矩阵都是线性变换。

image-20210529101044826

正是因为是线性变换,所以变换后的A点满足如下公式:OA=1i2+1j2\vec{OA} = 1 * \vec{i_2} + 1 * \vec{j_2}。因为旋转45度,所以我们计算出 i2\vec{i_2}j2\vec{j_2} 分别为(√2 / 2, √2 / 2)和(-√2 / 2, √2 / 2)。所以OA = (0, √2 )。

image-20210529102434851

请仔细阅读我上图中的计算步骤,请保证你能看懂整个计算过程。

上图中我写了一个变换矩 阵,这个变换矩阵其实就是我们旋转45度的旋转矩阵。细心的朋友已经发现了,矩阵的第一列就是变换后的i帽,第二列就是变换后的j帽。所以还记得我之前说的那个真理吗?

线性变换矩阵的每一列表示的都是变换后的坐标系的x、y、z轴的单位向量的表示

三.逆矩阵 #

还是用之前的例子,我们将变换前的坐标系称为 xyoxyo, 变换后的坐标系称为 x2y2o2x_2y_2o_2xyoxyox2y2o2x_2y_2o_2 的变换矩阵如下(后面我将其称为 MatAMatA),每一列表示的是 x2y2o2x_2y_2o_2 坐标系的x和y方向的单位向量在 xyoxyo 坐标系中的表示。所以将这个矩阵乘以一个坐标,其实得到的是一个在 xyoxyo 坐标系中表示的坐标。

image-20210529105350442

例如,例如点A(1, 1),计算MatA · A = B,得到的点B是经过线性变换后A的坐标,但是这个坐标还是用xyo坐标系表示的, 点A的坐标却是在 x2y2o2x_2y_2o_2 坐标系中的表示。所以这里MatA的作用就是将 x2y2o2x_2y_2o_2 坐标系的表示转化为 xyoxyo 坐标系表示。那么反过来呢,xyoxyo -> x2y2o2x_2y_2o_2 如何转换?

这里引入逆矩阵的思想,逆矩阵表示相反的线性变换, 由 MatAA=BMatA · A = B 得到 A=(MatA1)BA = (MatA^-1) · BMatA1MatA^{-1} 表示的是 MatAMatA 的逆矩阵。所以有 MatAA=BMatA · A = BA=(MatA1)BA = (MatA^-1) · B 这两个公式,就可以得到同一点在 xyoxyox2y2o2x_2y_2o_2 中的表示方法。

这不正是lookAt矩阵的作用吗?lookAt矩阵就是在不同坐标系下如何表示同一点。

四.lookAt矩阵 #

其实这部分类容已经不重要了,因为通过上面的学习,你已经知道如何去转换坐标系了。但是我还是简单的介绍下learnOpengl_cn官网的lookAt矩阵吧。

LookAt矩阵如下, (Rx,Ry,Rz)(R_x, R_y, R_z) 表示摄像机的 XX 轴方向向量,(Ux,Uy,Uz)(U_x, U_y, U_z) 表示摄像机坐标系的Y轴方向,(Dx,Dy,Dz)(D_x, D_y, D_z) 表示摄像机的视线方向及 ZZ 轴。 (Px,Py,Pz)(P_x, P_y, P_z) 表示摄像机位置的世界坐标。

image-20210526213813353

通过上面的阅读,现在看这个矩阵,你能否自己给出证明呢?

......

......

矩阵的第二部分,是一个平移矩阵,目的是平移到(px, py, pz),矩阵中px,py,pz都加上了负号,是因为这里移动的不是摄像机而是整个场景,将场景向相反方向移动等价于移动摄像机。矩阵的第一部分就是一个线性变换的逆矩阵。计算逆矩阵通常需要计算非逆矩阵,那么非逆矩阵是什么呢?我在第二节内容说到,线性变换矩阵的每一列表示的都是变换后的坐标系的x、y、z轴的单位向量的表示。所以由 (Rx, Ry, Rz), (Ux, Uy, Uz), (Dx, Dy, Dz), 我们很容易写出线性变换矩阵。

image-20210529111854626

这个线性变换矩阵我用 Mat1Mat1 表示,平移矩阵用 Mat2Mat2 表示,所以lookAt矩阵如下:

LookAt=Mat11Mat2LookAt = Mat1^{-1} \cdot Mat2

逆矩阵的计算并不重要,写代码时,一般可以直接用函数去求解逆矩阵,重要的是你要理解我在本篇文章介绍的思想。本篇文章可能不是很好理解,我已经把我理解的尽可能详细的去描述讲解出来了,你可以多读几遍,带入思考去阅读。

(完)

目录