Real-Time-Rendering 矩陣的其他變換及投影矩陣(三)

        接下來我們討論矩陣的平移、投影變換,在計算機圖形學中這兩種變換也及其常用。

一、4x4矩陣

        在討論位移矩陣前,我們需要引出4x4矩陣的相關概念。

        4D向量有4個分量,前三個是標準的x、y、z分量,第四個是w,有時稱爲齊次座標。

        我們可以把齊次座標理解爲更高維度的抽象。比如2D座標系中一個點在2D的擴展座標齊次座標中將有無數的點對應。他的形式爲(x,y,w)。對於不在w=1平面的點,我們可以通過將x、y除以w來將這個點投影到w=1的平面。所以2D座標系中的齊次座標(x,y,w)其實映射的實際2D點爲(x/w,y/w)。3D座標系同理。

        爲什麼引入4x4矩陣,第一個原因是因爲方便的記法,在平移矩陣中將會討論。第二個原因是因爲w的映射性質。

二、平移矩陣

        在上一章中我們討論的都是用3x3矩陣表示的線性變換,不包含平移。因爲矩陣乘法的性質,零向量總是變化成零向量。顯然無法描述分量加、減這樣的平移操作。而4x4矩陣提供了數學上的技巧幫我們做到這一點。

        暫時假設w總是等於1,那麼,標準3D向量[x,y,z]對應的4D向量爲[x,y,z,1]。任意3x3變換矩陣在4D中表示爲:

        \begin{bmatrix} m_{11} & m_{12} &m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} &m_{32} & m_{33} \end{bmatrix} => \begin{bmatrix} m_{11} & m_{12} &m_{13} & 0 \\ m_{21} & m_{22} & m_{23}& 0 \\ m_{31} &m_{32} & m_{33} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

        \begin{bmatrix} m_{11} & m_{12} &m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} &m_{32} & m_{33} \end{bmatrix} \begin{bmatrix} x\\ y\\ z \end{bmatrix} = \begin{bmatrix} xm_{11} + ym_{12} + zm_{13}\\ xm_{21} + ym_{22} + zm_{23}\\ xm_{31} + ym_{32} + zm_{33} \end{bmatrix}

        \begin{bmatrix} m_{11} & m_{12} &m_{13}&0 \\ m_{21} & m_{22} & m_{23} &0\\ m_{31} &m_{32} & m_{33}&0 \\ 0 &0 & 0&1\end{bmatrix} \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} xm_{11} + ym_{12} + zm_{13} + 0 * 1\\ xm_{21} + ym_{22} + zm_{23} + 0 * 1\\ xm_{31} + ym_{32} + zm_{33} + 0 * 1\\ 1 \end{bmatrix}

        可以發現中間的3x3矩陣依然可以代表線性變換改變向量的x、y、z分量,如果我們想屏蔽線性變換隻需中間的3x3方陣改變爲單元矩陣即可。而現在x、y、z分量同時被4x4矩陣的第四列所影響(如果矩陣以行爲主,則是第四行)。只是因爲我們都設爲0,所以他並沒有向量帶來實際變換,但他卻有加減的特性,利用此數學技巧我們可以利用矩陣的第四列實現向量的平移變換。

        \begin{bmatrix} 1 & 0 & 0 & \triangle x\\ 0 & 1 & 0 & \triangle y\\ 0 & 0 & 1 &\triangle z\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} x + \triangle x\\ y + \triangle y\\ z + \triangle z\\ 1 \end{bmatrix}

        當中間的3x3方陣包含一個線性變換時,外面包裹上位移矩陣的第4列,即實現了諸如y = ax + b形式的映射,我們稱其爲仿射變換。

        之前我們將列向量的w總是設爲1,現在我們設爲0,很容易發現位移矩陣的第四列失去了作用。換句話說,列向量的w可以開關平移矩陣。所以在計算變換時,向量如果代表一個點,說明他具有3D座標系中的具體位置,我們應該把w設爲1。如果向量就是作爲向量,只具有方向的含義,我們應將w設爲0,屏蔽無用的位置偏移的信息。

        在上一章中我們所做的線性操作要求任意軸都經過原點。現在我們有了位移矩陣就可以獲得不經過原點的任意軸的仿射變換。我們可以將向量先平移至原點,在做線性變換,再將向量反向平移回去。即可實現向量對任意軸的變幻了。

        \mathbf{T} = \begin{bmatrix} 1 & 0 & 0 & -\mathbf{p_{x}} \\ 0 & 1 & 0 &-\mathbf{p_{y}} \\ 0 & 0 & 0 &-\mathbf{p_{z}} \\ 0 & 0 & 1 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{I }& -\mathbf{p}\\ 0 & 1 \end{bmatrix}

        \mathbf{R}_{4x4} = \begin{bmatrix} r_{11} & r_{12} & r_{13} & 0\\ r_{21} & r_{22} & r_{23} & 0\\ r_{31} & r_{32} & r_{33} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{R}_{3x3} & \mathbf{0}\\ 0 & 1 \end{bmatrix}

        \mathbf{T}^{-1} = \begin{bmatrix} 1 & 0 & 0 & \mathbf{p_{x}} \\ 0 & 1 & 0 &\mathbf{p_{y}} \\ 0 & 0 & 0 &\mathbf{p_{z}} \\ 0 & 0 & 1 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{I }&\mathbf{p}\\ 0 & 1 \end{bmatrix}

        \mathbf{T}\mathbf{R}_{4x4}\mathbf{T}^{-1} = \begin{bmatrix} \mathbf{I} & -\mathbf{p}\\ 0 & 1 \end{bmatrix} \begin{bmatrix} \mathbf{R}_{3x3} & \mathbf{0}\\ 0 & 1 \end{bmatrix} \begin{bmatrix} \mathbf{I} & \mathbf{p}\\ 0 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{R}_{3x3} & \mathbf{R}_{3x3}(-\mathbf{p}) + \mathbf{p}\\ 0 & 1 \end{bmatrix}

