3d變換基礎:平移、旋轉、縮放(仿射變換)詳解——公式推導


是時候整理一波3d變換相關的知識了。模型的變換可以認爲是空間中一堆點的變換,三維空間中,(x,y,z)可以認爲是點,也可以認爲是一個向量,因此,人們引入的第4個維度來標識是點還是向量,這個4維空間就叫仿射空間,具體可以參考CV及CG數學基礎:空間,在仿射空間中,(x,y,z,0)標識向量,而(x,y,z,1)表示點。

平移、旋轉、縮放

平移

平移沒什麼好說的,(x,y,z,1)向x,y,z軸分別移動a,b,c單位長度後變成(x+a, y+b, z+c, 1)。寫成矩陣相乘的方式即爲:

[x+ay+bz+c1]=[100a010b001c0001][xyz1]\left[ \begin{matrix} x+a \\ y+b \\ z+c \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} 1 & 0 & 0 & a\\ 0 & 1 & 0 & b \\ 0 & 0 & 1 & c \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]

旋轉

對於旋轉,任何一個旋轉都可以認爲是沿着x,y,z軸分別旋轉 α\alpha, β\beta, γ\gamma 度數,所以選旋轉就先講沿着某個軸向的旋轉。這裏以逆着座標軸正向方向看去的順時針爲旋轉的正向,就是你的視線朝向和座標軸正向是相反的,(⊙o⊙)…我還是畫個圖吧,下圖就是沿着z軸旋轉的正向了哈~

延z軸旋轉的正向

1. 沿x軸旋轉

我畫的!好看嗎?
嗯!這裏推一波公式,其實很簡單,就是三角函數。
如上圖左邊,A點沿着x軸旋轉一定角度變成A’,爲了更容易看,右圖是左圖的左視圖,記旋轉的角度爲θ\theta, 旋轉後得到的A’與旋轉中心連線與y軸正方向的夾角爲α\alpha(圖中的α\alpha是個負值),記A’與旋轉中心連線的長度爲L(A與旋轉中心連線的長度也是L),那麼,顯而易見,有:

x=xy=Lcos(θ+α)z=Lsin(θ+α) \begin{aligned} x' =& x\\ y' =& L·cos(\theta + \alpha)\\ z' =& L·sin(\theta + \alpha) \end{aligned}

y=Lcosαz=Lsinα \begin{aligned} y =& L·cos\alpha\\ z =& L·sin\alpha \end{aligned}
根據三角函數公式可以得到
y=Lcos(αθ)=L(cosαcosθsinαsinθ)=ycosθzsinθz=Lsin(αθ)=L(sinθcosα+cosθsinα)=ysinθ+zcosθ \begin{aligned} y' =& L·cos(\alpha - \theta) = L·(cos\alpha cos\theta - sin\alpha sin\theta) = ycos\theta -zsin\theta\\ z' =& L·sin(\alpha - \theta) = L·(sin\theta cos\alpha + cos\theta sin\alpha ) = ysin\theta + zcos\theta \end{aligned}
綜上,有:
x=xy=ycosθzsinθz=ysinθ+zcosθ \begin{aligned} x' =& x\\ y' =& ycos\theta -zsin\theta\\ z' =&ysin\theta + zcos\theta \end{aligned}
現在就可以寫成漂亮的矩陣形式了:
[xyz1]=[10000cosθsinθ00sinθcosθ00001][xyz1]\left[ \begin{matrix} x' \\ y' \\ z' \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} 1 & 0 & 0 & 0\\ 0 & cos\theta & -sin\theta & 0 \\ 0 & sin\theta & cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]

2. 沿y軸或者z軸旋轉

推了x軸的,其他兩個軸向其實原理都是一樣的。
對於y軸,可以簡單把y軸和x軸對調,也就是公式裏的x,y對調,不過這樣子的話,z軸的方向會反過來,所以再把z相關的加個符號就好了。
公式如下:
y=yx=xcosθ+zsinθz=xsinθ+zcosθ \begin{aligned} y' =& y\\ x' =& xcos\theta +zsin\theta\\ z' =&-xsin\theta +zcos\theta \end{aligned}
寫成漂亮的矩陣形式就是:
[xyz1]=[cosθ0sinθ00100sinθ0cosθ00001][xyz1]\left[ \begin{matrix} x' \\ y' \\ z' \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} cos\theta &0 & sin\theta & 0 \\ 0 & 1 & 0 & 0\\ -sin\theta & 0 & cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]

對於z軸,x,z互換,y置反,直接上公式:
z=zy=ycosθ+xsinθx=ysinθ+xcosθ \begin{aligned} z' =& z\\ y' =& ycos\theta +xsin\theta\\ x' =&-ysin\theta + xcos\theta \end{aligned}
矩陣形式:
[xyz1]=[cosθsinθ00sinθcosθ0000100001][xyz1]\left[ \begin{matrix} x' \\ y' \\ z' \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} cos\theta & -sin\theta&0 & 0 \\ sin\theta & cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]
那一個物體沿着x,y,z 軸分別旋轉α\alpha, β\beta, γ\gamma 度數就把3個矩陣相乘就好了。

[xyz1]=[cosγsinγ00sinγcosγ0000100001][cosβ0sinβ00100sinβ0cosβ00001][10000cosαsinα00sinαcosα00001][xyz1]\left[ \begin{matrix} x' \\ y' \\ z' \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} cos\gamma& -sin\gamma&0 & 0 \\ sin\gamma& cos\gamma& 0 & 0 \\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} cos\beta&0 & sin\beta& 0 \\ 0 & 1 & 0 & 0\\ -sin\beta& 0 & cos\beta& 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} 1 & 0 & 0 & 0\\ 0 & cos\alpha & -sin\alpha & 0 \\ 0 & sin\alpha & cos\alpha & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]
[xyz1]=[cosβcosγsinαsinβcosγsinγcosαsinβcosαcosγ+sinαsinγ0cosβsinγcosαcosγ+sinαsinβsinγsinαcosγ+sinγsinβcosα0sinβsinαcosβcosαcosβ00001][xyz1]\left[ \begin{matrix} x' \\ y' \\ z' \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} cos\beta cos\gamma & sin\alpha sin\beta cos\gamma - sin\gamma cos\alpha & sin\beta cos\alpha cos\gamma +sin\alpha sin\gamma & 0\\ cos\beta sin\gamma & cos\alpha cos\gamma + sin\alpha sin\beta sin\gamma & -sin\alpha cos\gamma + sin\gamma sin\beta cos\alpha & 0 \\ -sin\beta & sin\alpha cos\beta& cos\alpha cos\beta& 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]

縮放

縮放感覺也沒的說,直接上公示,下面公式表示沿着x,y,z軸分別縮放a,b,c倍:
[xyz1]=[a0000b0000c00001][xyz1]\left[ \begin{matrix} x' \\ y' \\ z' \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} a & 0 & 0 & 0\\ 0 & b & 0 & 0 \\ 0 & 0 & c & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ z \\ 1\\ \end{matrix} \right]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章