本文首先講解歐拉變換(Euler transform)以及它的參數提取(extraction of parameters)。歐拉變換是描述朝向(orientation)的一個直觀的方法。然後,會講到如何從單個矩陣中提取出一系列變換。最後,講述一個繞任意軸旋轉實體(entity,即點、線、面或者物體)的方法。

1 歐拉變換(The Euler Transform)

歐拉變換是一個直觀的方法,用於構造一個矩陣設置你自己(即照相機camera)或者任何別的實體朝向某個方向。其名字來源於偉大的瑞士數學傢萊昂哈德·歐拉(Leonhard Euler,1707–1783).

首先,某個默認的觀察方向(或者視線方向view direction)需要被確立。它經常是沿著-z軸,使頭部朝向正y軸,如圖4.7所示。這裡可以想像一下右手坐標系,正y軸朝向電腦屏幕正上方,正z軸,從垂直電腦屏幕指向屏幕外,而負z軸指向屏幕裡。也就是默認觀察方向指向屏幕裡。

圖4.7 歐拉變換及其與改變歐拉角head, pitch, roll的關系。默認觀察方向為負z軸,up direction為y軸。

怎麼記住三個歐拉角各自的作用(對應的軸)?

歐拉變換是三個旋轉矩陣的乘積。用 mathbf{E} 表示歐拉變換,則:

mathbf{E}(h,p,r)=mathbf{R}_z(r)mathbf{R}_x(p)mathbf{R}_y(h)tag{4.21}

矩陣的順序多達24種。這裡我們僅展示方程4.21裡的這種,因為它是常為常用。因為 mathbf{E} 是多個旋轉的連接,則它也是一個旋轉矩陣,是正交的。因此它的逆陣可表示為 mathbf{E}^{-1}=mathbf{E}^T=(mathbf{R}_z mathbf{R}_x mathbf{R}_y)^T=mathbf{R}_y^T mathbf{R}_x^T mathbf{R}_z^T

註意歐拉變換不僅可以用於設置照相機的朝向,也可以設置任何物體或實體的朝向。這些變換可以在全局的世界坐標系下完成,也可以在相對於某個物體的局部坐標系完成。

