回顧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