Matrix and Transform Conversion 2/3
來自專欄 Graphics & Homo Ludens
目前市面上存在大大小小的引擎也不少,一般來說引擎所使用的模型動畫資源大抵是可以互相通用,主要的原因在於工業流程的統一(Max,Maya或兩者導出的FBX)。但這並非一定,比如引擎A有一些資源,現在需要扔給引擎B,直接用可能會有問題,因為兩者的坐標定義也許並非相同。所以如何將引擎之間的資源格式統一是本文所要解決的問題。資源格式的統一很大程度上取決於Transform的統一(可以類比Unity,每創建一個空的GameObject,可以看到都會有一個默認的Transform組件)。
前文鏈接
楊智為:Matrix and Transform Conversion 1/3註:文中所涉及的定義概念名稱僅個人方便理解所制定,理解其背後的含義即可。另,本文均以行矩陣向量左乘為例。
基本原理
Transform是什麼,簡單來說可理解為子空間在父空間的表達,從數據結構來說就是包含縮放,平移和旋轉的矩陣。如下圖,子空間 在父空間 的映射關係就是一個Transform(紅色箭頭標記)。
圖中顯示了四個坐標系:
- 左邊坐標定義下有兩個空間,子空間 和父空間
- 右邊坐標定義 下有兩個空間,子空間 和父空間
假設空間 在空間 的映射關係,與空間 在空間 的映射關係是等價的,也就是同一Transform在不同坐標定義下的表達。下面我們嘗試推導一下四個坐標系之間的關係:
已知空間存在向量 ,那麼可以通過空間 在空間 的映射關係得
其中 表示向量 在空間 中的表達。同樣,可通過坐標定義變換(後文詳述)得
其中 表示坐標定義變換,並不同於Transform。進一步,可通過空間 在空間 的映射關係得
或者
其中 和 是不同的,但對於一些特定情況是相等的(比如圖中左邊所有坐標係為同一坐標定義,而右邊所有坐標係為同一坐標定義,坐標定義的變換關係一定是唯一的,這這種情況也比較常見),我們可以用 進行替代。
綜合上述所有的公式,我們可以得到Transform在兩種坐標定義下的變換公式:
坐標定義變換的求解
一般情況下 是已知的,而 是我們最終需要求解的目標,所以只要得到的值即可。
坐標定義也可看作笛卡爾坐標系,並使用矩陣表達。本文統一用行矩陣為例,第一行為x軸,第二行為y軸,第三行為z軸。比如單位陣就可以看作是由 , , 組成的坐標系。通過對矩陣增加語義,可方便地描述各類坐標系。
令為y向上,x向左,z向外的左手坐標系,則
y向上,x向右,z向里( , , )的左手坐標系矩陣為
z向下,x向右,y向里( , , )。的左手坐標系矩陣為
令兩個坐標系分為 和 ,那麼
其中 為坐標系 到坐標系 的變換關係。
坐標定義的公式已經推導完成,下面開始介紹坐標定義之間的變換求解。舉個具體的例子,下圖左為z向下,x向右,y向里的左手坐標定義 ,下圖右為y向上,x向右,z向里的左手坐標定義 。
前文已給出坐標定義,坐標定義 ,根據公式可得
熟悉旋轉矩陣的朋友應該已經可以看出來 ,該矩陣本質是在左手坐標系下繞x軸順時針旋轉90度的矩陣(從+軸方向看),具體如下
對比圖例完全吻合,這裡就完全介紹完了變換矩陣的求解。
Transform變換
基本原理已經分析了Transform變換公式,這裡就針對上一節的具體例子(坐標定義 和坐標定義 )進行分析。
Transform從坐標定義向坐標定義進行變換,最終希望得到變換前後狀態均相同(朝向、姿態等)的結果,如下圖所示。
其中左邊為坐標定義,右邊為坐標定義。紅色標記的部分為Transform,紅色坐標系為子空間,灰色坐標系為父空間,虛線表示Transform的平移分量。
Transform具體的變換過程如下圖,主要有兩個步驟(用紅色箭頭標出),一是子空間坐標定義從坐標定義 變換到了坐標定義,二是父空間坐標定義從坐標定義 變換到了坐標定義。
(感謝 @Yang Liuqing 的修改意見,增加備註解釋)
- 子空間的坐標定義變換:變換對象為子空間的坐標系。可以理解為Transform左乘坐標定義變換矩陣,具體過程見上圖(左-中)。操作為子空間坐標系繞子空間的x軸逆時針旋轉90度,該操作以父空間作為參考系,灰色坐標系的方向和位置保持不變。
- 父空間的坐標定義變換:變換想像為空間的坐標系和平移分量。可以理解為Transform右乘坐標定義變換矩陣,具體結果見上圖(中-右)。操作為父空間坐標系繞父空間的x軸逆時針旋轉90度,該操作以子空間作為參考系,紅色坐標系的方向和位置保持不變。
可以看到,雖然父子空間均是繞各自的x軸逆時針旋轉90度(左手系,正軸方向看)。但這兩個矩陣正好是互逆的(參考上一篇文章《Matrix and Transform Conversion 1/3》,文章的結論是這個),所以前者正好可以表示為 ,而後者表示為 ,其中為在左手坐標系下繞x軸順時針旋轉90度的矩陣,也就是前文求的 。
備註:
- 父空間變換與子空間變換的參考系是不同的
- 父空間變換可以父空間自身為參考系,也可以子空間為參考系(互為等價,參考下圖)
圖片不夠清晰,可翻閱上一篇文章。這裡觀察所有紅框選中的灰色坐標系,可見前兩幅圖中父空間(灰色部分)保持不變,該行為可等效為矩陣乘法
其中 影響子空間整體(橙色部分整體)的朝向。第一幅和第三幅中子空間(橙色部分)保持不變,該行為可等效為矩陣乘法
其中 影響父空間中局部坐標系(灰色坐標系)的朝向。從公式即可看出,前後兩種變換是互為等價的。
最後可以推導出該例下Transform的轉換公式:
綜上,結論如下:
- 區分Transform,坐標系,坐標定義,同一引擎下應確定唯一的坐標定義。
- 區分靜態量(Transform, 或 )與動態量(坐標定義變換, )。
先寫到這,還有一篇詳述鏡像的原理。
推薦閱讀:
※gal2mat:將gal權重文件轉成n-by-n矩陣
※矩陣和向量求導
※語料庫語言學基礎知識:矩陣(Haskell版)
※矩陣論筆記(2)