概述
方法來自於《3D數學基礎,圖形與遊戲開發》這本書。
學習這些轉換可以加深自己對這些知識點的理解~兩兩轉換一共有六種情況,下面就依次列舉一下這六種情況。
1.從歐拉角轉換到矩陣
這種情況的轉換不難,還記得我們的旋轉矩陣長啥樣嗎,歐拉角的三個值就是座標系繞着特定軸旋轉的值,注意是座標系旋轉哦,點的旋轉值是和座標系的旋轉值相反的,需要把旋轉矩陣的角度取反。
比如下面就是繞y軸的旋轉矩陣,角度h取反了,
[ c o s ( − h ) 0 − s i n ( − h ) 0 1 0 s i n ( − h ) 0 c o s ( − h ) ] \begin{bmatrix}
cos(-h)&0&-sin(-h)\\
0&1&0\\
sin(-h)&0&cos(-h)\\
\end{bmatrix} ⎣ ⎡ c o s ( − h ) 0 s i n ( − h ) 0 1 0 − s i n ( − h ) 0 c o s ( − h ) ⎦ ⎤
我們根據特定的順序把三個旋轉矩陣乘起來就行了,很簡單的。
書上是先繞y軸旋轉再繞x軸旋轉,再繞z軸旋轉,得到的結果爲:
[ c o s h c o s b + s i n h s i n p s i n b − c o s h s i n b + s i n h s i n p c o s b s i n h c o s p s i n b c o s p c o s b c o s p − s i n p − s i n h c o s b + c o s h s i n p s i n b s i n b s i n h + c o s h s i n p c o s b c o s h c o s p ] \begin{bmatrix}
coshcosb+sinhsinpsinb&-coshsinb+sinhsinpcosb&sinhcosp\\
sinbcosp&cosbcosp&-sinp\\
-sinhcosb+coshsinpsinb&sinbsinh+coshsinpcosb&coshcosp\\
\end{bmatrix} ⎣ ⎡ c o s h c o s b + s i n h s i n p s i n b s i n b c o s p − s i n h c o s b + c o s h s i n p s i n b − c o s h s i n b + s i n h s i n p c o s b c o s b c o s p s i n b s i n h + c o s h s i n p c o s b s i n h c o s p − s i n p c o s h c o s p ⎦ ⎤
這個旋轉矩陣是從慣性座標系旋轉到物體座標系的旋轉矩陣。h爲繞y軸的旋轉角度,p爲繞x軸的旋轉角度,b爲繞z軸的旋轉角度。
2.從旋轉矩陣到歐拉角
當我們知道了從歐拉角到旋轉矩陣的矩陣形式,倒推是一件非常簡單的事情,假設上面的矩陣爲M,則M23 = -sinp,我們能直接得到繞x軸的旋轉角度p,然後把M21/M22能直接得到tanb,所以也能得到繞z的旋轉角度b,把M13/M33也能直接得到tanh,然後就能得到角度h,於是這一切問題都解決了,是不是很容易。
3.從四元數轉換到旋轉矩陣
[ n x 2 ( 1 − c o s θ ) + c o s θ n x n y ( 1 − c o s θ ) + n z s i n θ n x n z ( 1 − c o s θ ) − n y s i n θ n x n y ( 1 − c o s θ ) − n z s i n θ n y 2 ( 1 − c o s θ ) + c o s θ n y n z ( 1 − c o s θ ) + n x s i n θ n x n z ( 1 − c o s θ ) + n y s i n θ n y n z ( 1 − 0 c o s θ ) − n x s i n θ n x 2 ( 1 − c o s θ ) + c o s θ ] \begin{bmatrix}
n_x^2(1-cos\theta)+cos\theta & n_xn_y(1-cos\theta)+n_zsin\theta&n_xn_z(1-cos\theta)-n_ysin\theta\\
n_xn_y(1-cos\theta)-n_zsin\theta&n_y^2(1-cos\theta)+cos\theta&n_yn_z(1-cos\theta)+n_xsin_\theta\\
n_xn_z(1-cos\theta)+n_ysin\theta&n_yn_z(1-0cos\theta)-n_xsin\theta&n_x^2(1-cos\theta)+cos\theta
\end{bmatrix} ⎣ ⎡ n x 2 ( 1 − c o s θ ) + c o s θ n x n y ( 1 − c o s θ ) − n z s i n θ n x n z ( 1 − c o s θ ) + n y s i n θ n x n y ( 1 − c o s θ ) + n z s i n θ n y 2 ( 1 − c o s θ ) + c o s θ n y n z ( 1 − 0 c o s θ ) − n x s i n θ n x n z ( 1 − c o s θ ) − n y s i n θ n y n z ( 1 − c o s θ ) + n x s i n θ n x 2 ( 1 − c o s θ ) + c o s θ ⎦ ⎤
這個東西就是我們繞任意軸n旋轉θ \theta θ 的旋轉矩陣,具體的推導我有單獨介紹過。
然後我們想一下四元數的概念,其四個分量分別是
w = c o s ( θ / 2 ) w = cos(\theta/2) w = c o s ( θ / 2 )
x = n x s i n ( θ / 2 ) x = n_xsin(\theta/2) x = n x s i n ( θ / 2 )
y = n y s i n ( θ / 2 ) y = n_ysin(\theta/2) y = n y s i n ( θ / 2 )
z = n z s i n ( θ / 2 ) z = n_zsin(\theta/2) z = n z s i n ( θ / 2 )
我們所需要做的事情,僅僅是把上面的矩陣用x,y,z,w替換一下就行了,利用倍角公式
c o s 2 α = 1 − s i n 2 α cos2\alpha = 1-sin^2\alpha c o s 2 α = 1 − s i n 2 α
可以做到這一點,具體的計算過程我不寫了,寫起來一大串,知道方法即可。
最後得到的結果如下所示:
[ 1 − 2 y 2 − 2 z 2 2 x y + 2 w z 2 x z − 2 w y 2 x y − 2 w z 1 − 2 x 2 − 2 z 2 2 y z + 2 w x 2 x z + 2 w y 2 y z − 2 w x 1 − 2 x 2 − 2 y 2 ] \begin{bmatrix}
1-2y^2-2z^2&2xy+2wz&2xz-2wy\\
2xy-2wz&1-2x^2-2z^2&2yz+2wx\\
2xz+2wy&2yz-2wx&1-2x^2-2y^2\\
\end{bmatrix} ⎣ ⎡ 1 − 2 y 2 − 2 z 2 2 x y − 2 w z 2 x z + 2 w y 2 x y + 2 w z 1 − 2 x 2 − 2 z 2 2 y z − 2 w x 2 x z − 2 w y 2 y z + 2 w x 1 − 2 x 2 − 2 y 2 ⎦ ⎤
4.從旋轉矩陣到四元數
同旋轉矩陣到歐拉角一樣,我們需要從矩陣本身來逆推一下,計算原理本身不難,我們設旋轉矩陣爲M,則有
M 11 + M 22 + M 33 = 4 w 2 − 1 M11+M22+M33=4w^2-1 M 1 1 + M 2 2 + M 3 3 = 4 w 2 − 1
M 11 − M 22 − M 33 = 4 x 2 − 1 M11-M22-M33=4x^2-1 M 1 1 − M 2 2 − M 3 3 = 4 x 2 − 1
− M 11 + M 22 − M 33 = 4 y 2 − 1 -M11+M22-M33=4y^2-1 − M 1 1 + M 2 2 − M 3 3 = 4 y 2 − 1
− M 11 − M 22 + M 33 = 4 z 2 − 1 -M11-M22+M33=4z^2-1 − M 1 1 − M 2 2 + M 3 3 = 4 z 2 − 1
這樣xyzw我們都可以計算出來,但是我們可以同時得到xyzw互爲相反的兩個跟,而且我們沒有判斷根是否正確的依據,因對對於四元數來說,所有元素取反得到的結果是一樣的,因爲相當於θ \theta θ 加上了一個360°,我們對矩陣進行處理,得到另一種方法:
M12+M21 = 4xy
M12-M21 = 4wz
M31+M13 = 4xz
M31- M13 = 4wy
M23 + M32 = 4yz
M23 - M32 = 4wx
這種積的運算可以保留符號信息,所以我們只需要根據上面的式子計算出任意一個變量,然後通過下面的式子就可以得到所有的值,那麼選擇先計算哪一個變量呢,書中建議是計算出xyzw的平方值,然後選一個最大的來通過下面的式子來計算出其餘的量。
5.從歐拉角到四元數
這個得要從四元數的定義下手,繞着n軸旋轉θ \theta θ 的四元數如下:
q = [ c o s ( θ / 2 ) ( ( s i n ( θ / 2 ) n x ) ( s i n ( θ / 2 ) n y ) ( s i n ( θ / 2 ) n z ) ) q = [cos(\theta/2) ((sin(\theta/2)n_x) (sin(\theta/2)n_y) (sin(\theta/2)n_z)) q = [ c o s ( θ / 2 ) ( ( s i n ( θ / 2 ) n x ) ( s i n ( θ / 2 ) n y ) ( s i n ( θ / 2 ) n z ) )
那麼我們很容易就能把歐拉角的三個旋轉轉化爲四元數,記住旋轉角度要取反,因爲歐拉角是座標軸的旋轉,點的旋轉和座標軸的旋轉是相反的。
繞y軸
h = [ c o s ( − h / 2 ) ( 0 s i n ( − h / 2 ) 0 ) ] h = [cos(-h/2) (0 sin(-h/2) 0)] h = [ c o s ( − h / 2 ) ( 0 s i n ( − h / 2 ) 0 ) ]
繞x軸
p = [ c o s ( − p / 2 ) ( s i n ( − p / 2 ) 00 ) ] p = [cos(-p/2) (sin(-p/2)0 0)] p = [ c o s ( − p / 2 ) ( s i n ( − p / 2 ) 0 0 ) ]
繞z軸
b = [ c o s ( − b / 2 ) ( 00 s i n ( − b / 2 ) ) ] b = [cos(-b/2) (00sin(-b/2))] b = [ c o s ( − b / 2 ) ( 0 0 s i n ( − b / 2 ) ) ]
根據四元組的乘法公式
[ w 1 [ x 1 y 1 z 1 ] ] ∗ [ w 2 [ x 2 y 2 z 2 ] ] = [ w 1 w 2 x 1 x 2 − y 1 y 2 − z 1 z 2 [ w 1 x 2 + x 1 w 2 + z 1 y 2 − y 1 z 2 w 1 y 2 + y 1 w 2 + x 1 z 2 − z 1 x 2 w 1 z 2 + z 1 w 2 + y 1 x 2 − x 1 y 2 ] ] \begin{bmatrix}w1\\\begin{bmatrix}x_1\\y_1\\z_1\\\end{bmatrix}\end{bmatrix}*
\begin{bmatrix}w2\\\begin{bmatrix}x_2\\y_2\\z_2\\\end{bmatrix}\end{bmatrix}=\begin{bmatrix}w_1w_2x_1x_2-y_1y_2-z_1z_2\\\begin{bmatrix}w_1x_2+x_1w_2+z_1y_2-y_1z_2\\w_1y_2+y_1w_2+x_1z_2-z_1x_2\\w_1z_2+z_1w_2+y_1x_2-x_1y_2\\\end{bmatrix}\end{bmatrix} ⎣ ⎢ ⎢ ⎡ w 1 ⎣ ⎡ x 1 y 1 z 1 ⎦ ⎤ ⎦ ⎥ ⎥ ⎤ ∗ ⎣ ⎢ ⎢ ⎡ w 2 ⎣ ⎡ x 2 y 2 z 2 ⎦ ⎤ ⎦ ⎥ ⎥ ⎤ = ⎣ ⎢ ⎢ ⎡ w 1 w 2 x 1 x 2 − y 1 y 2 − z 1 z 2 ⎣ ⎡ w 1 x 2 + x 1 w 2 + z 1 y 2 − y 1 z 2 w 1 y 2 + y 1 w 2 + x 1 z 2 − z 1 x 2 w 1 z 2 + z 1 w 2 + y 1 x 2 − x 1 y 2 ⎦ ⎤ ⎦ ⎥ ⎥ ⎤
依次把三個四元組相乘,就能得到最後的結果了,結果爲:
h q b = [ c o s ( h / 2 ) c o s ( p / 2 ) c o s ( b / 2 ) + s i n ( h / 2 ) s i n ( p / 2 ) s i n ( b / 2 ) [ c o s ( h / 2 ) s i n ( p / 2 ) c o s ( b / 2 ) + s i n ( h / 2 ) c o s ( p / 2 ) s i n ( b / 2 ) s i n ( h / 2 ) c o s ( p / 2 ) c o s ( b / 2 ) − c o s ( h / 2 ) s i n ( p / 2 ) s i n ( b / 2 ) c o s ( h / 2 ) c o s ( p / 2 ) s i n ( b / 2 ) − s i n ( h / 2 ) s i n ( p / 2 ) c o s ( b / 2 ) ] ] hqb=\begin{bmatrix}cos(h/2)cos(p/2)cos(b/2)+sin(h/2)sin(p/2)sin(b/2)\\
\begin{bmatrix}cos(h/2)sin(p/2)cos(b/2)+sin(h/2)cos(p/2)sin(b/2)\\sin(h/2)cos(p/2)cos(b/2)-cos(h/2)sin(p/2)sin(b/2)\\cos(h/2)cos(p/2)sin(b/2)-sin(h/2)sin(p/2)cos(b/2)\\\end{bmatrix}
\end{bmatrix} h q b = ⎣ ⎢ ⎢ ⎡ c o s ( h / 2 ) c o s ( p / 2 ) c o s ( b / 2 ) + s i n ( h / 2 ) s i n ( p / 2 ) s i n ( b / 2 ) ⎣ ⎡ c o s ( h / 2 ) s i n ( p / 2 ) c o s ( b / 2 ) + s i n ( h / 2 ) c o s ( p / 2 ) s i n ( b / 2 ) s i n ( h / 2 ) c o s ( p / 2 ) c o s ( b / 2 ) − c o s ( h / 2 ) s i n ( p / 2 ) s i n ( b / 2 ) c o s ( h / 2 ) c o s ( p / 2 ) s i n ( b / 2 ) − s i n ( h / 2 ) s i n ( p / 2 ) c o s ( b / 2 ) ⎦ ⎤ ⎦ ⎥ ⎥ ⎤
6.從四元數到歐拉角
這個變換我們可以利用旋轉矩陣作爲中間變量,我們知道旋轉矩陣如何表示歐拉角,
p = arcsin(-m23)
h = arctan(m13/m33) cosp!=0
h = arctan(-m31/m11)cosp=0
b = arctan(m13/m33) cosp!=0
b = 0 cosp=0
然而這裏涉及到的矩陣的所有的值都可以用四元數表示出來,參考從四元數到旋轉矩陣的公式,然後只需要代入到上面的公式就行了,結果如下所示:
p = arcsin(-2(yz+wx))
h = arctan(xz-wy/(1/2-x2-y 2)) cosp!=0
h = arctan(-xz-wy/(1/2-y2-z 2)) cosp=0
b = arctan(xy-wz/(1/2-x2-z 2)) cosp!=0
b=0 cosp = 0