三、正交矩陣

        上述混合變換時我們用到了逆矩陣,逆矩陣很好的變現了變換的逆操作,但根據第一篇矩陣的文章所述,求矩陣的逆將帶來大量的運算。這裏引入一種新的矩陣,正交矩陣。一個矩陣M,當且僅當矩陣M和其轉置矩陣乘積等於單位矩陣。則說矩陣M正交。

        \mathbf{M}正交=d正交 <=> \mathbf{M}\mathbf{M}^{T} = \mathbf{I}

        根據矩陣第一章逆的相關定義,若矩陣乘他的逆等於單元矩陣,那麼他的轉置等於他的逆。

        所以如果該矩陣是正交的,那麼我們在求他的逆矩陣時只需獲得他的轉置矩陣即可。顯然轉置的計算量遠小於求逆的過程。

        若一個矩陣是正交的,他滿足一下條件:

        1.矩陣的每一列都是單位向量。

        2.矩陣的所有列互相垂直。

        顯然之前所述的旋轉與鏡像矩陣都是正交的。並且若一個矩陣正交,那麼他的轉置矩陣也正交。在計算逆矩陣中,顯然如果我們知道該矩陣是正交矩陣時,直接獲取其轉置矩陣性能最佳。但若我們不知道他是否是正交矩陣時,先判斷矩陣是否正交和直接計算矩陣逆耗費時間相同。若矩陣本來並不正交,我們只會浪費更多的計算時間。

        因爲我們在矩陣的計算過程中矩陣的每一位的精度都可能超過了計算機能存儲的精度。所以矩陣在浮點運算的過程中可能會累計誤差,稱爲矩陣爬行。當我們認爲一個矩陣是正交矩陣時,他可能因爲外部的數據損壞或運算中的誤差積累變得並不那麼正交。所以有時我們需要做矩陣正交化的操作。

        施密特正交化是線性代數中標準的矩陣正交化算法。原理即每一列(行)都減去它投影於已處理過的列(行)的部分。顯然得到的三個向量互相垂直。這三個向量稱爲3D向量空間的三個正交基。若將正交基標準化。則稱爲規範正交基(在線性代數中如此稱呼,在3D數學基礎:圖形與遊戲開發一書中稱爲標準正交基)。

        現在我們有一個3x3的矩陣,我們從矩陣中獲取每一列分別記作r1,r2,r3。則求正交基的過程如下:

        \mathbf{r}_{1}^{'} <= \mathbf{r}_{1}

        \mathbf{r}_{2}^{'} <= \mathbf{r}_{2} - (\mathbf{r}_{2}*\mathbf{r}_{1}^{'}/\mathbf{r}_{1}^{'} * \mathbf{r}_{1}^{'}) \mathbf{r}_{1}^{'}

        \mathbf{r}_{3}^{'} <= \mathbf{r}_{3} - (\mathbf{r}_{3}*\mathbf{r}_{1}^{'}/\mathbf{r}_{1}^{'} * \mathbf{r}_{1}^{'}) \mathbf{r}_{1}^{'} - (\mathbf{r}_{3}*\mathbf{r}_{2}^{'}/\mathbf{r}_{2}^{'} * \mathbf{r}_{2}^{'}) \mathbf{r}_{2}^{'}

        然後將得到的三個向量標準化即可得到規範正交基。

        可以發現如果這麼做正交化會出現因爲選擇第一個基向量的順序的不同導致不同的結果。3D數學基礎:圖形與遊戲開發一書中提出一個優化方法,選擇一個小的因子k,每次都將一個向量減去對其餘所有向量的投影,但都只減少k倍。如此迭代多次。得到的基向量會越來越正交化,但可能並不完全正交。

        \mathbf{r}_{1}^{'} <= \mathbf{r}_{1} - k(\mathbf{r}_{1}*\mathbf{r}_{2}/\mathbf{r}_{2} * \mathbf{r}_{2}) \mathbf{r}_{2} - (\mathbf{r}_{1}*\mathbf{r}_{3}/\mathbf{r}_{3} * \mathbf{r}_{3}) \mathbf{r}_{3}

        \mathbf{r}_{2}^{'} <= \mathbf{r}_{2} - k(\mathbf{r}_{2}*\mathbf{r}_{1}/\mathbf{r}_{1} * \mathbf{r}_{1}) \mathbf{r}_{1} - (\mathbf{r}_{2}*\mathbf{r}_{3}/\mathbf{r}_{3} * \mathbf{r}_{3}) \mathbf{r}_{3}

        \mathbf{r}_{3}^{'} <= \mathbf{r}_{3} - k(\mathbf{r}_{3}*\mathbf{r}_{1}/\mathbf{r}_{1} * \mathbf{r}_{1}) \mathbf{r}_{1} - (\mathbf{r}_{3}*\mathbf{r}_{2}/\mathbf{r}_{2} * \mathbf{r}_{2}) \mathbf{r}_{2}

        要得到完美的結果,需要選擇適當的因子k,並迭代足夠次數(如10次),接着標準化即可。

四、正交投影

        一般來說,投影意味着降維操作。可以將某個方向上用零作爲縮放因子。這樣所有點被拉伸到平面(3D)或線(2D)中。

        如果在2D中向座標軸投影或者在3D中向兩個座標軸形成的平面投影。我們只需將剩下的一個維度設爲0即可,即上述的縮放因子設爲0。得到如下矩陣:

        \mathbf{P_{x}} = \mathbf{S}(\begin{bmatrix} 0 & 1 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 1 &0 \\ 0 & 0 \end{bmatrix}

        \mathbf{P_{y}} = \mathbf{S}(\begin{bmatrix} 1 & 0 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 0 &0 \\ 0 & 1 \end{bmatrix}

        \mathbf{P_{xy}} = \mathbf{S}(\begin{bmatrix} 0 &0 & 1 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 1 &0&0 \\ 0 & 1&0\\ 0 & 0&0 \end{bmatrix}

        \mathbf{P_{xz}} = \mathbf{S}(\begin{bmatrix} 0 &1 & 0 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 1 &0&0 \\ 0 & 0&0\\ 0 & 0&1 \end{bmatrix}

        \mathbf{P_{yz}} = \mathbf{S}(\begin{bmatrix} 0 &0 & 1 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 0 &0&0 \\ 0 & 1&0\\ 0 & 0&1 \end{bmatrix}

        向任意直線或平面投影,位移部分用上述方法即可獲取,現在我們關注經過原點的直線或平面的投影。

        上一章中獲得的對任意經過原點的直線或平面的縮放矩陣,將縮放因子設爲0即可獲得。將0帶入縮放矩陣很容易得到:

        \mathbf{P}(\mathbf{n}) = \mathbf{S}(\mathbf{n},0) = \begin{bmatrix} 1 + (0 - 1)\mathbf{n}_{x}^{2} & (0 - 1)\mathbf{n}_{x}\mathbf{n}_{y}\\ (0 - 1)\mathbf{n}_{x}\mathbf{n}_{y} & 1 + (0 - 1)\mathbf{n}_{y}^{2} \end{bmatrix} = \begin{bmatrix} 1 -\mathbf{n}_{x}^{2} & -\mathbf{n}_{x}\mathbf{n}_{y}\\ -\mathbf{n}_{x}\mathbf{n}_{y} & 1 -\mathbf{n}_{y}^{2} \end{bmatrix}

        \mathbf{P}(\mathbf{n}) = \mathbf{S}(\mathbf{n},0) = \begin{bmatrix} 1 -\mathbf{n}_{x}^{2} & -\mathbf{n}_{x}\mathbf{n}_{y}& -\mathbf{n}_{x}\mathbf{n}_{z}\\ -\mathbf{n}_{x}\mathbf{n}_{y} & 1 -\mathbf{n}_{y}^{2} & -\mathbf{n}_{z}\mathbf{n}_{y}\\ -\mathbf{n}_{x}\mathbf{n}_{z} & -\mathbf{n}_{y}\mathbf{n}_{z} & 1 -\mathbf{n}_{z}^{2} \end{bmatrix}

五、透視投影

        之前我們說引入齊次座標作爲4D向量的第四個分量的第二個原因是w可以爲其他座標做除以w的操作。這個性質在透視投影中得到運用。

        之前的平行投影之所以成爲平行投影是因爲投影線互相平行。而3D中透視投影的投影線不在平行,且會相交於一點,該點成爲投影中心。

        透視投影是人類視覺系統的模型,充分顯示出小孔成像的幾何特性。小孔成像

        而圖形接口如OpenGL中的投影矩陣與小孔成像相比只是在光透過小孔前就會成像。且一般都會投影到攝像機的z = 近裁剪面形成的平行於xy平面的面上。如下圖所示。

投影圖示

        我們現在將點P投影到P'。設P點的z分量爲z。投影面的z分量即P'點的z分量爲d。投影公式爲:

        \mathbf{P} = \begin{bmatrix} x\\ y\\ z \end{bmatrix} => \mathbf{P{}'} = \begin{bmatrix} x{}'\\ y{}'\\ z{}' \end{bmatrix} = \begin{bmatrix} dx/z\\ dy/z\\ d \end{bmatrix}

        \mathbf{P}{}' = \begin{bmatrix} dx/z\\ dy/z\\ dz/z \end{bmatrix} = \begin{bmatrix} x\\ y\\ z \end{bmatrix}/(z/d)

        我們將P'轉換爲帶有w的4D座標即\begin{bmatrix} x & y & z & z/d \end{bmatrix}^{T}。是的4D座標中x、y、z座標分別除以w等於前面的3D座標的x、y、z。

        所以我們需要構造一個4x4矩陣完成上述映射。矩陣如下:

        \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 1/d & 0 \end{bmatrix} \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} x\\ y\\ z\\ z/d \end{bmatrix}

        當然真正使用的投影矩陣比這個複雜的多,比如unity中將攝像機座標系下的點變換爲投影座標系下的點所使用的矩陣。在下一章中我們會詳細講述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章