0%

DirectX 12 龙书读书笔记(3)

线性变换

定义

数学函数 τ(v)=τ(x,y,z)=(x,y,z)\tau(\boldsymbol{v})=\tau(x,y,z)=(x^\prime,y^\prime,z^\prime),我们称τ\tau线性变换(linear transformation),当且仅当该函数具有下列性质:

τ(u+v)=τ(u)+τ(v)τ(ku)=kτ(u)\begin{aligned} \tau(\boldsymbol{u}+\boldsymbol{v}) &=\tau(\boldsymbol{u})+\tau(\boldsymbol{v}) \\ \tau(k\boldsymbol{u}) &=k\tau(\boldsymbol{u}) \end{aligned}

其中 u\boldsymbol{u}v\boldsymbol{v}是任意三维向量,kk为标量。

矩阵表示法

向量 u=(x,y,z)\boldsymbol{u}=(x,y,z) 可以写作

u=(x,y,z)=xi+yj+zk=x(1,0,0)+y(0,1,0)+z(0,0,1)\boldsymbol{u}=(x,y,z)=x\boldsymbol{i}+y\boldsymbol{j}+z\boldsymbol{k}=x(1,0,0)+y(0,1,0)+z(0,0,1)

i\boldsymbol{i}j\boldsymbol{j}k\boldsymbol{k} 称为 R3\mathbb{R}^3标准基向量 (standard basis vector)。设τ\tau 为一种线性变换,能够得到

τ(u)=τ(xi+yj+zk)=uA=[x,y,z][A11A12A13A21A22A23A31A32A33]\begin{aligned} \tau(\boldsymbol{u})&=\tau(x\boldsymbol{i}+y\boldsymbol{j}+z\boldsymbol{k}) \\ &=\boldsymbol{uA}=[x,y,z]\left[\begin{array}{ccc} A_{11} &A_{12} &A_{13} \\ A_{21} &A_{22} &A_{23} \\ A_{31} &A_{32} &A_{33} \end{array} \right] \end{aligned}

其中 τ(i)=(A11,A12,A13)\tau(\boldsymbol{i})=(A_{11},A_{12},A_{13})τ(j)=(A21,A22,A23)\tau(\boldsymbol{j})=(A_{21},A_{22},A_{23})τ(k)=(A31,A32,A33)\tau(\boldsymbol{k})=(A_{31},A_{32},A_{33})

缩放

缩放(scaling,又称比例变换),定义为

S(x,y,z)=(sxx,syy,szz)S(x,y,z)=(s_xx,s_yy,s_zz)

缩放矩阵(scaling matrix)表示为

S=[sx000sy000sz]\boldsymbol{S}=\left[\begin{array}{ccc} s_x &0 &0 \\ 0 &s_y &0 \\ 0 &0 &s_z \end{array} \right]

其对应的逆矩阵为

S=[1/sx0001/sy0001/sz]\boldsymbol{S}=\left[\begin{array}{ccc} 1/s_x &0 &0 \\ 0 &1/s_y &0 \\ 0 &0 &1/s_z \end{array} \right]

旋转

描述令向量 v\boldsymbol{v} 绕轴 n\boldsymbol{n} 以角度 θ\boldsymbol{\theta} 进行旋转,在沿 n\boldsymbol{n} 轴从上至下俯瞰时,按顺时针方向测量角θ\boldsymbol{\theta},并假设n=1\left\|\boldsymbol{n}\right\|=1

可得旋转的变换矩阵

