3D應用開發中的歐拉角和旋轉矩陣

原文連接前端

做者:天瑜web

前言

在二維平面內,咱們用(x, y)來表示點的位置,經過向座標原始值累加偏移值便可將點移動。但在三維空間內除了位置偏移外,還存在着旋轉變化,所以空間內的每一個物體都具備至少兩個基礎特性:位置和方向。位置咱們能夠用座標來表達,那麼方向由什麼概念來表達呢?api

1.歐拉角(Euler Angles)

三維空間中物體的旋轉變化,能夠映射爲座標系的方向變化。換言之,咱們去旋轉一個空間內的物體,能夠將其轉化爲旋轉座標系。所謂一圖勝千言,直接看下圖:函數

咱們儘可能用簡明意賅的語言來描述圖片所傳達出來的信息。圖中有兩個三維座標系,一個藍色(xyz),另外一個是紅色(XYZ)。首先,咱們先將藍色座標系沿z軸旋轉α角度,再將藍色座標系沿新的x軸旋轉β角度,最後將藍色座標系沿新Z軸旋轉γ角度,就獲得新的紅色座標系(XYZ)。若是將三次變換所圍繞軸和角度記錄下來,那麼本次旋轉的歐拉角爲(z-x-z)-(α, β, γ)。對三種旋轉軸順序進行排列組合後,咱們總結共有12種旋轉順序組合,也就是十二種歐拉角。post

對於某些簡單的旋轉方式,好比先繞x軸旋轉90度,再繞y軸旋轉90度,最後繞x軸旋轉-90度,獲得的結果與直接圍繞z軸旋轉-90度結果相同。也就是說實現一個三維旋轉不必定非要圍繞xyz三個軸每一個軸都旋轉一次。所以能夠對十二種歐拉角作以下分類:學習

  • 經典歐拉角:(z-x-z,x-y-x,y-z-y,z-y-z, x-z-x,y-x-y)
  • 泰特-布萊恩角:(x-y-z,y-z-x,z-x-y,x-z-y,z-y-x,y-x-z)

旋轉軸順序形如ABA的經典歐拉角適用於相對簡單的旋轉場景,而須要三個旋轉軸的泰布萊恩角更多應用於複雜的旋轉場景,好比航空航天領域。google

2.旋轉矩陣(Rotation Matrix)

線性代數中的矩陣不一樣於咱們熟悉的形如y = ax + b的數學關係式,很容易被"古怪"的概念和各類"方框"搞的暈頭轉向。正由於矩陣不一樣於傳統具體的數學關係式,在學習和理解矩陣須要轉換思考方式。好比,咱們能夠用具體公式來描述曲線,像貝塞爾曲線、三角函數曲線,但他們都是基於二維平面的,如何用數學來描述線性三維空間內的變換呢?矩陣所以應運而生。.net

回到本文主題,旋轉順序和角度咱們能夠用歐拉角來表示,那麼如何將其實際應用呢?答案是用旋轉矩陣來表示旋轉角。之前文座標系轉換爲例,抽象出矩陣關係式:3d

依據矩陣除法求得M的值,便可獲得旋轉矩陣。在實際推導三維旋轉矩陣以前,咱們首先推導二維旋轉矩陣,有助於咱們更好的理解三維旋轉矩陣:code

原始向量op圍繞o點旋轉φ角度,原座標(x, y)變爲(x', y'),由圖中標註可得:

由三角函數關係式可得:

依據矩陣乘法法則,以上關係式用矩陣表示爲:

三維變換就是比二維變換多了一個z軸罷了,當空間內的物體圍繞x軸旋轉時,咱們能夠理解爲在yz平面進行二維變換。實際推導過程與上式相似,只是x座標保持不變:

得出圍繞x軸的旋轉矩陣爲:

同理,當空間內的物體圍繞y軸和z軸旋轉時,記圍繞xyz三軸的旋轉角分別爲θβγ(即歐拉角),矩陣分別爲PMQ,有:



3.萬向節死鎖(Gimbal lock)

使用歐拉角來描述三維方向變化並非完美的,很經典的例子就是炮臺問題:

假設地面上有一個炮臺,它能夠與地面平行的360度環繞,圍繞軸記爲x軸,與地面垂直,也能夠俯仰(仰視90度或俯視-90度),俯仰旋轉時所圍繞的軸記爲y軸,與地面平行。正北地平線方向記作x=0, y=0。此時一個飛行器從正東x=90 y=10方向向炮臺飛來,炮口跟蹤瞄準了該飛行器。當飛行器飛到炮臺頭頂時,飛行器的座標(同時也是炮口的指向)也從x=90 y=10逐漸遞增到了x=90 y=90。忽然飛行器向南飛行,但此時炮口垂直地面,不管如何旋轉x軸炮口始終指向天頂。從數據的角度說,從正東的x=90x=180發生了不連續突變,然而飛行器的位置倒是連續的。

究其根本緣由,歐拉角的理論基礎是分別計算圍繞xyz三軸旋轉角度後合併而成的,多種旋轉方式的結果會對應同一個三維空間角度,致使在插值場景中使用歐拉角會出現不連續的死鎖問題(如上文的大炮跟蹤)。死鎖問題與解決在3D空間軌跡跟蹤等領域有普遍的應用,更多例子有興趣的讀者能夠自行google。

如何解決死鎖問題呢?答案是四元數。核心理念就是擺脫對圍繞xyz旋轉計算的依賴,空間內的旋轉基於圍繞任意軸計算,好比圍繞(0, 4, 7)軸。不過四元數就是另外一個複雜的話題了。

4.前端應用

在前端應用層,並不是只有旋轉這一種場景,除了旋轉,還有平移、縮放等等。在上文中咱們使用三階矩陣來表達變換,但在更復雜的變換場景中一般使用四階矩陣來作計算,例如設平移距離分別爲TxTyTz,那麼獲得平移四階矩陣:

三階矩陣的運算已經很繁瑣,四階更讓人頭皮發麻。萬幸的是矩陣計算早已工程化了,沒必要手工操做底層矩陣運算。以表明性的 three.js 爲例,它有不少封裝成熟的 api 可供使用,大大下降了開發前端3D應用的成本。還有函數庫glmatrix,開發者只關心輸入輸出便可。

瞭解歐拉角和矩陣變換隨便只是開發3D應用的第一步,更寬廣的世界依然須要咱們不懈探索。

相關文章
相關標籤/搜索