回顾Games101图形学(一)几何变换中一些公式的推导

回顾Games101 chatper1 – 6

前言

本文只写回顾后重新加深认识的知识

透视除法的意义

经过MVP矩阵之后,将模型空间下某点的坐标,转换成了裁剪空间下的坐标,此时因为裁剪空间的范围是x∈[-W/2,W/2]和y∈[-H/2,H/2],所以经过以下两个变换,其中除以pz就是透视除法
一:

\[-1≤2·\frac{\left( \frac{p_x}{p_z}·near \right)}{w}≤1
\\
-1≤2·\frac{\left( \frac{p_y}{p_z}·near \right)}{h}≤1
\]

二:

\[\left[ \begin{matrix}
x& y& z& w\\
\end{matrix} \right] \left[ \begin{matrix}
1& 0& 0& 0\\
0& 1& 0& 0\\
0& 0& 1& 0\\
\varDelta x& \varDelta y& \varDelta z& 1\\
\end{matrix} \right] =\left[ \begin{matrix}
x+\varDelta x*w& y+\varDelta y*w& z+\varDelta z*w& w\\
\end{matrix} \right]
\]

只有当W=1,这个三维坐标转换是等价的,才能保证位移的量是正确的,W=0时,则没有位移

只有当W=1时,三维坐标点转换成四维齐次坐标点才是等价的

坐标系变换和矩阵推导

坐标系变换理解不直观,倾向于101中闫老师所说的理解坐标系的转换通过矩阵进行的线性变换,将A坐标系下的点P,乘上矩阵得出B坐标系下的点P’,以下是抛开常见的变换(如透视投影变换、正交投影变换等)如何得出变换矩阵M,通过矩阵变换(下文着重说明)

已知坐标系A和坐标系B

\[坐标系B的x,y,z轴在坐标系A下可表示为(u_{\mathrm{x}},u_{\mathrm{y}},v_{\mathrm{z}},0)
\]

\[\left( \mathrm{v}_{\mathrm{x}},\mathrm{v}_{\mathrm{y}},\mathrm{v}_{\mathrm{z}},0 \right) \text{,}\left( \mathrm{w}_{\mathrm{x}},\mathrm{w}_{\mathrm{y}},\mathrm{w}_{\mathrm{z}},0 \right) \text{,坐标系B的原点在坐标系A下表示为(Q}_{\mathrm{x}},\mathrm{Q}_{\mathrm{y}},\mathrm{Q}_{\mathrm{z}},1\text{)}
\]

img

则将坐标系B中一点P从坐标系B变换到坐标系A的变换矩阵为:(注意此处的例子是将源坐标系A变换到目标坐标系B下)

\[\mathrm{M}=\left[ \begin{matrix}
u_{\mathrm{x}}& u_{\mathrm{y}}& u_{\mathrm{z}}& 0\\
v_{\mathrm{x}}& v_{\mathrm{y}}& v_{\mathrm{z}}& 0\\
w_{\mathrm{x}}& w_{\mathrm{y}}& w_{\mathrm{z}}& 0\\
Q_{\mathrm{x}}& Q_{\mathrm{y}}& Q_{\mathrm{z}}& 1\\
\end{matrix} \right]
\]

如之前所说,变换过程中点p在空间中的绝对位置没有发生改变,只是参考坐标系发生了改变,从B坐标系变到A坐标系。(缩放,旋转,平移变换只有在同一坐标系下才有意义)

矩阵变换是基于基向量组的结果

  • 矩阵变换之于同一个坐标系,可以理解为坐标系不变,点的位置改变
  • 矩阵变换之于不同坐标系,可以理解为点的绝对位置不变,坐标系改变