Rn=[cosθ+(1cosθ)x2(1cosθ)xy+sinθz(1cosθ)xzsinθy(1cosθ)xysinθzcosθ+(1cosθ)y2(1cosθ)yz+sinθx(1cosθ)xz+sinθy(1cosθ)yzsinθxcosθ+(1cosθ)z2]\boldsymbol{R}_\boldsymbol{n}=\left[\begin{array}{ccc} \boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})x^2 &(1-\boldsymbol{\cos\theta})xy+\boldsymbol{\sin\theta}z &(1-\boldsymbol{\cos\theta})xz-\boldsymbol{\sin\theta}y \\ (1-\boldsymbol{\cos\theta})xy-\boldsymbol{\sin\theta}z &\boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})y^2 &(1-\boldsymbol{\cos\theta})yz+\boldsymbol{\sin\theta}x \\ (1-\boldsymbol{\cos\theta})xz+\boldsymbol{\sin\theta}y &(1-\boldsymbol{\cos\theta})yz-\boldsymbol{\sin\theta}x &\boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})z^2 \end{array} \right]

旋转矩阵每个行向量都为单位长度且两两正交,即行向量都是 规范正交的 (orthonormal),并称其为 正交矩阵(orthogonal matrix)。它的逆矩阵与转置矩阵相等:

Rn1=RnT=[cosθ+(1cosθ)x2(1cosθ)xysinθz(1cosθ)xz+sinθy(1cosθ)xy+sinθzcosθ+(1cosθ)y2(1cosθ)yzsinθx(1cosθ)xzsinθy(1cosθ)yz+sinθxcosθ+(1cosθ)z2]\boldsymbol{R}_\boldsymbol{n}^{-1}=\boldsymbol{R}_\boldsymbol{n}^T=\left[\begin{array}{ccc} \boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})x^2 &(1-\boldsymbol{\cos\theta})xy-\boldsymbol{\sin\theta}z &(1-\boldsymbol{\cos\theta})xz+\boldsymbol{\sin\theta}y \\ (1-\boldsymbol{\cos\theta})xy+\boldsymbol{\sin\theta}z &\boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})y^2 &(1-\boldsymbol{\cos\theta})yz-\boldsymbol{\sin\theta}x \\ (1-\boldsymbol{\cos\theta})xz-\boldsymbol{\sin\theta}y &(1-\boldsymbol{\cos\theta})yz+\boldsymbol{\sin\theta}x &\boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})z^2 \end{array} \right]

特别的,以 xxyyzz 为旋转轴的对应旋转矩阵为:

Rx=[10000cosθsinθ00sinθcosθ00001],Ry=[cosθ0sinθ00100sinθ0cosθ00001],Rz=[cosθsinθ00sinθcosθ0000100001]\boldsymbol{R}_x=\left[\begin{array}{cccc} 1 &0 &0 &0\\ 0 &\boldsymbol{\cos\theta} &\boldsymbol{\sin\theta} &0\\ 0 &-\boldsymbol{\sin\theta} &\boldsymbol{\cos\theta} &0\\ 0 &0 &0 &1 \end{array} \right], \boldsymbol{R}_y=\left[\begin{array}{cccc} \boldsymbol{\cos\theta} &0 &-\boldsymbol{\sin\theta} &0\\ 0 &1 &0 &0\\ \boldsymbol{\sin\theta} &0 &\boldsymbol{\cos\theta} &0\\ 0 &0 &0 &1 \end{array} \right], \boldsymbol{R}_z=\left[\begin{array}{cccc} \boldsymbol{\cos\theta} &\boldsymbol{\sin\theta} &0 &0\\ -\boldsymbol{\sin\theta} &\boldsymbol{\cos\theta} &0 &0\\ 0 &0 &1 &0\\ 0 &0 &0 &1 \end{array} \right]

仿射变换

齐次坐标

仿射变换(affine transformation)是由一个线性变换与一个平移变换组合而成的。平移变换只能应用于点,齐次坐标(homogeneous coordinate)所提供的表示机制,是我们可以方便地对点和向量进行统一的处理:

  1. (x,y,z,0)(x,y,z,0)表示向量;
  2. (x,y,z,1)(x,y,z,1)表示点。

仿射变换定义及其矩阵表示

仿射变换为一个线性变换加上一个平移向量b\boldsymbol{b},即

α(u)=τ(u)+b\alpha(\boldsymbol{u})=\tau(\boldsymbol{u})+\boldsymbol{b}

或使用矩阵表示法

