开篇
线性代数的机制可以被用来表达排布三维场景中的物体、使用相机观察物体、在屏幕上看到物体所需要的许多操作。几何变换(Geometric Transformation)例如旋转、平移、缩放、投影都可以通过与矩阵相乘来得到,变换矩阵(Transformation Matrices)就是这章的话题。
我们可以使用一个\(2 \times 2\)的矩阵来改变或变换一个二维向量
\[\begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} a_{11}x+a_{12}y \\ a_{21}x+a_{22}y \end{bmatrix}
\]
这种简单的取一个二维向量产生另外一个向量的矩阵乘法,就叫做线性变换(Linear Transformation),使用这种简单的公式可以达到许多不同类型的有用的变换。
缩放(Scaling)
最基础的变换就是沿坐标轴缩放(Scale),这种变换可以改变模而且有可能改变方向。
\[\mathrm{scale}(s_x,s_y)=\begin{bmatrix} s_x & 0 \\ 0 & s_y \end{bmatrix}
\]
\[\begin{bmatrix} s_x & 0 \\ 0 & s_y \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} s_xx \\ x_yy \end{bmatrix}
\]
下面是两个缩放的例子
\[\mathrm{scale}(0.5,0.5) = \begin{bmatrix} 0.5 & 0 \\ 0 & 0.5 \end{bmatrix}
\]
![img]()
\[\mathrm{scale}(0.5,1.5) = \begin{bmatrix} 0.5 & 0 \\ 0 & 1.5 \end{bmatrix}
\]
![img]()
剪切(Shearing)
剪切描述的是把东西推向某边的那种变换,水平剪切矩阵和竖直剪切矩阵长这样
\[\mathrm{shear-x}(s)=\begin{bmatrix} 1 & s \\ 0 & 1 \end{bmatrix},\mathrm{shear-y}(s)=\begin{bmatrix} 1 & 0 \\ s & 1 \end{bmatrix}
\]
下面是两个剪切的例子
\[\mathrm{shear-x}(1)=\begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix}
\]
![img]()
\[\mathrm{shear-y}(1)=\begin{bmatrix} 1 & 0 \\ 1 & 1 \end{bmatrix}
\]
![img]()
旋转(Rotation)
假设我们想以一个\(\phi\)角度逆时针旋转向量\(\mathbf{a}\)到向量\(\mathbf{b}\),我们首先用半径\(r\)和角度\(\alpha\)来表示向量\(\mathbf{a}\)
\[x_a=r\cos\alpha
\]
\[y_a=r\sin\alpha
\]
因为\(\mathbf{b}\)是从\(\mathbf{a}\)旋转得到的,因此可得
\[x_b=r\cos(\alpha+\phi)=r\cos\alpha\cos\phi-r\sin\alpha\sin\phi
\]
\[y_b=r\sin(\alpha+\phi)=r\sin\alpha\cos\phi+r\cos\alpha\sin\phi
\]
因为\(x_a=r\cos\alpha\)、\(y_a=r\sin\alpha\),这实际上等于
\[x_b=x_a\cos\phi-y_a\sin\phi
\]
\[y_b=y_a\cos\phi+x_a\sin\phi
\]
可以化成矩阵向量相乘形式
\[\begin{bmatrix} x_b \\ y_b \end{bmatrix} = \begin{bmatrix} \cos\phi & -\sin\phi \\ \sin\phi & \cos\phi \end{bmatrix} \begin{bmatrix} x_a \\ y_a \end{bmatrix}
\]
因此旋转矩阵为
\[\mathrm{rotate}(\phi) = \begin{bmatrix} \cos\phi & -\sin\phi \\ \sin\phi & \cos\phi \end{bmatrix}
\]
下面是两个旋转的例子
\[\begin{bmatrix} \cos\frac{\pi}{4} & -\sin\frac{\pi}{4} \\ \sin\frac{\pi}{4} & \cos\frac{\pi}{4} \end{bmatrix} = \begin{bmatrix} 0.707 & -0.707 \\ 0.707 & 0.707 \end{bmatrix}
\]
![img]()
\[\begin{bmatrix} \cos\frac{-\pi}{6} & -\sin\frac{-\pi}{6} \\ \sin\frac{-\pi}{6} & \cos\frac{-\pi}{6} \end{bmatrix} = \begin{bmatrix} 0.866 & 0.5 \\ -0.5 & 0.866 \end{bmatrix}
\]
![img]()
反射(Reflection)
我们可以让向量沿着坐标轴反射,沿\(y\)轴反射和沿\(x\)轴反射的矩阵为
\[\mathrm{reflect-y}=\begin{bmatrix} -1 & 0 \\ 0 & 1 \end{bmatrix},\mathrm{reflect-x}=\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}
\]
下面是两个反射的例子
![img]()
![img]()
要注意的是,叠加这两种反射等效于旋转\(\pi\)弧度。
对于图形程序来说施加多个变换是很常见的,例如首先施加缩放\(\mathbf{S}\)接着施加旋转\(\mathbf{R}\),可以通过两步做到
\[\mathbf{v}_2=\mathbf{S}\mathbf{v}_1,\mathbf{v}_3=\mathbf{R}\mathbf{v}_2
\]
另一个方法是
\[\mathbf{v}_3 =\mathbf{R}(\mathbf{Sv}_1)
\]
因为矩阵相乘服从结合律我们也可以这么写
\[\mathbf{v}_3 = (\mathbf{RS})\mathbf{v}_1
\]
这样我们可以得到一个新的矩阵\(\mathbf{M}=\mathbf{RS}\),这个新的矩阵描述的就是先缩放再旋转的变换。下图是个相关的例子
![img]()
之前提到过矩阵相乘不服从交换律,下图是个相关的例子
![img]()
有时候需要撤销变换,把变换分成更简单的片段。例如,让用户控制旋转因子和缩放因子来向其展示变换。但是在内部,变换可能仅仅使用一个矩阵来表达,而这个矩阵已经混合好了旋转和缩放。其实可以通过先把矩阵拆解成期望的片段,接着调整这些片段,最后再次组装这些变换得到。
对于对称矩阵来说有特征值分解,可以把对称矩阵\(\mathbf{A}\)分解成如下形式
\[\mathbf{A}=\mathbf{RSR}^\mathrm{T}
\]
式中的\(\mathbf{R}\)为正交矩阵,\(\mathbf{S}\)为对角矩阵。从几何角度来理解,可以把\(\mathbf{R}\)当作旋转,把\(\mathbf{S}\)当作缩放,实际上就是把单布变换\(\mathbf{A}\)变成了多步变换\(\mathbf{RSR}^\mathrm{T}\)。令特征向量为\(\mathbf{v}_1\)和\(\mathbf{v}_2\),特征值为\(\lambda_1\)和\(\lambda_2\),\(\mathbf{RSR}^\mathrm{T}\)代表的多步变换可以被解释为
![img]()
对于非对称矩阵来说有奇异值分解,可以把非对称矩阵\(\mathbf{A}\)分解成如下形式
\[\mathbf{A}=\mathbf{USV}^\mathrm{T}
\]
式中的\(\mathbf{U}\)和\(\mathbf{V}\)为正交矩阵,\(\mathbf{S}\)为对角矩阵。从几何的角度来理解,可以把\(\mathbf{U}\)和\(\mathbf{V}\)当作旋转,把\(\mathbf{S}\)当作缩放。令左奇异向量为\(\mathbf{u}_1\)和\(\mathbf{u}_2\),右奇异向量为\(\mathbf{v}_1\)和\(\mathbf{v_2}\),奇异值为\(\sigma_1\)和\(\sigma_2\),\(\mathbf{USV}^\mathrm{T}\)代表的多步变换可以被解释为
![img]()
还有一种是用于非0旋转的Paeth分解,如下所示
\[\begin{bmatrix} \cos\phi & -\sin\phi \\ \sin\phi & \cos\phi \end{bmatrix} = \begin{bmatrix} 1 & \frac{\cos\phi-1}{\sin\phi} \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 \\ \sin\phi & 1 \end{bmatrix} \begin{bmatrix} 1 & \frac{\cos\phi-1}{\sin\phi} \\ 0 & 1 \end{bmatrix}
\]
以45°旋转为例可以得到
\[\mathrm{rotate}(\frac{\pi}{4})=\begin{bmatrix} 1 & 1-\sqrt{2} \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 \\ \frac{\sqrt{2}}{2} & 1 \end{bmatrix} \begin{bmatrix} 1 & 1-\sqrt{2} \\ 0 & 1 \end{bmatrix}
\]
这种特别的变换对光栅旋转非常有用,因为剪切是对图像非常有效的光栅操作,它会引入一些锯齿但是不会留下孔洞。一个关键的观察是,如果取光栅位置\((i,j)\)接着施加水平剪切,我们可以得到
\[\begin{bmatrix} 1 & s \\ 0 & 1 \end{bmatrix} \begin{bmatrix} i \\ j \end{bmatrix} = \begin{bmatrix} i+sj \\ j \end{bmatrix}
\]
如果把\(sj\)舍入到最近的整数,这个量会让每一行往侧边移动一点,行与行之间移动的量会相差一定量,但是相同行的每个位置往侧边移动的量是一样的,因此能让旋转后的图像的内部无孔洞。对于竖直剪切也是一样的道理,因此我们可以简单地实现一个光栅旋转。
三维线性变换可以从二维线性变换推广得到,例如沿轴缩放为
\[\mathrm{scale}(s_x,s_y,s_z)=\begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & s_z \end{bmatrix}
\]
三维中的旋转分为绕z、x、y轴旋转,分别为
\[\mathrm{rotate-z}(\phi)=\begin{bmatrix} \cos\phi & -\sin\phi & 0 \\ \sin\phi & \cos\phi & 0 \\ 0 & 0 & 1 \end{bmatrix}
\]
\[\mathrm{rotate-x}(\phi)=\begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\phi & -\sin\phi \\ 0 & \sin\phi & \cos\phi \end{bmatrix}
\]
\[\mathrm{rotate-y}(\phi)=\begin{bmatrix} \cos\phi & 0 & \sin\phi \\ 0 & 1 & 0 \\ -\sin\phi & 0 & \cos\phi \end{bmatrix}
\]
在二维中的剪切可以沿着某个轴进行,而在三维中
\[\mathrm{shear-x}(d_x,d_z)=\begin{bmatrix} 1 & d_x & d_z \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}
\]
和二维变换一样,三维变换矩阵可以用奇异值分解,从而得到一个旋转矩阵、一个缩放矩阵、另一个旋转矩阵。当然了,对称三维矩阵也可以使用特征值分解,从而得到一个旋转矩阵、一个缩放矩阵、一个逆旋转矩阵。此外,一个三维旋转矩阵也可以分解成三维剪切矩阵的乘积。
任意三维旋转(Arbitrary 3D Rotations)
绕任意轴旋转其实很简单,可以利用上一章的对矩阵变换向量的不同理解得到。假设我们有一个点\((x,y,z)\)处于全局坐标系中,想让点\((x,y,z)\)绕\(\mathbf{w}\)轴旋转,我们首先得找到另外两个辅助轴\(\mathbf{u}\)和\(\mathbf{v}\),要求是\(\mathbf{u}\)、\(\mathbf{v}\)、\(\mathbf{w}\)能组成一个标准正交基。有了这个条件后,我们先把点\((x,y,z)\)投影到\(\{\mathbf{u},\mathbf{v},\mathbf{w}\}\)这个坐标系中,于是可以使用这个矩阵
\[\begin{bmatrix} x_u & y_u & z_u \\ x_v & y_v & z_v \\ x_w & y_w & z_w \end{bmatrix}
\]
接着我们绕\(\{\mathbf{u},\mathbf{v},\mathbf{w}\}\)这个坐标系中的z轴旋转,于是可以用这个矩阵
\[\mathrm{rotate-z}(\phi)=\begin{bmatrix} \cos\phi & -\sin\phi & 0 \\ \sin\phi & \cos\phi & 0 \\ 0 & 0 & 1 \end{bmatrix}
\]
最后我们使用\(\mathbf{u}\)、\(\mathbf{v}\)、\(\mathbf{w}\)这三个基向量,把在这个坐标系中绕z轴旋转后的坐标变换到全局坐标系中,从而得到点\((x,y,z)\)绕\(\mathbf{w}\)轴旋转后的点\((x^{new},y^{new},z^{new})\),因此可以使用这个矩阵
\[\begin{bmatrix} x_u & x_v & x_w \\ y_u & y_v & y_w \\ z_u & z_v & z_w \end{bmatrix}
\]
综上,绕轴多步变换为
\[\begin{bmatrix} x^{new} \\ y^{new} \\ z^{new} \end{bmatrix} = \begin{bmatrix} x_u & x_v & x_w \\ y_u & y_v & y_w \\ z_u & z_v & z_w \end{bmatrix} \begin{bmatrix} \cos\phi & -\sin\phi & 0 \\ \sin\phi & \cos\phi & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_u & y_u & z_u \\ x_v & y_v & z_v \\ x_w & y_w & z_w \end{bmatrix} \begin{bmatrix} x \\ y \\ z \end{bmatrix}
\]
绝大多数三维向量都是用来表示位置或方向的,例如光从哪来。不过有些向量会被用来表示表面法线(Surface Normals),当表面被变换时这些法线不能以同样方式被变换。假设表面会被矩阵\(\mathbf{M}\)变换,表面的切向向量\(\mathbf{t}\)被\(\mathbf{M}\)变换后会保持与表面相切。然而表面法线\(\mathbf{n}\)被\(\mathbf{M}\)变换后可能不会与表面垂直。因此我们得以\(\mathbf{M}\)为基础,得到用于变换法线的矩阵\(\mathbf{N}\)。因为表面的切向向量与表面法线总是垂直的,因此可以得到
\[\begin{align*}
\mathbf{n}^\mathrm{T}\mathbf{t}&=0 \\
\mathbf{n}^\mathrm{T}\mathbf{I}\mathbf{t}&=0 \\
\mathbf{n}^\mathrm{T}\mathbf{M}^{-1}\mathbf{M}\mathbf{t}&=0
\end{align*}
\]
这两个向量被分别变换后也会保持垂直,因此
\[\begin{align*}
(\mathbf{Nn})^\mathrm{T}\mathbf{Mt}&=0 \\
\mathbf{n}^\mathrm{T}\mathbf{N}^\mathrm{T}\mathbf{Mt}&=0
\end{align*}
\]
由\(\mathbf{n}^\mathrm{T}\mathbf{M}^{-1}\mathbf{M}\mathbf{t}=0\)和\(\mathbf{n}^\mathrm{T}\mathbf{N}^\mathrm{T}\mathbf{Mt}=0\)可以得到\(\mathbf{N}^\mathrm{T}=\mathbf{M}^{-1}\),所以
\[\mathbf{N}=(\mathbf{M}^{-1})^\mathrm{T}或\mathbf{N}=(\mathbf{M}^\mathrm{T})^{-1}
\]
之前已经探讨过了使用矩阵来进行缩放、旋转、剪切等变换,在二维中变换为
\[\begin{bmatrix} x^{\prime} \\ y^{\prime} \end{bmatrix} = \begin{bmatrix} m_{11} & m_{12} \\ m_{21} & m_{22} \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix}
\]
这种变换有个缺点,就是不能移动物体,只能进行缩放、旋转等变换。为了让物体平移(Translate),我们必须实现这样一种变换
\[\begin{align*}
x^{\prime} &= x + x_t \\
y^{\prime} &= y + y_t
\end{align*}
\]
结果很简单,我们为表示位置的点\((x,y)\)增加一个坐标到\((x,y,1)\)接着与下面这种\(3 \times 3\)的矩阵相乘
\[\begin{bmatrix} m_{11} & m_{12} & x_t \\ m_{21} & m_{22} & y_t \\ 0 & 0 & 1 \end{bmatrix}
\]
相乘的结果为
\[\begin{bmatrix} x^{\prime} \\ y^{\prime} \\ 1 \end{bmatrix} = \begin{bmatrix} m_{11} & m_{12} & x_t \\ m_{21} & m_{22} & y_t \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \end{bmatrix} \equiv \begin{bmatrix} m_{11}x+m_{12}y+x_t \\ m_{21}x+m_{22}y+y_t \\ 1 \end{bmatrix}
\]
这一个矩阵就实现了一次线性变换加上一次平移变换,这种类型的变换叫做仿射变换(Affine Transformation),为实现仿射变换而增加的那一个维度的坐标叫做齐次坐标(Homogeneous Coordinate)。
要注意的是,这种变换会带来一个问题,使表示方向的向量平移是明显不合理的,可以把齐次坐标置零解决这个问题
\[\begin{bmatrix} 1 & 0 & x_t \\ 0 & 1 & y_t \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 0 \end{bmatrix}
\]
在之后的章节,我们会实现透视视图,到那个时候会了解齐次坐标的其它用途。特别地来说,齐次坐标是在图形硬件中实现的渲染器的设计和操作的基石。在三维中的平移和二维中的差不多,增加一个第四坐标即可,因此平移变换为
\[\begin{bmatrix} 1 & 0 & 0 & x_t \\ 0 & 1 & 0 & y_t \\ 0 & 0 & 1 & z_t \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} = \begin{bmatrix} x+x_t \\ y+y_t \\ z+z_t \\ 1 \end{bmatrix}
\]
这里要再次注意把表示方向的向量的齐次坐标置零。
有时我们可能想进行逆变换,例如对于缩放\(\mathrm{scale}(s_x,s_y,s_z)\)的逆缩放就是\(\mathrm{scale}(1/s_x,1/s_y,1/s_z)\),旋转的逆就是反方向旋转,平移的逆就是反方向平移。如果我们有一些矩阵\(\mathbf{M}=\mathbf{M}_1\mathbf{M}_2\cdots\mathbf{M}_n\),它的逆变换就是\(\mathbf{M}^{-1}=\mathbf{M}^{-1}_n\cdots\mathbf{M}^{-1}_2\mathbf{M}^{-1}_1\)。
当然了,我们也可以用奇异值分解来求逆变换,对于上面的矩阵\(\mathbf{M}\)有
\[\mathbf{M}=\mathbf{R}_1\mathrm{scale}(\sigma_1,\sigma_2,\sigma_3)\mathbf{R}_2
\]
因此它的逆变换\(\mathbf{M}^{-1}\)为
\[\mathbf{M}^{-1}=\mathbf{R}^{\mathrm{T}}_2\mathrm{scale}(1/\sigma_1,1/\sigma_2,1/\sigma_3)\mathbf{R}^{\mathrm{T}}_1
\]
之前的所有讨论都是使用矩阵来变换一些点,不过这还隐藏着其它含义,其实我们也可以把它们看成是在改变坐标系统。例如坐在行进的车中观察,这个时候会发现车之外的物体都在相对你往后移动,从计算机和变换的角度来理解,就是每帧都有变换矩阵作用于物体来让其往后移动。从另一个方面来说,感受到相对移动实际上是以你的视角为参考的结果。这个时候就发现了变换矩阵和改变坐标系统实际上是息息相关的。
从几何上说,一个坐标系统或坐标帧是由原点和基构成的,标准正交基是最常用的一种。在一帧中,坐标系统的原点和基分别为\(\mathbf{p}\)和\(\{\mathbf{u},\mathbf{v},\mathbf{w}\}\),我们可以用在这个坐标系中的一点\((u,v,w)\)得到另外一点
\[\mathbf{p}+u\mathbf{u}+v\mathbf{v}+w\mathbf{w}
\]
在计算机中存储这些向量时,会发现这些向量实际上是在某个坐标系统中表达的,例如坐标系原点\(\mathbf{p}\)实际上是位于某个坐标系统中的。为了让这一切进行下去,我们需要指定规范坐标系统,通常叫“全局”或“世界”坐标系统,这种系统会被用来描述其它所有系统。
在二维中,规范坐标系统通常用点\(\mathbf{o}\)表示原点,用\(\mathbf{x}\)和\(\mathbf{y}\)来表示右手标准正交基向量。其它的坐标系统可能用\(\mathbf{e}\)来表示原点,用\(\mathbf{u}\)和\(\mathbf{v}\)来表示右手标准正交基向量。一般来说,用于描述规范坐标系统的数据是不需要被显式存储的,因为它们是其它所有坐标系统的参考。使用规范坐标系中的坐标\((x_p,y_p)\)可以得到它在世界空间中的坐标为
\[\mathbf{p}=(x_p,y_p)\equiv\mathbf{o}+x_p\mathbf{x}+y_p\mathbf{y}
\]
使用某个坐标系中的坐标\((u_p,v_p)\)可以得到它在规范坐标系中的坐标为
\[\mathbf{p}=(u_p,v_p)\equiv\mathbf{e}+u_p\mathbf{u}+v_p\mathbf{v}
\]
因此,某个坐标系中的坐标\((u_p,v_p)\)和它在规范坐标系中的坐标\((x_p,y_p)\)的关系为
\[\begin{bmatrix} x_p \\ y_p \\ 1 \end{bmatrix} = \begin{bmatrix} x_u & x_v & x_e \\ y_u & y_v & y_e \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} u_p \\ v_p \\ 1 \end{bmatrix}
\]
让它变简洁点可以化简成
\[\mathbf{p}_{xy}=\begin{bmatrix} \mathbf{u} & \mathbf{v} & \mathbf{e} \\ 0 & 0 & 1 \end{bmatrix} \mathbf{p}_{uv}
\]
我们称等式右侧的矩阵为帧到规范(Frame-To-Canonical)矩阵,它把在某个坐标系下的坐标转化为在规范坐标系下的坐标。从另一个方向变换,我们可以得到
\[\begin{bmatrix} u_p \\ v_p \\ 1 \end{bmatrix} = \begin{bmatrix} x_u & y_u & 0 \\ x_v & y_v & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & -x_e \\ 0 & 1 & -y_e \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_p \\ y_p \\1 \end{bmatrix}
\]
让它变简洁点可以化简成
\[\mathbf{p}_{uv}=\begin{bmatrix} \mathbf{u} & \mathbf{v} & \mathbf{e} \\ 0 & 0 & 1 \end{bmatrix}^{-1} \mathbf{p}_{xy}
\]
我们称等式右侧的矩阵为规范到帧(Canonical-To-Frame)矩阵,它把在规范坐标系下的坐标转化为在某个坐标系下的坐标。因此在三维中我们有
\[\begin{align*}
\begin{bmatrix} x_p \\ y_p \\ z_p \\ 1 \end{bmatrix}&=\begin{bmatrix} 1 & 0 & 0 & x_e \\ 0 & 1 & 0 & y_e \\ 0 & 0 & 1 & z_e \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_u & x_v & x_w & 0 \\ y_u & y_v & y_w & 0 \\ z_u & z_v & z_w & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} u_p \\ v_p \\ w_p \\1 \end{bmatrix} \\ \mathbf{p}_{xyz} &= \begin{bmatrix} \mathbf{u} & \mathbf{v} & \mathbf{w} & \mathbf{e} \\ 0 & 0 & 0 & 1 \end{bmatrix} \mathbf{p}_{uvw}
\end{align*}
\]
\[\begin{align*}
\begin{bmatrix} u_p \\ v_p \\ w_p \\ 1 \end{bmatrix} &= \begin{bmatrix} x_u & y_u & z_u & 0 \\ x_v & y_v & z_v & 0 \\ x_w & y_w & z_w & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & -x_e \\ 0 & 1 & 0 & -y_e \\ 0 & 0 & 1 & -z_e \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_p \\ y_p \\ z_p \\ 1 \end{bmatrix} \\ \mathbf{p}_{uvw} &= \begin{bmatrix} \mathbf{u} & \mathbf{v} & \mathbf{w} & \mathbf{e} \\ 0 & 0 & 0 & 1 \end{bmatrix}^{-1} \mathbf{p}_{xyz}
\end{align*}
\]