\[\left[ \begin{array}{c}
x^{‘}\\
y^{‘}\\
\end{array} \right] =B\left[ \begin{array}{c}
x\\
y\\
\end{array} \right] \Rightarrow \left[ \begin{array}{c}
x\\
y\\
\end{array} \right] =B^{-1}\left[ \begin{array}{c}
x^{‘}\\
y^{‘}\\
\end{array} \right] \text{,}B=\left[ \begin{matrix}
\overrightarrow{b_1}& \overrightarrow{b_2}\\
\end{matrix} \right] \text{,且}\overrightarrow{b_1}\text{,}\overrightarrow{b_2}\text{是坐标系}B\text{的基向量}
\]

其中,矩阵B的各个列向量分别对应B坐标系的各个基向量,\(
\left[ \begin{array}{c}
x\\
y\\
\end{array} \right]
\)
是向量\(
\overrightarrow{OP}
\)
或者说点P在B坐标系的表示,\(
\left[ \begin{array}{c}
x^{‘}\\
y^{‘}\\
\end{array} \right]
\)
则是向量\(
\overrightarrow{OP}
\)
或者点P在A坐标系中的表示

这里写图片描述

以图中的两个向量\(
\overrightarrow{b_1}
\)
\(
\overrightarrow{b_2}
\)
为基确定一个坐标系B,显然在B坐标系中\(
\overrightarrow{b_{1B}}=\left[ \begin{array}{c}
1\\
0\\
\end{array} \right]
\)
\(
\overrightarrow{b_{2B}}=\left[ \begin{array}{c}
0\\
1\\
\end{array} \right]
\)
,接下来,将\(
\overrightarrow{b_1}
\)
\(
\overrightarrow{b_2}
\)
定位到A坐标系中,得到\(
\overrightarrow{b_{1A}}=\left[ \begin{array}{c}
2\\
1\\
\end{array} \right]
\)
\(
\overrightarrow{b_{2A}}=\left[ \begin{array}{c}
-1\\
1\\
\end{array} \right]
\)

\(
\because \overrightarrow{OP}=2\overrightarrow{b_1}+2\overrightarrow{b_2}
\)

\(
\therefore \overrightarrow{OP}\)
在B坐标系中的表示为\(
\left[ \begin{array}{c}
2\\
2\\
\end{array} \right]
\)
,现在,将\(
\overrightarrow{OP}
\)
用A坐标系描叙:
\(
\overrightarrow{OP}=2\overrightarrow{b_1}+2\overrightarrow{b_2}=2\overrightarrow{b_{1A}}+2\overrightarrow{b_{2A}}=\left[ \begin{matrix}
\overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\
\end{matrix} \right] \left[ \begin{array}{c}
2\\
2\\
\end{array} \right] =\left[ \begin{array}{c}
2\\
4\\
\end{array} \right]
\\
\)

现在,令矩阵B=\(
\left[ \begin{matrix}
\overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\
\end{matrix} \right]
\)
,P点是用B坐标系表示的任意一点\((x,y)\)
于是\(
\overrightarrow{OP}
\)
在A坐标系中的表示\(
\left[ \begin{array}{c}
^{x^{‘}}\\
y^{‘}\\
\end{array} \right] =B\left[ \begin{array}{c}
x\\
y\\
\end{array} \right]
\)
,显然,B是可逆的,于是就有了之前的结论
那么在这个例子当中,当我们需要知道某点在转换坐标系后的新坐标时,通过该例子也可以加深印象,比如在B坐标系下有点\(Q(3,4)\),即\(\overrightarrow{OQ}=(3,4)\),跟据刚才的例子可以看出它转换在A坐标系下的点

\[\overrightarrow{OQ}=2\overrightarrow{b_1}+2\overrightarrow{b_2}=2\overrightarrow{b_{1A}}+2\overrightarrow{b_{2A}}=\left[ \begin{matrix}
\overrightarrow{b_{1A}}& \overrightarrow{b_{2A}}\\
\end{matrix} \right] \left[ \begin{array}{c}
3\\
4\\
\end{array} \right] =\left[ \begin{matrix}
2& -1\\
1& 1\\
\end{matrix} \right] \left[ \begin{array}{c}
5\\
4\\
\end{array} \right] =\left[ \begin{array}{c}
6\\
9\\
\end{array} \right]
\]

