基於矩陣運算的父約束
來自專欄他是老王15 人贊了文章
"Once you can understand Matrices; I think life in general with CG becomes easier."
作為一名技術美術,無論你是Shading方向,還是Character方向,矩陣運算和線性代數的知識都是你必須掌握的硬技能。在今後的幾篇文章裡面,我會從矩陣出發,介紹一些大家平時可能不太會關注的,但是如果掌握會有益的知識點。
父約束(Parent Constraint)是一個十分常見的概念,他們在效率上要明顯慢於direct attribute connection或者parenting,但是他是唯一可以打破結構上從屬關係的方法。
所以今天的文章要介紹一種基於矩陣運算的父約束,這個方法我認為在效率上是優於Maya自帶的Parent Constraint的,但是由於增加多餘的節點,可能會導致graph editor的冗餘和難於管理。因此對於方法的取捨,完全屬於個人喜好。
- 公式: childWorldMatrix = childLocalMatrix * childParentMatrix
- 公式:childLocalMatrix = childWorldMatrix * childParentMatrix.inverse()
上述的公式計算是在matrixMult節點裡面完成。將父物體的worldMatrix乘以被約束物體的parentInverseMatrix,將其轉至本地矩陣。 最後我們將本地矩陣通過decomposeMatrix分解成變換屬性(Transform)。這就是最基本的基於矩陣的父約束。接下來討論如何保持偏移差。
- 公式: offsetMatrix * initParentWorldMatrix = initChildWorldMatrix
- 公式: offsetMatrix = initChildWorldMatrix * initParentWorldMatrix.inverse()
- 公式: childWorldMatrix = offsetMatrix * parentWorldMatrix
- 公式: childLocalMatrix = offsetMatrix *parentMatrix * childParentMatrix.inverse()
對於增加多餘的節點,我在以後的文章裡面會介紹一種通過特殊的父節點來管理子節點的方法,這在「procedure rigging」裡面被廣泛應用。
代碼如下:
最後我要講一下這個方法在對於骨骼做父約束時存在的一個問題。在Maya的骨骼裡面,jointOrient屬性是一個單獨的矩陣,應用於rotation矩陣之後。
所以要做的就是在我們的矩陣鏈最後乘以jointOrient的逆矩陣。
如上圖,我將jointOrient轉換成四元數,求逆,再和原方法求出的四元數做叉乘。這個方法可以很好解決沒有偏移差時的結果。但是有偏移差時,上述矩陣鏈並不能正常工作。我最終決定自己寫一個Maya節點, 使用MTransformationMatrix類裡面的rotateBy函數,把jointOrient的逆四元數作為參數傳入。
rotateByNode: 直接貼上我gitbub的鏈接,有興趣的朋友可以看看源代碼。注意在歐拉角和四元數的轉換中,旋轉順序也是可以暴露出來的屬性以供選擇,默認是XYZ。這應該是在我的TODO List上。
https://github.com/tenghaowang/Python_Deformer/blob/master/matrixConstraint/rotateByNode.py總結, 使用基於矩陣的父約束,可以完全取代Maya裡面內置的parent,point和orient constraints,並且在效率上更佳。這個方法同時也不局限於Maya里,在任何的DCC工具或者引擎裡面都可以嘗試使用。最關鍵還是希望大家可以理解其背後的矩陣知識:矩陣乘法的意義,矩陣的結合律,逆矩陣的意義等等。然後在未來的文章裡面我會討論如何通過矩陣計算twist distribution,和如何構造rivets。
後記:
@狗狗 在 狗狗:《幾分鐘遊戲開發:Unity的PBR》裡面討論的PBR流程。有興趣的朋友可以關注我的個人網站:Tool Development,裡面介紹了一種基於Substance Designer的PBR 貼圖轉換流程,將傳統的貼圖快速轉換成PBR標準貼圖。
推薦閱讀:
※矩陣和行列的相互轉換-ucinet簡直救我狗命
※tensorflow實現非負矩陣分解(Non-negative matrix factorization)
※從矩陣的角度來看待複數
※大白話講數據結構:矩陣的轉置和矩陣的乘法問題(2) (應該都能看懂的!)