需要註意的是,歐拉角的某些情形下,把z軸作為初始的up direction(即上方向,而我們這裡使用y軸作為up direction)。這種差異僅僅是一個符號改變,但可能會令人困惑。在計算機圖形學中,如何看待世界(the world)和如何排列內容,有一個區分(a division)或者說有兩種方式: y-up或者z-up。大多數生產過程(Most manufacturing processes),包括3D打印,把z-direction作為世界空間(world space)的up方向。航空和海上運輸工具認為−z是up方向。而媒體相關的建模系經常認為y-direction為世界坐系下的up方向,這和圖形學中描述照相機屏幕上方向(a camera's screen up direction)的方式一致。在本文中,我們使用y-up。

這裡需要指出觀察空間(view space)內的照相機的上方向(camera's up direction)和世界空間的上方向(world's up direction)沒有什麼特別的關系。畢竟處於兩個坐標系中。

盡管對於小的角度或者觀察者朝向改變,歐拉角很有用,但它也有一些嚴重的限制。同時結合使用兩個歐拉角集合(tow sets of Euler angles)是困難的。例如,在兩個歐拉角集合間進行插值不是簡單地對兩組集合的三個角度分別進行插值。因為兩個不同的歐拉角集合可能給出相同的朝向,此時任何插值都不會旋轉物體。這些是考慮用四元數(Quaternion)等來代替歐拉角的原因。

2 從歐拉變換中提取參數(Extracting Parameters from the Euler Transform)

有時從一個正交矩陣,即歐拉變換矩陣,提交出歐拉角 h, p, r 是有用的。過程如下:

mathbf{E}(h,p,r)=left( begin{matrix} e_{00} & e_{01} & e_{02}\ e_{10} & e_{11} & e_{12}\ e_{20} & e_{21} & e_{22} end{matrix} right)=mathbf{R}_z(r) mathbf{R}_x(p) mathbf{R}_y(h) tag{4.22}

這裡我們放棄瞭 4times 4 矩陣,代之以 3times 3 矩陣,因為後者提交瞭所有關於旋轉矩陣的必要信息。也就是說,對應的4D矩陣的剩餘部分之是0,其右下角的元素為1。

連接方程4.22中的三個旋轉矩陣,可以得到:

mathbf{E}=left( begin{matrix} cos r cos h − sin r sin p sin h & -sin r cos p & cos r sin h+sin r sin p cos h\ sin r cos h+cos r sin p & sin h cos r & cos p sin r sin h−cos r sin p cos h\ −cos p sin h & sin p & cos p cos h end{matrix} right)tag{4.23}

顯然, sin p = e_{21} ,且有:

frac{e_{01}}{e_{11}}=frac{-sin r}{cos r}=-tan r quad and quad frac{e_{20}}{e_{22}}=frac{-sin h}{cos h}=-tan h. tag{4.24}

因此可解出三個歐拉角分別為:

begin{aligned} h &= atan2(-e_{20}, e_{22}),\ p &= arcsin(e_{21}),\ r &= atan2(-e_{01}, e_{11}) end{aligned} tag{4.25}

有一個特殊的情形需要處理。如果 cos p = 0 ,則會出現萬向節鎖(gimbal lock),旋轉角度 r, h 將會繞相同的軸旋轉(可能方向相反,這取決於 p 的值為 -pi/2 還是 pi/2 ),這樣隻有一個角度( r, h 中的一個)需要推導。如果我們任意地設 h=0 ,則

mathbf{E}=left( begin{matrix} cos r & -sin rcos p & sin rsin p\ sin r & cos rcos p & −cos r sin p\ 0 & sin p & cos p end{matrix} right) tag{4.26}

因為p不影響第一列,所以當cos p = 0時,我們可以使用 sin r/cos r=tan r=e_{10}/e{00} ,可以得到 r=atan2(e_{10}, e_{00})

註意arcsin的定義域為 -pi/2 le p le pi/2 ,這意味著如果 mathbf{E} 創建時包含瞭一個在此定義域范圍外的p,則不能提取出原始參數。

當使用歐拉變換時,萬向節鎖(gimbal lock)可能會出現。當某個旋轉使得三個自由度(對應r, p, h或者說對應x, y, z軸)中的一個消失時,萬向節鎖會出現。例如,變換順序為 x/y/z ,假設第一個旋轉變換為繞y軸旋轉 pi/2 弧度,然後再進行第二個旋轉變換。但第一個旋轉變換已經導致z軸和原始的x軸對齊,這樣最後繞z軸的旋轉就是冗餘(redundant)的瞭。

使用案例: 限制一個變換(Constraining a Transform)

設想你正拿著一個虛擬的扳手,正在擰緊一個螺栓。為瞭使螺栓擰緊,你必須使扳手繞x軸旋轉。現在假設你的輸入設備(鼠標、VR手套、空間球等)給你一個旋轉矩陣,即,一個關於扳手運動的旋轉。問題是對扳手施加這個transform很可能是錯誤的,因為應該隻繞x軸旋轉。為瞭限制輸入變換(the input transform)僅繞x軸旋轉,隻需要用上面的方法提取(extract)出歐拉角 h, p, r ,然後創建一個新的矩陣 mathbf{R}_x(p) ,用它來對扳手進行旋轉變換就行瞭,扳手隻會在x軸旋轉。

3 矩陣分解(Matrix Decomposition)

到目前為止,我們總是假設我們知道當前使用的變換矩陣的原始形態及變化歷史(the origin and history of the transformation matrix)。但通常的情形並不是這樣的。例如,有時我隻有一個由多個變換矩陣相乘得到的最終的矩陣(concatenated matrix),而不知道別的任何信息。從一個concatenated matrix中提取出各種變換的任務被稱為矩陣分解(matrix decomposition)。

有許多原因需要從concatenated matrix中提取各種變換。包括:

  • 提取出一個物體的縮放因子
  • 找到一個特殊系統需要的變換。(例如,有些系統可能不允許使用任意 4times 4 矩陣)
  • 檢測一個模型是否隻經歷瞭剛體變換(only rigid-body transforms)
  • 在一個動畫的關鍵幀之間插值隻對該物體可用的矩陣
  • 從一個旋轉矩陣中移除錯切變換

提取平移矩陣也是簡單直觀的,隻需要原始4times 4變換矩陣的最後一列元素。我們也可以確定是否發生瞭鏡像變換,隻需要檢測矩陣的行列式是否為負。而要剝離出roattion, scaling以及shear,則需要更多的操作。

目前網上已有相關的文章和代碼:

  1. Thomas, Spencer W., “Decomposing a Matrix into Simple Transformations,” in James Arvo, ed., Graphics Gems II, Academic Press, pp. 320–323, 1991. Cited on p. 72, 74
  2. Goldman, Ronald, “Recovering the Data from the Transformation Matrix,” in James Arvo, ed., Graphics Gems II, Academic Press, pp. 324–331, 1991. Cited on p. 74
  3. Goldman, Ronald, “Decomposing Linear and Affine Transformations,” in David Kirk, ed., Graphics Gems III, Academic Press, pp. 108–116, 1992. Cited on p. 74
  4. Sloan, Peter-Pike, Ben Luna, and John Snyder, “Local, Deformable Precomputed Radiance Transfer,” ACM Transactions on Graphics (SIGGRAPH 2005), vol. 24, no. 3, pp. 1216–1224, Aug. 2005. Cited on p. 431, 481

4 繞任意軸旋轉(Rotation about an Arbitrary Axis)

有時能夠使一個實體繞任意旋轉軸旋轉是很有用的。假設旋轉軸 mathbf{r} 是一個歸一化(normalized)的向量,我們要創建一個變換使得物體繞mathbf{r}旋轉 alpha 弧度。

為瞭達到此目的,我們首先需要變換坐標空間,在新的坐標空間中,mathbf{r}為新坐標系的x軸。這一變換需要一個旋轉矩陣 mathbf{M} 完成。然後,在新坐標空間中對物體施加旋轉alpha弧度的變換。最後,利用mathbf{M}的逆陣 mathbf{M}^{-1} 把物體變換到原始的坐標空間。這一過程如圖4.8所示。

圖4.8 繞任意軸旋轉

關鍵的問題是: 怎麼計算 mathbf{M} 呢?

為瞭計算mathbf{M},我們需要找到另外兩個坐標軸 mathbf{s, t} ,使得 mathbf{r, s, t} 相互垂直。我們隻需要專註於如何找到第二個坐標軸 mathbf{s} ,因為找到它之後,隻需要用前兩個的叉積就能計算第三個坐標軸 mathbf{t}=mathbf{r}timesmathbf{s} 。一種數值穩定的方法是找到找到 mathbf{r} 的絕對值最小的分量,將其設置為0,然後交換另外兩個分量的值,再把被交換的兩個分量的值中的第一個值取負(negate. 實際上,把二者中任意非零分量取負都行)。可用數學語言表示為:

begin{equation} overline{mathbf{s}}=left{ begin{aligned} (0, -r_z, r_y), quad ifquad |r_x| le|r_y| quad and quad |r_x| le|r_z|,\ (-r_z, 0, r_x), quad ifquad |r_y| le|r_x| quad and quad |r_y| le|r_z|,\ (-r_y, r_x, 0), quad ifquad |r_z| le|r_y| quad and quad |r_z| le|r_x|, end{aligned} right. end{equation}tag{4.27}

begin{aligned} mathbf{s}&=overline{mathbf{s}}/||overline{mathbf{s}}||, \ mathbf{t}&=mathbf{r}timesmathbf{s}. end{aligned}

這能確保 mathbf{s} 是歸一化的,且與 mathbf{r} 是正交的,使得 (mathbf{r, s, t}) 是一組正交基。則可得:

mathbf{M}=left( begin{matrix} mathbf{r}^T\ mathbf{s}^T\ mathbf{t}^T end{matrix} right)tag{4.28}

因此最終把物體繞歸一化的軸 mathbf{r} 旋轉 alpha 弧度的變換矩陣為:

mathbf{X}=mathbf{M^TR}_x(alpha)mathbf{M}tag{4.29}

總之,就是先通過坐標空間變換把 mathbf{r} 變換成x軸,然後進行alpha弧度旋轉(用 mathbf{R}_x(alpha) ),最後再通過坐標空間變換,回到原始坐標系。

另外一篇文章 四元數和旋轉(Quaternion & rotation)也介紹過一種方法來計算繞任意軸旋轉,它直接給出瞭一個繞任意軸旋轉的矩陣。此處不再單獨說明。那篇文章中也說明瞭用四元數做任意軸旋轉會更新加高效、便捷。

Reference:

  1. Real-Time Rendering 4th 第4.2節
  2. 四元數和旋轉(Quaternion & rotation)