即转换到A坐标系下的点\(Q^{‘}\)的坐标为\(Q^{‘}(6,9)\)

虽然这里的讨论是基于二维的,但是,结论可以扩展到任意维度

阐述结论:

将B坐标系的基向量定位到A坐标系,然后将定位之后的基向量作为矩阵B的列向量,用矩阵B对B坐标系中的点P的坐标进行矩阵变换,将得到点P在A坐标系中的坐标。这个过程,就是从坐标系B到坐标系A的一个追溯过程

View/Camera Transformation

先将相机移到原点,然后进行分别对坐标轴进行旋转,用矩阵表示则是\(M_{view}=R_{view}T_{view}\)

  • 将相机移回原点
\[T_{view}=\left[ \begin{matrix}
1& 0& 0& -x_e\\
0& 1& 0& -y_e\\
0& 0& 1& -z_e\\
0& 0& 0& 1\\
\end{matrix} \right]
\]

  • \(Rotate\,\,g\,\,to\,\,-Z, t\,\,to\,\,Y, \left( g×t \right) \,\,To\,\,X\)
    g是相机看的方向(lookAt),t是相机向上的方向(Up),也就是相机的-Z轴和Y轴,两个向量叉积就是另一个坐标轴
\[R_{view}^{-1}=\left[ \begin{matrix}
x_{\widehat{g}×\widehat{t}}& x_t& x_{-g}& 0\\
y_{\widehat{g}×\widehat{t}}& y_t& y_{-g}& 0\\
z_{\widehat{g}×\widehat{t}}& z_t& z_{-g}& 0\\
0& 0& 0& 1\\
\end{matrix} \right]
\]

旋转矩阵是正交矩阵,所以旋转矩阵的逆就是旋转矩阵的转置

\[R_{view}^{}=\left[ \begin{matrix}
x_{\widehat{g}×\widehat{t}}& y_{\widehat{g}×\widehat{t}}& z_{\widehat{g}×\widehat{t}}& 0\\
x_t& y_t& y_t& 0\\
x_{-g}& y_{-g}& z_{-g}& 0\\
0& 0& 0& 1\\
\end{matrix} \right]
\]

正交投影矩阵

无论是正交投影还是透视投影,都是要将x、y、z移到-1到1的范围内,先将中心点移到原点,然后缩放

\[M_{ortho}=\left( \begin{matrix}
\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{matrix} \right) \left( \begin{matrix}
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{matrix} \right)
\]

透视投影矩阵推导

首先先将frustum 转变为cuboid(n -> n,f -> f)(\(
M_{persp->ortho}
\)

)
然后再做正交投影

整个投影变换包括两部分

  • v = P(矩阵)*p
  • \(v=\frac{v}{v_w}=\frac{v}{pz}\)透视除法


以上大概推出等式这一步,接下来用公式展示更为直观

\[\left( \begin{matrix}
m00& m01& m02& m03\\
m10& m11& m12& m13\\
m20& m21& m22& m23\\
m30& m31& m32& m33\\
\end{matrix} \right) \left( \begin{array}{c}
x\\
y\\
z\\
1\\
\end{array} \right) =\left( \begin{array}{c}
\frac{x}{z*aspect*\tan \left( \frac{fov}{2} \right)}\\
\frac{y}{z*tan\left( \frac{fov}{2} \right)}\\
z^{‘’}\\
1\\
\end{array} \right)
\]

\[m00*x+m01*y+m02*z+m03=\frac{x}{z*aspect*\tan \left( \frac{fov}{2} \right)}
\]

将右边的四维列向量表示的坐标每一项乘以z,所以有

