Model 模型变换

缩放变换

S(sx,sy)=[sx000sy0001]S(s_x, s_y)=\begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix}

S(sx,sy,sz)=[sx0000sy0000sz00001]S(s_x, s_y, s_z)=\begin{bmatrix} s_x & 0 & 0 & 0\\ 0 & s_y & 0 & 0\\ 0 & 0 & s_z & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

反射变换

alt text

Rx=[100010001]R_x=\begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & 1 \end{bmatrix}

Ry=[100010001]R_y=\begin{bmatrix} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}

错切变换

H(hx,hy)=[1hx0hy10001]H(h_x, h_y)=\begin{bmatrix} 1 & h_x & 0 \\ h_y & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}

alt text

旋转变换

二维空间中绕原点的旋转矩阵公式

R(α)=[cos(α)sin(α)0sin(α)cos(α)0001]R(\alpha)=\begin{bmatrix} cos(\alpha) & -sin(\alpha) & 0 \\ sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1 \end{bmatrix}

三维空间中绕 x 轴的旋转矩阵公式

Rx(α)=[10000cos(α)sin(α)00sin(α)cos(α)00001]R_x(\alpha)=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & cos(\alpha) & -sin(\alpha) & 0 \\ 0 & sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

三维空间中绕 y 轴的旋转矩阵公式

Ry(α)=[cos(α)0sin(α)00100sin(α)0cos(α)00001]R_y(\alpha)=\begin{bmatrix} cos(\alpha) & 0 & sin(\alpha) & 0 \\ 0 & 1 & 0 & 0 \\ -sin(\alpha) & 0 & cos(\alpha) & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

三维空间中绕 z 轴的旋转矩阵公式

Rz(α)=[cos(α)sin(α)00sin(α)cos(α)0000100001]R_z(\alpha)=\begin{bmatrix} cos(\alpha) & -sin(\alpha) & 0 & 0 \\ sin(\alpha) & cos(\alpha) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

alt text

平移变换

T(tx,ty)=[10tx01ty001]T(t_x, t_y)=\begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix}

二维空间中绕任意点的旋转矩阵公式

R(α,p)=T(p)R(α)T(p)R(\alpha, \vec p)=T(\vec p) R(\alpha) T(-\vec p)

  • T(p)T(\vec p)为将点p\vec p平移回去的平移矩阵
  • R(α)R(\alpha)为绕原点的旋转矩阵
  • T(p)T(-\vec p)为将点p\vec p平移到原点的平移矩阵

公式展开如下:

R(α,p)=[10px01py001][cos(α)sin(α)0sin(α)cos(α)0001][10px01py001]=[cos(α)sin(α)px(1cos(α))+pysin(α)sin(α)cos(α)py(1cos(α))pxsin(α)001]R(\alpha, \vec p) = \begin{bmatrix} 1 & 0 & p_x \\ 0 & 1 & p_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} cos(\alpha) & -sin(\alpha) & 0 \\ sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & -p_x \\ 0 & 1 & -p_y \\ 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} cos(\alpha) & -sin(\alpha) & p_x(1-cos(\alpha))+p_y sin(\alpha) \\ sin(\alpha) & cos(\alpha) & p_y(1-cos(\alpha))-p_x sin(\alpha) \\ 0 & 0 & 1 \end{bmatrix}

例如一个点(x,y)(x,y)绕点(px,py)(p_x,p_y)逆时针旋转α\alpha角度后的位置为

[xy1]=[cos(α)sin(α)px(1cos(α))+pysin(α)sin(α)cos(α)py(1cos(α))pxsin(α)001][xy1]=[(xpx)cos(α)(ypy)sin(α)+px(xpx)sin(α)+(ypy)cos(α)+py1]\begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} cos(\alpha) & -sin(\alpha) & p_x(1-cos(\alpha))+p_y sin(\alpha) \\ sin(\alpha) & cos(\alpha) & p_y(1-cos(\alpha))-p_x sin(\alpha) \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} (x-p_x) cos(\alpha) - (y-p_y) sin(\alpha) + p_x \\ (x-p_x) sin(\alpha) + (y-p_y) cos(\alpha) + p_y \\ 1 \end{bmatrix}

三维空间中绕任意向量的旋转矩阵公式

罗德里格斯旋转公式(Rodrigues’ rotation formula)

矩阵形式

R(n,α)=cos(α)I+(1cos(α))nnT+sin(α)[0nznynz0nxnynx0]R(\mathbf n, \alpha)=cos(\alpha) I + (1-cos(\alpha)) \mathbf n \cdot \mathbf n ^ T + sin(\alpha) \begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x\\ -n_y & n_x & 0 \end{bmatrix}

