Matrix and Transform Conversion 2/3

Matrix and Transform Conversion 2/3

來自專欄 Graphics & Homo Ludens

目前市面上存在大大小小的引擎也不少,一般來說引擎所使用的模型動畫資源大抵是可以互相通用,主要的原因在於工業流程的統一(Max,Maya或兩者導出的FBX)。但這並非一定,比如引擎A有一些資源,現在需要扔給引擎B,直接用可能會有問題,因為兩者的坐標定義也許並非相同。所以如何將引擎之間的資源格式統一是本文所要解決的問題。資源格式的統一很大程度上取決於Transform的統一(可以類比Unity,每創建一個空的GameObject,可以看到都會有一個默認的Transform組件)。

前文鏈接

楊智為:Matrix and Transform Conversion 1/3?

zhuanlan.zhihu.com圖標

註:文中所涉及的定義概念名稱僅個人方便理解所制定,理解其背後的含義即可。另,本文均以行矩陣向量左乘為例。

基本原理

Transform是什麼,簡單來說可理解為子空間在父空間的表達,從數據結構來說就是包含縮放,平移和旋轉的矩陣。如下圖,子空間 a 在父空間 ap 的映射關係就是一個Transform(紅色箭頭標記)。

不同坐標定義下的四個坐標系

圖中顯示了四個坐標系:

  • 左邊坐標定義alpha下有兩個空間,子空間 a 和父空間 ap
  • 右邊坐標定義eta 下有兩個空間,子空間 b 和父空間 bp

假設空間 a 在空間 ap 的映射關係,與空間 b 在空間 bp的映射關係是等價的,也就是同一Transform在不同坐標定義下的表達。下面我們嘗試推導一下四個坐標系之間的關係:

已知空間a存在向量 v_a ,那麼可以通過空間 a 在空間 ap的映射關係得

v_{ap}=v_a cdot T_{a2ap}

其中 v_{ap} 表示向量 v_a 在空間 ap 中的表達。同樣,可通過坐標定義變換(後文詳述)得

v_b = v_a cdot M_{a2b}

其中 M_{a2b} 表示坐標定義變換,並不同於Transform。進一步,可通過空間 b 在空間 bp的映射關係得

v_{bp}=v_{a} cdot M_{a2b} cdot T_{b2bp}

或者

v_{bp}=v_{a} cdot T_{a2ap} cdot M_{ap2bp}

其中  M_{ap2bp}M_{a2b} 是不同的,但對於一些特定情況是相等的(比如圖中左邊所有坐標係為同一坐標定義,而右邊所有坐標係為同一坐標定義,坐標定義的變換關係一定是唯一的,這這種情況也比較常見),我們可以用 M_c 進行替代。

綜合上述所有的公式,我們可以得到Transform在兩種坐標定義下的變換公式:

T_{b2bp}=M_{b2a} cdot T_{a2ap} cdot M_{ap2bp}={M_c}^{-1} cdot T_{a2ap} cdot M_c

坐標定義變換的求解

一般情況下 T_{a2ap} 是已知的,而 T_{b2bp} 是我們最終需要求解的目標,所以只要得到M_c的值即可。

坐標定義也可看作笛卡爾坐標系,並使用矩陣表達。本文統一用行矩陣為例,第一行為x軸,第二行為y軸,第三行為z軸。比如單位陣就可以看作是由 x=[1,0,0]y=[0,1,0]z=[0,0,1] 組成的坐標系。通過對矩陣增加語義,可方便地描述各類坐標系。

令為y向上,x向左,z向外的左手坐標系left[ egin {matrix} 1 & 0 & 0 \ 0 & 1 & 0 \ 0 & 0 & 1 end {matrix} 
ight],則

y向上,x向右,z向里( x=-xy=yz=-z )的左手坐標系矩陣為

left[ egin {matrix} -1 & 0 & 0 \ 0 & 1 & 0 \ 0 & 0 & -1 end {matrix} 
ight]

z向下,x向右,y向里(x=-xy=-zz=-y)。的左手坐標系矩陣為

left[ egin {matrix} -1 & 0 & 0 \ 0 & 0 & -1 \ 0 & -1 & 0 end {matrix} 
ight]

令兩個坐標系分為 M_aM_b ,那麼

M_{a2b}=M_a cdot {M_b}^{-1}

其中 M_{a2b} 為坐標系 a 到坐標系 b 的變換關係。

坐標定義的公式已經推導完成,下面開始介紹坐標定義之間的變換求解。舉個具體的例子,下圖左為z向下,x向右,y向里的左手坐標定義 alpha ,下圖右為y向上,x向右,z向里的左手坐標定義 eta

前文已給出坐標定義alpha =left[ egin {matrix} -1 & 0 & 0 \ 0 & 0 & -1 \ 0 & -1 & 0 end {matrix} 
ight],坐標定義eta=left[ egin {matrix} -1 & 0 & 0 \ 0 & 1 & 0 \ 0 & 0 & -1 end {matrix} 
ight] ,根據公式可得