\[\left( \begin{matrix}
m00& m01& m02& m03\\
m10& m11& m12& m13\\
m20& m21& m22& m23\\
m30& m31& m32& m33\\
\end{matrix} \right) *\left( \begin{array}{c}
x\\
y\\
z\\
1\\
\end{array} \right) =\left( \begin{array}{c}
\frac{x}{aspect*\tan \left( \frac{fov}{2} \right)}\\
\frac{y}{\tan \left( \frac{fov}{2} \right)}\\
z*z^{{‘}{‘}}\\
z\\
\end{array} \right)
\]

所以求得矩阵为

\[\left( \begin{matrix}
\frac{1}{aspect*\tan \left( \frac{fov}{2} \right)}& 0& 0& 0\\
0& \frac{1}{\tan \left( \frac{fov}{2} \right)}& 0& 0\\
0& 0& m22& m23\\
0& 0& 1& 0\\
\end{matrix} \right)
\]

\[m22*z+m23 =\,\,z*z^{{‘}{‘}}
\\
\Rightarrow m22+\frac{m23}{z}=z^{{‘}{‘}}
\]

因为z=zNear时,z”=-1;z=zFar时,z”=1所以有以下等式

\[m22+\frac{m23}{zNear}=-1
\\
m22+\frac{m23}{zFar}=1
\]

联立求得:

\[m22=\frac{-zFar-zNear}{zNear-zFar}
\\
m23=\frac{2*zFar*zNear}{zNear-zFar}
\]

最后求得投影矩阵为

\[\left( \begin{matrix}
\frac{1}{aspect*\tan \left( \frac{fov}{2} \right)}& 0& 0& 0\\
0& \frac{1}{\tan \left( \frac{fov}{2} \right)}& 0& 0\\
0& 0& \frac{-zFar-zNear}{zNear-zFar}& \frac{2*zNear*zFar}{zNear-zFar}\\
0& 0& 1& 0\\
\end{matrix} \right)
\]

将这样得矩阵乘以视锥体内的一个顶点坐标,得到一个新的向量,再将这个向量的每个分量除以第四个分量(此步骤也被称为透视除法)(w),这样就可以得到顶点映射到规则立方观察体后的新的坐标

注意:z坐标的映射方式的获得,最后我们是为了方便矩阵乘法的操作方向求得了z坐标与cvv中的z坐标的映射方式:

\[m22+\frac{m23}{z}=z^{{‘}{‘}}
\]

此时的映射并不是线性的,当z越大时,z的变化对z”的扰动越小

Canonical Cube to Screen

  • Irrelevant to z
  • Transform in xy plane : [-1, 1] to [0, width] × [0, height]
  • Viewport transform matrix:

视口矩阵

\[M_{viewport}=\left[ \begin{matrix}
\frac{width}{2}& 0& 0& \frac{width}{2}\\
0& \frac{height}{2}& 0& \frac{height}{2}\\
0& 0& 1& 0\\
0& 0& 0& 1\\
\end{matrix} \right]
\]

深度z的计算

前言
3D光栅化发生在图元被变换到Screen space之后,因为这里的Screen space与2D的Screen Space完全一致,所以2D的光栅化算法在这里依然适用。

然而由于图元经过了投影变换,且投影变换为非线性变换,所以不能用简单的线性插值获取fragment的属性

投影变换不会保持相对距离不变性

如上图所示,view space中的线段v0v1上两点$
p0\left( p0_x,p0_y,p0_z,1 \right)
$,$
p1\left( p1_x,p1_y,p1_z,1 \right)
$在near plane上的投影为点$
s0\left( s0_x,s0_y \right)
$,$
s1\left( s1_x,s1_y \right)
$。$
p0
$,$p1$中间一点$v(v_x,v_y,v_z,1)$在near plane上的投影为点$q(q_x,q_y)$。从图中可以看出点v到p0,p1的距离比值与点q到s0,s1的距离比值完全不同,投影变换不保持距离不变。