其中:

  • n\mathbf n为旋转轴的单位向量
  • α\alpha为旋转角度
  • II为单位矩阵
  • nnT\mathbf n \cdot \mathbf n ^ T为向量n\mathbf n的外积矩阵
  • 反对称矩阵[n]×=[0nznynz0nxnynx0][\mathbf n]_{\times}=\begin{bmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x\\ -n_y & n_x & 0 \end{bmatrix}为向量n\mathbf n的叉乘矩阵

向量形式

v=R(n,α)v=vcos(α)+(1cos(α))(nnT)v+sin(α)[n]×v=vcos(α)+(1cos(α))(nv)n+sin(α)(n×v)\mathbf{v'}=R(\mathbf n, \alpha) \mathbf v \\= \mathbf v cos(\alpha) + (1-cos(\alpha)) (\mathbf n \mathbf n^T) \mathbf v + sin(\alpha) [\mathbf n]_{\times} \mathbf v \\= \mathbf v cos(\alpha) + (1-cos(\alpha)) (\mathbf n \cdot \mathbf v) \mathbf n + sin(\alpha) (\mathbf n \times \mathbf v)

其中:

  • v\mathbf v为待旋转的向量
  • v\mathbf v'为旋转后的向量
  • n\mathbf n为旋转轴的单位向量
  • α\alpha为旋转角度
  • [n]×[\mathbf n]_{\times}为向量n\mathbf n的叉乘矩阵,有[n]×v=n×v[\mathbf n]_{\times} \mathbf v = \mathbf n \times \mathbf v
  • (nnT)v=n(nTv)=(nv)n(\mathbf n \mathbf n^T) \mathbf v = \mathbf n (\mathbf {n^T} \cdot \mathbf v) = (\mathbf n \cdot \mathbf v) \mathbf n

推导过程

设旋转轴为单位向量n\mathbf n,待旋转的向量为v\mathbf v,旋转后的向量为v\mathbf v'
v\mathbf v分解为平行于n\mathbf n的分量v\mathbf{v_{\parallel}}和垂直于n\mathbf n的分量v\mathbf{v_{\perp}}

v=v+v\mathbf v = \mathbf{v_{\parallel}} + \mathbf{v_{\perp}}

其中

v=(nv)n\mathbf{v_{\parallel}} = (\mathbf n \cdot \mathbf v) \mathbf n

v=vv=v(nv)n\mathbf{v_{\perp}} = \mathbf v - \mathbf{v_{\parallel}} = \mathbf v - (\mathbf n \cdot \mathbf v) \mathbf n

旋转后,v\mathbf{v_{\parallel}}不变,v\mathbf{v_{\perp}}n\mathbf n旋转α\alpha角度
v\mathbf{v_{\perp}}在旋转前的垂直分量为v1\mathbf{v_{\perp 1}},旋转后的垂直分量为v2\mathbf{v_{\perp 2}},则有

v2=vcos(α)+(n×v)sin(α)\mathbf{v_{\perp 2}} = \mathbf{v_{\perp}} cos(\alpha) + (\mathbf n \times \mathbf{v_{\perp}}) sin(\alpha)

其中n×v\mathbf n \times \mathbf{v_{\perp}}v\mathbf{v_{\perp}}n\mathbf n旋转 90 度后的向量

v=v+v2=(nv)n+(v(nv)n)cos(α)+(n×(v(nn)n))sin(α)=(nv)n+vcos(α)(nv)ncos(α)+(n×v)sin(α)=vcos(α)+(1cos(α))(nv)n+sin(α)(n×v)\mathbf v' = \mathbf{v_{\parallel}} + \mathbf{v_{\perp 2}} \\ = (\mathbf n \cdot \mathbf v) \mathbf n + (\mathbf v - (\mathbf n \cdot \mathbf v) \mathbf n) cos(\alpha) + (\mathbf n \times (\mathbf v - (\mathbf n \cdot \mathbf n) \mathbf n)) sin(\alpha) \\ = (\mathbf n \cdot \mathbf v) \mathbf n + \mathbf v cos(\alpha) - (\mathbf n \cdot \mathbf v) \mathbf n cos(\alpha) + (\mathbf n \times \mathbf v) sin(\alpha) \\ = \mathbf v cos(\alpha) + (1-cos(\alpha)) (\mathbf n \cdot \mathbf v) \mathbf n + sin(\alpha) (\mathbf n \times \mathbf v)

View 相机变换

相机变换矩阵的推导

一个相机由以下几部分所构成

  • 相机位置 e\vec e
  • 相机视线方向g\vec g
  • 相机的正上方向t\vec t
    在相机的参考系中,定义相机视线方向g\vec g为相机坐标系的 z 轴方向
    定义相机的正上方向t\vec t为相机坐标系的 y 轴方向
    定义g×t\vec g \times \vec t为相机坐标系的 x 轴方向
    通常相机的视线方向为世界坐标系的z-z轴方向

首先将相机平移到原点,可得到矩阵

Tview=[100xe010ye001ze0001]T_{view}=\begin{bmatrix} 1 & 0 & 0 & -x_e\\ 0 & 1 & 0 & -y_e\\ 0 & 0 & 1 & -z_e\\ 0 & 0 & 0 & 1 \end{bmatrix}

g\vec g旋转到z-z方向,将t\vec t旋转到 y 轴方向,将g×t\vec g \times \vec t旋转到 x 轴方向,可得到矩阵RviewR_{view},但是这个矩阵并不好求,但我们可以反过来求。
我们可以按照变换后的基底直接求出逆变换的变换矩阵,由于是正交基底构成的矩阵,所以是正交矩阵,所以RviewT=Rview1R_{view}^T=R^{-1}_{view}

Rview1=[xg×txtxg0yg×tytyg0zg×tztzg00001]R^{-1}_{view}=\begin{bmatrix} x_{\vec g \times \vec t} & x_{\vec t} & x_{\vec {-g}} & 0\\ y_{\vec g \times \vec t} & y_{\vec t} & y_{\vec {-g}} & 0\\ z_{\vec g \times \vec t} & z_{\vec t} & z_{\vec {-g}} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

故最终相机变换矩阵得到

Mview=RviewTviewM_{view}=R_{view}T_{view}

Projection 投影变换

平行投影变换矩阵推导

假设平行投影摄像机的视线范围由长方体[l,r]×[b,t]×[f,n][l, r] \times [b,t] \times [f,n] 所确定,其中 l,r 为 x 轴方向的两平面位置,b,t 为 y 轴方向的两平面位置,f,n 为 z 轴方向的两平面位置。我们希望将其标准化到[1,1]3[-1,1]^3
首先将其平移到原点,然后再缩放它。

Mortho=[2rl00002tb00002nf00001][100r+l2010t+b2001n+f20001]=[2rl00r+lrl02tb0t+btb002nfn+fnf0001]M_{ortho}= \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{2}{n-f} & -\frac{n+f}{n-f} \\ 0 & 0 & 0 & 1 \end{bmatrix}

透视投影变换矩阵推导

透视投影摄像机的视线范围由一个平头四棱台体所确定,使得内部的物体可以呈现近大远小的效果。
我们可以想象以下直接通过“挤压”将平头四棱台挤压为一个长方体,变换前后 n 平面上的点不变,n~f 平面上的点将被压缩,越接近 f 平面,点被压缩的越厉害,所以当变换到长方体后相同的三维几何体离 f 平面越近投影后的图像就越小,故能够呈现出近大远小的效果。这也是一种空间变换,但它在三维空间中属于一种非线性变换,如果我们希望使用矩阵描述,则需要借助齐次坐标将其放置在四维空间中完成这个变换。

alt text

假设这种“挤压”变换可以使用矩阵 A 描述,则最终的透视投影变换矩阵可表述如下:

Mpersp=MorthoMpersporthoM_{persp}=M_{ortho} \cdot M_{persp \to ortho}

矩阵MpersporthoM_{persp \to ortho}的推导如下:
x=nzxx'=\frac{n}{z}x
y=nzyy'=\frac{n}{z}y

[xyz1][nzxnzy?1]=[nxny?z]\begin{bmatrix} x \\ y \\ z \\ 1 \\ \end{bmatrix} \Rightarrow \begin{bmatrix} \frac{n}{z}x \\ \frac{n}{z}y \\ ? \\ 1 \\ \end{bmatrix} = \begin{bmatrix} nx \\ ny \\ ? \\ z \\ \end{bmatrix}

由于 n 平面上的任何点在变换前后位置都仍然不变,设未知量?为 k 可得出以下关系:

[xyn1]=[nxnykn]\begin{bmatrix} x \\ y \\ n \\ 1 \\ \end{bmatrix} = \begin{bmatrix} nx \\ ny \\ k \\ n \\ \end{bmatrix}

解得k=n2k=n^2
故矩阵MpersporthoM_{persp \to ortho}可初步写为如下形式

Mpersportho=[n0000n0000AB0010]M_{persp \to ortho}= \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & A & B\\ 0 & 0 & 1 & 0 \end{bmatrix}

由于 f 平面和 z 轴的交点在变换前后都不变,故得出以下关系:

[00f1]=[00f2f]\begin{bmatrix} 0 \\ 0 \\ f \\ 1 \\ \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \\ f^2 \\ f \\ \end{bmatrix}

由这两个特殊点可列出关于 A,B 未知数的二元一次方程组

{An+B=n2Af+B=f2\left\{\begin{matrix} An+B=n^2 \\ Af+B=f^2 \end{matrix}\right.

解得

{A=n+fB=nf\left\{\begin{matrix} A=n+f \\ B=-nf \end{matrix}\right.

故得到矩阵

Mpersportho=[n0000n0000n+fnf0010]M_{persp \to ortho}= \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{bmatrix}

最终投影矩阵为:

Mpersp=MorthoMpersportho=[2nrl0l+rlr002ntbb+tbt000n+fnf2nffn0010]M_{persp}= M_{ortho} \cdot M_{persp \to ortho} = \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{l+r}{l-r} & 0 \\ 0 & \frac{2n}{t-b} & \frac{b+t}{b-t} & 0 \\ 0 & 0 & \frac{n+f}{n-f} & \frac{2nf}{f-n} \\ 0 & 0 & 1 & 0 \end{bmatrix}

z 坐标变换深入思考

当我们从透视投影的平头四棱台空间压缩变换到平行投影的长方体后,对于内部的任意一点(x,y,z)(x,y,z)坐标,变换后对应的坐标为(x,y,z)(x',y',z'),显然是可以得到zz越远的点,(x,y)(x',y')坐标被压缩的越厉害,关系式可在上述推导中体现。但是内部任意一个点的 z 坐标在变换前后就没有那么直观,我们可以进一步做一系列推导。

[xyz1]=[n0000n0000n+fnf0010][xyz1]=[nxny(n+f)znfz]=[nxznyz(n+f)nfz1]\begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} = \begin{bmatrix} nx \\ ny \\ (n+f)z-nf \\ z \end{bmatrix} = \begin{bmatrix} n\frac{x}{z} \\ n\frac{y}{z} \\ (n+f)-\frac{nf}{z} \\ 1 \end{bmatrix}

可得到函数z=(n+f)nfzz'=(n+f)-\frac{nf}{z}关于自变量zz的函数关系,zz的定义域为[n,f][n,f]
为了得知变换前后的 z 坐标是变远了还是变近了,可以做差得到函数f(z)f(z)

f(z)=zz=(n+f)(nfz+z),z[n,f]>0f(z)=z'-z=(n+f)-(\frac{nf}{z}+z), z \in [n,f] > 0

f(z)=0f(z)=0,则得到方程z2(n+f)+nf=0z^2-(n+f)+nf=0,即(zn)(zf)=0(z-n)(z-f)=0,得到方程有两个零点

x1=n,x2=fx_1=n, x_2=f

函数f(z)f(z)求导得f(z)=nfz21f'(z)=\frac{nf}{z^2}-1
f(z)>0f'(z)>0得,n<z<nfn<z<\sqrt{nf},令f(z)<0f'(z)<0得,nf<z<f\sqrt{nf}<z<f
得出以下函数及导函数分布表

z nn (n,nf)(n,\sqrt{nf}) nf\sqrt{nf} (nf,f)(\sqrt{nf},f) ff
f’(z) - >0 0 <0 -
f(z) 0 增函数 - 减函数 0

f(z)>=0f(z)>=0恒成立(当z=n or z=fz=n \space or \space z=f时,等号成立)
故对于透视投影空间内的某一点被压缩后,z>zz'>z,z 坐标变远。

实际应用的透视投影矩阵

alt text

实际使用中。近平面的 l, r, b, t 是如何确定的呢?通常人们使用field of view(视场角 fovY)和aspect ratio(宽高比)来计算得到。

alt text

假设近平面到相机的距离为 n,垂直角度为 fovY,假设相机的(x, y)坐标处于近平面的中心点,则有l=r,b=tl=-r, b=-t,则根据如图的推导,可得到:

tan(fovY2)=tnaspectRatio=rltb=2r2t=rttan(\frac{fovY}{2}) = \frac{t}{|n|} \\ aspectRatio = \frac{r-l}{t-b} = \frac{2r}{2t} = \frac{r}{t}

现在可以确定出:

{t=ntan(fovY2)b=tr=taspectRatiol=r\left\{ \begin{aligned} t &= |n| \cdot \tan\left(\frac{\text{fovY}}{2}\right) \\ b &= -t \\ r &= t \cdot \text{aspectRatio} \\ l &= -r \end{aligned} \right.