天天看點

矩陣基礎 2

上一篇矩陣基礎1

Case4

如何使用三根基軸建構矩陣?其實這個問題以前已經讨論過,思路可以看下相機空間矩陣。再次提出,主要是因為上次我沒有在代碼裡測試過,隻是理論,并且這個方法是可以推廣到任意矩陣上,而不隻是局限于相機空間矩陣。這次實際用到了,是以我先在 CSharp 中實作了,相信遷移到 Shader 中也并非難事。一個小技巧是,對于一些比較難調試自己又沒把握的問題,如果可能的話最好先在程式代碼中實作,再遷移到 Shader 中,而不要直接在 Shader 中編寫,因為程式代碼可以很友善的進行調試,快速定位錯誤,而這是 Shader 所做不到的(目前我還沒有發現什麼好的工具)。

矩陣基礎 2

最終的目标是在将世界空間的 Cube 變換到 c1 的局部坐标系下(這是最簡單的情況)。如果直接使用 Unity 提供的接口(worldToLocalMatrix 和 localToWorldMatrix)也是可以做到的。但是這裡我們使用自己的方法。思路就是:從 A 坐标系 變換到 B 坐标系,首先在 A 坐标系下表示出 B 坐标系的三根基軸,然後使用這三根基軸組成變換矩陣(組合方法見這裡) ,得到的這個矩陣就是我們想要的變換矩陣(注意行向量和列向量的差別)。

// 使用三根基軸建構矩陣
// 如果隻是用來變換法線的話,matR就已經夠了,直接做變換操作即可
Matrix4x4 matR = Matrix4x4.identity;
matR.SetRow(0, new Vector4(c1.right.x, c1.right.y, c1.right.z, 0));
matR.SetRow(1, new Vector4(c1.up.x, c1.up.y, c1.up.z, 0));
matR.SetRow(2, new Vector4(c1.forward.x, c1.forward.y, c1.forward.z, 0));
newNormal = matR * new Vector4(normal.x, normal.y, normal.z, 0);

// 位移矩陣
Matrix4x4 matT = Matrix4x4.identity;
matT.SetRow(0, new Vector4(1, 0, 0, -c1.position.x));
matT.SetRow(1, new Vector4(0, 1, 0, -c1.position.y));
matT.SetRow(2, new Vector4(0, 0, 1, -c1.position.z));
// 縮放矩陣
Matrix4x4 matS = Matrix4x4.identity;
matS.SetRow(0, new Vector4(c1.localScale.x, 0, 0, 0));
matS.SetRow(1, new Vector4(0, c1.localScale.y, 0, 0));
matS.SetRow(2, new Vector4(0, 0, c1.localScale.z, 0));
// 如果用來變換頂點,那麼需要同時使用 matR matT matS 這三個矩陣
// 注意相乘的順序是非常重要的,不可颠倒
Matrix4x4 mat = matS * matR * matT;
newPos = mat * new Vector4(pos.x, pos.y, pos.z, 1);           

https://chengkehan.github.io

繼續閱讀