α(u)=uA+b=[x,y,z][A11A12A13A21A22A23A31A32A33]+[bx,by,bz]=[x,y,z]\alpha(\boldsymbol{u})=\boldsymbol{uA}+\boldsymbol{b}=[x,y,z]\left[\begin{array}{ccc} A_{11} &A_{12} &A_{13} \\ A_{21} &A_{22} &A_{23} \\ A_{31} &A_{32} &A_{33} \end{array} \right]+[b_x,b_y,b_z]=[x^\prime,y^\prime,z^\prime]

平移

将平移变换(translation transformation)定义为仿射变换,此时其中的线性变换是一种 恒等变换(identity transformation),即

τ(u)=uI+b=u+b\tau(\boldsymbol{u})=\boldsymbol{uI}+\boldsymbol{b}=\boldsymbol{u}+\boldsymbol{b}

平移矩阵(translation matrix)为

T=[100001000010bxbybz1]\boldsymbol{T}=\left[\begin{array}{cccc} 1 &0 &0 &0\\ 0 &1 &0 &0\\ 0 &0 &1 &0\\ b_x &b_y &b_z &1 \end{array} \right]

其逆矩阵为

T1=[100001000010bxbybz1]\boldsymbol{T}^{-1}=\left[\begin{array}{cccc} 1 &0 &0 &0\\ 0 &1 &0 &0\\ 0 &0 &1 &0\\ -b_x &-b_y &-b_z &1 \end{array} \right]

缩放和旋转的仿射矩阵

缩放矩阵与旋转矩阵可以写作:

S=[sx0000sy0000sz00001]\boldsymbol{S}=\left[\begin{array}{cccc} s_x &0 &0 &0\\ 0 &s_y &0 &0\\ 0 &0 &s_z &0\\ 0 &0 &0 &1 \end{array} \right]

Rn=[cosθ+(1cosθ)x2(1cosθ)xy+sinθz(1cosθ)xzsinθy0(1cosθ)xysinθzcosθ+(1cosθ)y2(1cosθ)yz+sinθx0(1cosθ)xz+sinθy(1cosθ)yzsinθxcosθ+(1cosθ)z200001]\boldsymbol{R}_\boldsymbol{n}=\left[\begin{array}{cccc} \boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})x^2 &(1-\boldsymbol{\cos\theta})xy+\boldsymbol{\sin\theta}z &(1-\boldsymbol{\cos\theta})xz-\boldsymbol{\sin\theta}y &0\\ (1-\boldsymbol{\cos\theta})xy-\boldsymbol{\sin\theta}z &\boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})y^2 &(1-\boldsymbol{\cos\theta})yz+\boldsymbol{\sin\theta}x &0\\ (1-\boldsymbol{\cos\theta})xz+\boldsymbol{\sin\theta}y &(1-\boldsymbol{\cos\theta})yz-\boldsymbol{\sin\theta}x &\boldsymbol{\cos\theta}+(1-\boldsymbol{\cos\theta})z^2 &0\\ 0 &0 &0 &1 \end{array} \right]

仿射变换矩阵的几何意义

刚体变换 (rigid body transformation)本质是一种保形(shape preserving)变换。设τ\tau 为描述物体旋转操作的旋转变换,而 b\boldsymbol{b} 为定义物体平移操作的平移向量。那么,刚体变换就可以用仿射变换来表示:

α(x,y,z)=τ(x,y,z)+b=xτ(i)+yτ(j)+zτ(k)+b\alpha(x,y,z)=\tau(x,y,z)+\boldsymbol{b}=x\tau(\boldsymbol{i})+y\tau(\boldsymbol{j})+z\tau(\boldsymbol{k})+\boldsymbol{b}

坐标变换

不同标架间的坐标的转换称之为 坐标变换(change of coordinate transformation,译为坐标系变换或许更好)。

向量的坐标变换

设给定向量 p\boldsymbol{p} 在标架 AA 中的坐标为 pA=(x,y,z)\boldsymbol{p}_A=(x,y,z),希望求得向量p\boldsymbol{p} 在标架 BB 中的对应坐标pB\boldsymbol{p}_B,那么

