坐标系统之间的转换
概要
這篇文章中,我們來聊聊 OpenGL 中的坐標系統以及它們之間的轉換。
(??閱讀本文需要有線性代數基礎。)
坐標變換原理
首先,我們需要運用一點線性代數的知識,了解不同坐標系統變換的原理。
由于本文針對的是三維坐標,所以討論的空間是 \(R^3\) 空間。
在標準三維坐標系中,我們通常用一個向量 v=[x, y, z] 來表示一個點的位置。這里的 x、y、z 分別對應 x 軸、y 軸以及 z 軸三個方向的偏移,而標準三維坐標空間的基采用的是三個互相垂直的向量 \(\mathbf e_1=[1,0,0]\), \(\mathbf e_2=[0,1,0]\), \(\mathbf e_3=[0,0,1]\)。但根據線性無關等知識,我們完全可以找出另外三個向量作為三維空間的基,只要這三個向量線性無關,同樣能夠張成 \(R^3\) 空間。
現在,假設坐標系 A 采用的基向量是 {\(\mathbf v_1, \mathbf v_2, \mathbf v_3\)},坐標系 B 采用的是{\(\mathbf u_1\), \(\mathbf u_2\), \(\mathbf u_3\)}。
那么,根據線性無關性,我們可以得到線性方程組:
\[ {\mathbf u_1 = \gamma_{11}\mathbf v1+\gamma_{12}\mathbf v2+\gamma_{13}\mathbf v_3} \]
\[ \mathbf u_2 = \gamma_{21}\mathbf v1+\gamma_{22}\mathbf v2+\gamma_{23}\mathbf v_3 \]
\[ \mathbf u_3 = \gamma_{31}\mathbf v1+\gamma_{32}\mathbf v2+\gamma_{33}\mathbf v_3 \]
用矩陣方程的形式表示為:
\[\mathbf u = \mathbf M \mathbf v\]
由于 \(\mathbf u\), \(\mathbf v\) 都是三維空間的基,因此,對于三維空間內任意一個向量 \(\mathbf w\),\(\mathbf u\)、\(\mathbf v\)都可以通過線性組合的方式表示出 \(\mathbf w\):
\(\mathbf w = \mathbf a^T \mathbf v = \mathbf b^T \mathbf u\)(這里的\(\mathbf a^T\), \(\mathbf b^T\)分別表示不同坐標空間的標量)。
結合前面 \(\mathbf u = \mathbf M \mathbf v\),進一步得到:\(\mathbf w = \mathbf b^T \mathbf u = \mathbf b^T \mathbf M \mathbf v=\mathbf a^T \mathbf v\),
繼而 :\(\mathbf a = \mathbf M^T \mathbf b\),\(\mathbf b = (\mathbf M^T)^{-1} \mathbf a\)。
好了,到這里,關鍵的東西就講完了。所以坐標系統的變換很簡單有木有!如果你在B坐標系(基向量為{\(\mathbf u_1\), \(\mathbf u_2\), \(\mathbf u_3\)})中有個向量 \(\mathbf w\),沿用上面的假設,\(\mathbf w\) 的坐標為 \(\mathbf b\)(即 \(\mathbf w = \mathbf b^T \mathbf u\)),這個時候,我們想求出它在 A 坐標系(基向量為{\(\mathbf v_1, \mathbf v_2, \mathbf v_3\)})的坐標表示(假設為\(\mathbf a\)),我們只需要求出矩陣 \(\mathbf M\),則:\(\mathbf a = \mathbf M^T \mathbf b\)。
反之同理。
這個時候,有同學可能會問矩陣 \(\mathbf M\) 怎么求?
假設一個坐標系統的基向量為{\(\mathbf u_1\), \(\mathbf u_2\), \(\mathbf u_3\)},而另一個系統采用標準向量{\(\mathbf e_1\), \(\mathbf e_2\), \(\mathbf e_3\)},假設存在關系:\(\mathbf u = \mathbf M^T \mathbf e\)(這個式子的理解是:如果 \(\mathbf M\) 是兩個坐標系統的變換矩陣,那么兩個系統內的任意向量可以通過這個矩陣相互轉換,基向量只不過是特殊的向量,一樣可以通過 \(\mathbf M\) 進行轉換),那矩陣 \(\mathbf M\) 其實可以表示為 [\(\mathbf u_1, \mathbf u_2, \mathbf u_3\)]。這個結果其實很好理解,只要換種寫法:
\(\mathbf u = \begin{bmatrix} \mathbf u_1 \\ \mathbf u_2 \\ \mathbf u_3 \\ \end{bmatrix}\),\(\mathbf e = \begin{bmatrix} \mathbf e_1 \\ \mathbf e_2 \\ \mathbf e_3 \\ \end{bmatrix}\),可以發現,\(\mathbf e\)其實是一個單位矩陣。
而如果是非標準坐標系統之間的變換,則需要解一個線性方程組:\(\mathbf u = \mathbf M^T \mathbf v\),而且可以肯定,這個解存在且唯一。
盡管從上面的推論中我們可以得出,不同坐標系統可以通過一個唯一的 3*3 矩陣 \(\mathbf M\) 來變換,但都是基于坐標原點相同的前提。如果原點也發生變化,這時就必須引入第四個維度來表示平移的偏移量,也就是常說的齊次坐標。
引入第四維后,\(\mathbf u=[\mathbf u_1,\mathbf u_2,\mathbf u_3,\mathbf p]\),\(\mathbf v=[\mathbf v_1,\mathbf v_2,\mathbf v_3,\mathbf q]\),我們再次用一個矩陣 \(\mathbf M\) 來轉換這兩個坐標系統,不同的是,這里的 \(\mathbf M\) 是一個 4*4 的矩陣:
\[ \mathbf M= \begin{bmatrix} \gamma_{11} & \gamma_{12} & \gamma_{13} & 0 \\ \gamma_{21} & \gamma_{22} & \gamma_{23} & 0 \\ \gamma_{31} & \gamma_{32} & \gamma_{33} & 0 \\ \gamma_{41} & \gamma_{42} & \gamma_{43} & 1 \\ \end{bmatrix} \]
\[ \mathbf u = \mathbf M^T * \mathbf v \]
除了多出一維外,齊次坐標與上面使用的三維坐標本質上沒有區別,計算方法也基本一致,在對應到三維坐標系時,只需要舍棄第四個維度即可。
OpenGL中的坐標系統
OpenGL 的坐標系統有六種:
模型坐標系 (Object coordinates) 是每個模型在制作時特有的,如果要把模型放入世界,就需要將所有模型的坐標系轉換成世界坐標系 (World coordinates)。世界中的場景需要通過相機被人眼觀察,需要將世界坐標系轉換成相機坐標系 (Eye coordinates)。從模型坐標系,到世界坐標系,再到相機坐標系的變換,通常稱為 model-view transformation,通過 model-view matrix 來實現。
前三種坐標系統通常是由用戶指定的,而后三種坐標系統一般都是在 OpenGL 管道中,由程序自己實現的。
而 OpenGL 中坐標系統轉換的原理,其實就是上面所講的那些,只不過在使用時,我們可以使用一些 API 來簡化不少工作。
參考
- Interactive Computer Graphics - A Top-Down Approach 6e By Edward Angel and Dave Shreiner (Pearson, 2012)
轉載于:https://www.cnblogs.com/jermmyhsu/p/8195549.html
總結
- 上一篇: mycat快速体验(转)
- 下一篇: Nginx代理、负载均衡