为了执行z-buffer算法,需要通过点q获取到v的深度值(z)
\(v\)的深度值可以通过如下方法插值得到:

\[v_z=\frac{1}{\frac{c}{p1_z}+\frac{\left( 1-c \right)}{p0_z}}
\]

以下是推导的过程:

手写版:

文字版:
由于点\(q\)为点\(v\)在near plane上的投影,因此点\(q\)与点\(v\)的关系为:

  • \(q_x=\frac{v_x·near}{v_z}\)
    \(v\)位于\(p0p1\)之间,则
  • \(v_z=p0_{z}+t·(p1_z-p0_z)=\frac{v_x·near}{q_x}\)
    由点\(v\)\(p0\)\(p1\)之间,点\(q\)\(s0\)\(s1\)之间则有
  • \(v_x=p0_{x}·(1-t)+p1_{x}·t=p0_{x}+t·(p1_{x}-p0_{x})\)
  • \(q_x=s0_{x}·(1-c)+s1_{x}·c=s0_{x}+c·(s1_{x}-s0_{x})\)
    代入式(1)可得
    \(v_z=\frac{v_x·near}{q_x}=\frac{(p0_x+t·(p1_x-p0_x))·near}{s0_x+c·(s1_x-s0_x)}\)式(2)
    又s0和s1分别为p0和p1在near plane上的投影,则:
  • \(s0_x=\frac{p0_x·near}{p1_z}\)
  • \(s1_x=\frac{p1_x·near}{p1_z}\)
    代入式(2)可得:
\[v_z=\frac{\left( \frac{p0_x·s0_x}{near}+t·\left( \frac{p1_x·s1_x}{near}-\frac{p0_x·s0_x}{near} \right) \right) ·near}{s0_x+c·\left( s1_x-s0_x \right)}
\]

\[v_z=\frac{\left( \frac{p0_x·s0_x}{near}+t·\left( \frac{p1_x·s1_x}{near}-\frac{p0_x·s0_x}{near} \right) \right) ·near}{s0_x+c·\left( s1_x-s0_x \right)}
\\
v_z=\frac{\left( p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right) \right)}{s0_x+c·\left( s1_x-s0_x \right)}
\\
p0_z+t·\left( p1_z-p0_z \right) =\frac{\left( p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right) \right)}{s0_x+c·\left( s1_x-s0_x \right)}
\\
\left( p0_z+t·\left( p1_z-p0_z \right) \right) ·\left( s0_x+c·\left( s1_x-s0_x \right) \right) =p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right)
\\
p0_z·s0_x+p0_z·c·\left( s1_x-s0_x \right) +t·\left( p1_z-p0_z \right) ·s0_x+t·c·\left( p1_z-p0_z \right) ·\left( s1_x-s0_x \right) =p0_x·s0_x+t·\left( p1_x·s1_x-p0_x·s0_x \right)
\]

化简得:

\[t·\left( p1_z-c·\left( p1_z-p0_z \right) \right) =c·p0_z
\]

则:

\[t=\frac{c·p0_z}{c·p0_z+(1-c)·p1_z}
\]

代入式(1)可得

\[v_z=p0_z+t·(p1_z-p0_z)
\]

\[v_z=p0_z+\frac{c·p0_z}{c·p0_z+(1-c)·p1_z}·(p1_z-p0_z)
\]

\[v_z=\frac{1}{\frac{c}{p1_z}+\frac{(1-c)}{p0_z}}
\]

若View Space中三角形\(v0v1v2\),变换到Screen Space后为三角形\(s0s1s2\)\(v0v1v2\)内一点v在Screen Space的投影点\(s0s1s2\)内的点\(q\),对三角形\(s0s1s2\)内的点(fragment)\(q\),可以通过如下方法取得fragment\(q\)在View Space中对应的深度值:

\[q.z=v.z=\frac{1}{\frac{\lambda0}{v0.z}+\frac{\lambda1}{v1.z}+\frac{\lambda2}{v2.z}}
\]