pB=xuB+yvB+zwB\boldsymbol{p}_B=x\boldsymbol{u}_B+y\boldsymbol{v}_B+z\boldsymbol{w}_B

其中,u\boldsymbol{u}v\boldsymbol{v}w\boldsymbol{w} 分别是指向标架 AAxx轴、yy轴和 zz 轴正方向上的单位向量。

点的坐标变换

如果点 p\boldsymbol{p} 在标架 AA 中的坐标为pA=(x,y,z)\boldsymbol{p}_A=(x,y,z),那么

pB=xuB+yvB+zwB+QB\boldsymbol{p}_B=x\boldsymbol{u}_B+y\boldsymbol{v}_B+z\boldsymbol{w}_B+\boldsymbol{Q}_B

其中,u\boldsymbol{u}v\boldsymbol{v}w\boldsymbol{w} 分别是指向标架 AAxx轴、yy轴和 zz 轴正方向上的单位向量,Q\boldsymbol{Q}为标架 AA 中的原点。

坐标变换的矩阵表示

使用齐次坐标,可用同一公式对点和向量进行处理:

(x,y,z,w)=xuB+yvB+zwB+QB(x^\prime,y^\prime,z^\prime,w)=x\boldsymbol{u}_B+y\boldsymbol{v}_B+z\boldsymbol{w}_B+\boldsymbol{Q}_B

上式可改写为矩阵形式:

[x,y,z,w]=[x,y,z,w][uxuyuz0vxvyvz0wxwywz0QxQyQz1]=xuB+yvB+zwB+wQB\begin{aligned} \left[x^\prime,y^\prime,z^\prime,w\right]&=[x,y,z,w]\left[\begin{array}{cccc} u_x &u_y &u_z &0\\ v_x &v_y &v_z &0\\ w_x &w_y &w_z &0\\ Q_x &Q_y &Q_z &1 \end{array} \right] \\ &=x\boldsymbol{u}_B+y\boldsymbol{v}_B+z\boldsymbol{w}_B+w\boldsymbol{Q}_B \end{aligned}

我们把能把标架 AA 中的坐标转换为标架 BB 中的坐标的 4×44\times4 矩阵,称为 坐标变换矩阵 (change of coordinate matrix)或 标架变换矩阵(change of frame matrix)。

标架变换映射都是可逆的,因此一定存在逆矩阵使标架 BB 中的坐标转换为标架 AA 中的坐标。

DirectXMath 库

DirectXMath 中与变换相关的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 构建缩放矩阵
XMMATRIX XM_CALLCONV XMMatrixScaling (float ScaleX, float ScaleY, float ScaleZ);
XMMATRIX XM_CALLCONV XMMatrixScalingFromVector (FXMVECTOR Scale);
// 构建旋转矩阵 R_x、R_y、R_z 和 R_n(沿轴正方向看,顺时针旋转)
XMMATRIX XM_CALLCONV XMMatrixRotationX (float Angle);
XMMATRIX XM_CALLCONV XMMatrixRotationY (float Angle);
XMMATRIX XM_CALLCONV XMMatrixRotationZ (float Angle);
XMMATRIX XM_CALLCONV XMMatrixRotationAxis (FXMVECTOR Axis, float Angle);
// 构建平移矩阵
XMMATRIX MX_CALLCONV XMMatrixTranslation (float OffsetX, float OffsetY, float OffsetZ);
XMMATRIX MX_CALLCONV XMMatrixTranslationFromVector (FXMVECTOR Offset);
// 计算向量与矩阵的乘积 vM,针对点
XMVECTOR MX_CALLCONV XMVector3TransformCoord (FXMVECTOR V, CXMMATRIX M);
// 计算向量与矩阵的乘积 vM,针对向量
XMVECTOR MX_CALLCONV XMVector3TransformNormal (FXMVECTOR V, CXMMATRIX M);