Viewing和Modeling 變換關係緊密,對應到相機拍照為放置三角架和調整被拍物體位置及角度,通常將這兩個變換使用一個modelview 變換矩陣來定義。對於同一個座標變換,可以使用不同的方法來想象這個變換,比如將相機向某個方向平移一段距離,效果等同於將被拍攝的模型(model)向相反的方向平移同樣的距離(相對運動)。兩個不同的空間想象方法對於理解座標變換各有其優缺點。你可以使用適合自己理解能力的方法來想象空間座標變換。
下面我們使用一個由兩個座標變換組成的簡單例子開始介紹MODELVIEW變換:一個變換為逆時針繞Z軸旋轉45度,另一個變換為為沿X軸平移。 假定需要繪製的物體的尺寸和平移的距離相比要小的多從而你可以跟容易的看到平移效果。這個物體初始位置在座標系的原點。
如果先旋轉物體然後再平移,旋轉後的物體的位置在X軸上面,但如果先平移後繞原點旋轉物體,最終物體會出現在y=x 的直線上:
可以看到座標變換的次序直接影響到最終的變換結果。所有的Viewing和Modeling 變換操作都可以使用一個4X4 的矩陣來表示,所有後續的glMultMatrix*()
或其它座標變換指令 會使用一個新的變換矩陣M於當前modelview矩陣C相乘得到一個新的變換矩陣CM。然後所有頂點座標v 都會和這個新的變換矩陣相乘。 這個過程意味著最後發出的座標變換指令實際上是第一個應用到頂點上的:CMv 。因此一種來理解座標變換次序的方法是:使用逆序來指定座標變換。
比如下面代碼:
gl.glMatrixMode(GL_MODELVIEW);<br />gl.glLoadIdentity();<br />//apply transformation N<br />gl.glMultMatrixf(N);<br />//apply transformation M<br />glMultMatrixf(M);<br />//apply transformation L<br />gl.glMultMatrixf(L);<br />//draw vertex<br />...
上面代碼,modelview 矩陣依次為I(單位矩陣),N,NM最終為NML ,最終座標變換的結果為 NMLv ,也就是N(M(Lv)) ,v首先與L相乘,結果Lv 再和M相乘,所得結果MLv 再和N相乘。可以看到座標變換的次序和指令指定的次序正好相反。而實際代碼運行時,座標無需進行三次變換運算,頂點v 只需和計算出的最終變換矩陣NML 相乘一次就可以了。
因此如果你採用全局座標系(原點和X,Y,Z軸方向固定)來思考座標變換,代碼中座標變換指令的次序和 頂點和矩陣相乘的次序相反。比如,還是上面的例子,如果你想最終的物體出現在X軸上,此時必須是先旋轉後平移,可以使用如下代碼(R代表選擇矩陣,T 代表平移矩陣)
gl.glMatrixMode(GL_MODELVIEW);<br />gl.glLoadIdentity();<br />//translation<br />gl.glMultMatrixf(T);<br />//rotation<br />gl.glMultMatrixf(R);</p><p>draw_the_object()
另外一種想象座標變換的方法是忘記這種固定的座標系統,而是使用物體本身的局部座標系統,這種局部座標系和物體的相對位置是固定的。 所有的座標變換操作都是針對物體的局部座標系。使用這種方法,代碼中矩陣相乘的次序和相對局部座標系座標變換的次序是一致的。(不關使用哪種方法來想象座標變換,最終同樣變換結果代碼都是一樣的,只是理解的方法不同)。還是使用上面旋轉平移的例子。想象一個和物體串連一起的局部座標系,如紅色的座標系,想象所有的座標變換都是相對這個局部座標系的,要使物體最終出現在y=x 上,可以想象先轉動物體及其局部座標系(R),然後再平移物體及其局部座標系(T),這時代碼的順序和相對於物體局部座標系的次序是相同的。
gl.glMatrixMode(GL_MODELVIEW);<br />gl.glLoadIdentity();<br />//rotation<br />gl.glMultMatrixf(R);<br />//translation<br />gl.glMultMatrixf(T);</p><p>draw_the_object()
使用物體局部座標系,可以更好的瞭解理解如機械手和太陽系之類的圖形系統。
Android OpenGL ES 的GLU包有一個輔助函數gluLookAt提供一個更直觀的方法來設定modelview 變換矩陣:
void gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
- eyex,eyey,eyez 指定觀測點的空間座標。
- tarx,tary,tarz ,指定被觀測物體的參考點的座標。
- upx,upy,upz 指定觀測點方向為“上”的向量。
注意: 這些座標都採用全局座標系。