\(\lambda0,\lambda1,\lambda2\)为点p在三角形\(s0s1s2\)内的重心坐标
引入结论:
对Screen Space三角形\(s0,s1,s2\)内一点p的任意属性插值的公式为:

\[Atribute\left( p \right) =z·\left( \frac{\lambda 0·Atribute\left( v0 \right)}{z0}+\frac{\lambda 1·Atribute\left( v1 \right)}{z1}+\frac{\lambda 2·Atribute\left( v2 \right)}{z2} \right)
\]

\(\lambda0,\lambda1,\lambda2\)为点\(p\)的重心坐标,\(z0,z1,z2,z\)分别为\(s0,s1,s2,p\)在view space中对应点的深度值,可以用这个方法插值得到\(p\)在NDC Space内对应点的深度值

罗德里格斯旋转公式

字写得不好,在爬了…
手写版:

文字版:
首先先将\(\overrightarrow{k}\)处理成单位向量,这点很重要,关乎着下一步等式是否成立,有些博文写这里不需要处理单位向量,这是错的

\[\overrightarrow{v}·\overrightarrow{k}=|\overrightarrow{v}|·|\overrightarrow{k}|·\cos <\overrightarrow{v}\text{,}\overrightarrow{k}>=|\overrightarrow{v}|·\cos <\overrightarrow{v}\text{,}\overrightarrow{k}>
\]

可得

\[\overrightarrow{v_{||}}=|\overrightarrow{v}|·\cos <\overrightarrow{v},\overrightarrow{k}>·\overrightarrow{k}
\\
\overrightarrow{v}=\overrightarrow{v_{\bot}}+\overrightarrow{v_{||}}
\\
\overrightarrow{v_{\bot}}=\overrightarrow{v}-\overrightarrow{v_{||}}=\overrightarrow{v}-\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k}
\]

\(\overrightarrow{k}\)做旋转时,向下做垂线,可看作底部经过了类似半圆的旋转
要求得\(\overrightarrow{v_{rot}}=\overrightarrow{v_{||}}+\overrightarrow{v_{rot\bot}}\),将\(\overrightarrow{v_{rot\bot}}\)作正交分解有\(
\overrightarrow{v_{rot\bot}}=\overrightarrow{a}+\overrightarrow{b}
\)
,易得\(
|\overrightarrow{w}|=|\overrightarrow{v_{\bot}}|
\)
,则有\(
\overrightarrow{w}=\overrightarrow{k}×\overrightarrow{v_{\bot}}=\overrightarrow{k}×\left[ \overrightarrow{v}-\overrightarrow{v_{||}} \right] =\overrightarrow{k}×\overrightarrow{v}-\overrightarrow{k}×\overrightarrow{v_{||}}=\overrightarrow{k}×\overrightarrow{v}-0=\overrightarrow{k}×\overrightarrow{v}
\)

接下来求\(
\overrightarrow{a}
\)
\(
\overrightarrow{b}
\)

\[|\overrightarrow{a}|=|\overrightarrow{v_{rot\bot}}|·\cos \left( \theta -90 \right) =|\overrightarrow{v_{rot\bot}}|·\sin \left( \theta \right)
\\
\overrightarrow{a}=\frac{\overrightarrow{w}}{|\overrightarrow{w}|}·|\overrightarrow{a}|=\frac{\overrightarrow{w}}{|\overrightarrow{v_{rot\bot}}|}·|\overrightarrow{v_{rot\bot}}|·\sin \left( \theta \right) =\overrightarrow{w}·\sin \left( \theta \right)
\]