M_{alpha2eta}=M_alpha cdot {M_eta}^{-1}=left[ egin {matrix} -1 & 0 & 0 \ 0 & 0 & -1 \ 0 & -1 & 0 end {matrix} 
ight] 	imes left[ egin {matrix} -1 & 0 & 0 \ 0 & 1 & 0 \ 0 & 0 & -1 end {matrix} 
ight]=left[ egin {matrix} 1 & 0 & 0 \ 0 & 0 & 1 \ 0 & -1 & 0 end {matrix} 
ight]

熟悉旋轉矩陣的朋友應該已經可以看出來 ,該矩陣本質是在左手坐標系下繞x軸順時針旋轉90度的矩陣(從+軸方向看),具體如下

M_{alpha2eta}=left[ egin {matrix} 1 & 0 & 0 \ 0 & cos(90) = 0 & sin(90) = 1\ 0 & -sin(90) = -1& cos(90) = 0end {matrix} 
ight] =left[ egin {matrix} 1 & 0 & 0 \ 0 & 0 & 1 \ 0 & -1 & 0 end {matrix} 
ight]

對比圖例完全吻合,這裡就完全介紹完了變換矩陣M_c 的求解。

Transform變換

基本原理已經分析了Transform變換公式,這裡就針對上一節的具體例子(坐標定義 alpha 和坐標定義 eta )進行分析。

Transform從坐標定義alpha向坐標定義eta進行變換,最終希望得到變換前後狀態均相同(朝向、姿態等)的結果,如下圖所示。

轉換前和轉換後的transfrom

其中左邊為坐標定義alpha,右邊為坐標定義eta。紅色標記的部分為Transform,紅色坐標系left{ old x, old y,old z 
ight}為子空間,灰色坐標系left{ old X, old Y, old Z
ight}為父空間,虛線表示Transform的平移分量。

Transform具體的變換過程如下圖,主要有兩個步驟(用紅色箭頭標出),一是子空間坐標定義從坐標定義 alpha 變換到了坐標定義eta,二是父空間坐標定義從坐標定義 alpha 變換到了坐標定義eta

Transform的變換過程

(感謝 @Yang Liuqing 的修改意見,增加備註解釋)

  • 子空間的坐標定義變換:變換對象為子空間的坐標系left{ old x, old y,old z 
ight}。可以理解為Transform左乘坐標定義變換矩陣,具體過程見上圖(左-中)。操作為子空間坐標系繞子空間的x軸逆時針旋轉90度,該操作以父空間作為參考系,灰色坐標系的方向和位置保持不變。
  • 父空間的坐標定義變換:變換想像為空間的坐標系left{ old x, old y,old z 
ight}和平移分量。可以理解為Transform右乘坐標定義變換矩陣,具體結果見上圖(中-右)。操作為父空間坐標系繞父空間的x軸逆時針旋轉90度,該操作以子空間作為參考系,紅色坐標系的方向和位置保持不變。

可以看到,雖然父子空間均是繞各自的x軸逆時針旋轉90度(左手系,正軸方向看)。但這兩個矩陣正好是互逆的(參考上一篇文章《Matrix and Transform Conversion 1/3》,文章的結論是這個),所以前者正好可以表示為 {M_c}^{-1} ,而後者表示為 M_c ,其中M_c為在左手坐標系下繞x軸順時針旋轉90度的矩陣,也就是前文求的 left[ egin {matrix} 1 & 0 & 0 \ 0 & 0 & 1 \ 0 & -1 & 0 end {matrix} 
ight]

備註:

  1. 父空間變換與子空間變換的參考系是不同的
  2. 父空間變換可以父空間自身為參考系,也可以子空間為參考系(互為等價,參考下圖)

解釋父空間的坐標定義變換具體幾何含義

圖片不夠清晰,可翻閱上一篇文章。這裡觀察所有紅框選中的灰色坐標系,可見前兩幅圖中父空間(灰色部分)保持不變,該行為可等效為矩陣乘法

left( T_{child} cdot M_c 
ight) cdot T_{parent}

其中 M_c 影響子空間整體(橙色部分整體)的朝向。第一幅和第三幅中子空間(橙色部分)保持不變,該行為可等效為矩陣乘法

T_{child} cdot left( M_c cdot T_{parent} 
ight)

其中 M_c 影響父空間中局部坐標系(灰色坐標系)的朝向。從公式即可看出,前後兩種變換是互為等價的。

最後可以推導出該例下Transform的轉換公式:

T_{b2bp}=left[ egin {matrix} 1 & 0 & 0 \ 0 & 0 & -1 \ 0 & 1 & 0 end {matrix} 
ight] cdot T_{a2ap} cdot left[ egin {matrix} 1 & 0 & 0 \ 0 & 0 & 1 \ 0 & -1 & 0 end {matrix} 
ight]

綜上,結論如下:

  1. 區分Transform,坐標系,坐標定義,同一引擎下應確定唯一的坐標定義。
  2. 區分靜態量(Transform, 4	imes44	imes3 )與動態量(坐標定義變換, 3	imes3 )。

先寫到這,還有一篇詳述鏡像的原理。


推薦閱讀:

gal2mat:將gal權重文件轉成n-by-n矩陣
矩陣和向量求導
語料庫語言學基礎知識:矩陣(Haskell版)
矩陣論筆記(2)

TAG:遊戲引擎 | 矩陣 | 計算機圖形學 |