\[|\overrightarrow{b}|=|\overrightarrow{v_{rot\bot}}|·\cos \left( 180-\theta \right) =|\overrightarrow{v_{rot\bot}}|·\cos \left( \theta \right)
\\
\overrightarrow{b}=\frac{\overrightarrow{v_{\bot}}}{|\overrightarrow{v_{\bot}}|}·|\overrightarrow{b}|=\frac{\overrightarrow{v_{\bot}}}{|\overrightarrow{v_{\bot}}|}·|\overrightarrow{v_{rot\bot}}|·\cos \left( \theta \right) =\overrightarrow{v_{\bot}}·\cos \left( \theta \right) \,\, \text{注意}|\overrightarrow{v_{\bot}}|=|\overrightarrow{v_{rot\bot}}|
\]

\[\overrightarrow{v_{rot\bot}}=\overrightarrow{a}+\overrightarrow{b}=\overrightarrow{w}·\sin \left( \theta \right) +\overrightarrow{v_{\bot}}·\cos \left( \theta \right) =\sin \left( \theta \right) ·\left( \overrightarrow{k}×\overrightarrow{v} \right) +\cos \left( \theta \right) \left( \overrightarrow{v}-\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} \right)
\\
\overrightarrow{v_{rot}}=\overrightarrow{v_{||}}+\overrightarrow{v_{rot\bot}}=\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k}+\sin \left( \theta \right) ·\left( \overrightarrow{k}×\overrightarrow{v} \right) +\cos \left( \theta \right) \left( \overrightarrow{v}-\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} \right)
\\
=\cos \left( \theta \right) \overrightarrow{v}+\left( 1-\cos \left( \theta \right) \left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k} \right) +\sin \left( \theta \right) ·\left( \overrightarrow{k}×\overrightarrow{v} \right)
\]

\(
\overrightarrow{k}
\)
\(
\overrightarrow{v}
\)
分别写为列向量

\[\overrightarrow{k}=\left( \begin{array}{c}
k_x\\
k_y\\
k_z\\
\end{array} \right)
\]

\[\overrightarrow{v}=\left( \begin{array}{c}
v_x\\
v_y\\
v_z\\
\end{array} \right)
\]

\(
\overrightarrow{v_{rot}}=R·\overrightarrow{v}
\)

两个式子

\[\left( \overrightarrow{v}·\overrightarrow{k} \right) \overrightarrow{k}=\overrightarrow{k}\left( \overrightarrow{v}·\overrightarrow{k} \right) =\overrightarrow{k}\left( \overrightarrow{k^T}·\overrightarrow{v} \right)
\]

\[\overrightarrow{k}×\overrightarrow{v}=\left[ \begin{array}{c}
k_yv_z-k_zv_y\\
k_zv_x-k_xv_z\\
k_xv_y-k_yv_x\\
\end{array} \right] =\left[ \begin{matrix}
0& -k_z& k_y\\
k_z& 0& -k_x\\
-k_y& k_x& 0\\
\end{matrix} \right] \left[ \begin{array}{c}
v_x\\
v_y\\
v_z\\
\end{array} \right]
\]

结合以上两个式子可得,其中\(I\)为3×3的单位矩阵

\[R=I\cos \left( \theta \right) +\left( 1-\cos \left( \theta \right) \right) \left( \begin{array}{c}
k_x\\
k_y\\
k_z\\
\end{array} \right) \left( \begin{matrix}
k_x& k_y& k_z\\
\end{matrix} \right) +\sin \left( \theta \right) \left( \begin{matrix}
0& -k_z& k_y\\
k_z& 0& -k_x\\
-k_y& k_x& 0\\
\end{matrix} \right) \,\,
\]

以下是比较通用的表示方式

\[R\left( n,\alpha \right) =\cos \left( \alpha \right) I+\left( 1-\cos \left( \alpha \right) \right) nn^T+\sin \left( \alpha \right) \left( \begin{matrix}
0& -n_z& n_y\\
n_z& 0& -n_x\\
-n_y& n_x& 0\\
\end{matrix} \right)
\]

部分引用的博文

//blog.csdn.net/unclerunning/article/details/70948696#齐次坐标系与平移

//zhuanlan.zhihu.com/p/45757899