鍍金池/ 教程/ Android/ Viewing 和 Modeling(MODELVIEW) 變換
繪制線段 Line Segment
投影變換 Projection
繪制迷你太陽系
繪制一個(gè)球體
繪制三角形 Triangle
OpenGL 光照模型
三維坐標(biāo)系及坐標(biāo)變換初步
定義 3D 模型的前面和后面
繪制一個(gè) 20 面體
顏色 Color
Depth Buffer
材質(zhì)及光照示例
基本幾何圖形定義
關(guān)于EGL
導(dǎo)言
Viewing 和 Modeling(MODELVIEW) 變換
FrameBuffer
設(shè)置光照效果 Set Lighting
Viewport 變換
階段小結(jié)
繪制點(diǎn) Point
OpenGL ES API 命名習(xí)慣
通用的矩陣變換指令
關(guān)于 OpenGL ES
創(chuàng)建實(shí)例應(yīng)用 OpenGLDemos 程序框架
OpenGL ES 管道(Pipeline)
GLSurfaceView

Viewing 和 Modeling(MODELVIEW) 變換

Viewing 和 Modeling 變換關(guān)系緊密,對(duì)應(yīng)到相機(jī)拍照為放置三角架和調(diào)整被拍物體位置及角度,通常將這兩個(gè)變換使用一個(gè) modelview 變換矩陣來定義。對(duì)于同一個(gè)坐標(biāo)變換,可以使用不同的方法來想象這個(gè)變換,比如將相機(jī)向某個(gè)方向平移一段距離,效果等同于將被拍攝的模型(model)向相反的方向平移同樣的距離(相對(duì)運(yùn)動(dòng))。兩個(gè)不同的空間想象方法對(duì)于理解坐標(biāo)變換各有其優(yōu)缺點(diǎn)。你可以使用適合自己理解能力的方法來想象空間坐標(biāo)變換。

下面我們使用一個(gè)由兩個(gè)坐標(biāo)變換組成的簡(jiǎn)單例子開始介紹 MODELVIEW 變換:一個(gè)變換為逆時(shí)針繞Z軸旋轉(zhuǎn)45度,另一個(gè)變換為為沿X軸平移。 假定需要繪制的物體的尺寸和平移的距離相比要小的多從而你可以跟容易的看到平移效果。這個(gè)物體初始位置在坐標(biāo)系的原點(diǎn)。

如果先旋轉(zhuǎn)物體然后再平移,旋轉(zhuǎn)后的物體的位置在 X 軸上面,但如果先平移后繞原點(diǎn)旋轉(zhuǎn)物體,最終物體會(huì)出現(xiàn)在 y=x 的直線上:

http://wiki.jikexueyuan.com/project/opengl-es-guide/images/74.png" alt="" />

可以看到坐標(biāo)變換的次序直接影響到最終的變換結(jié)果。所有的 Viewing 和 Modeling 變換操作都可以使用一個(gè)4X4 的矩陣來表示,所有后續(xù)的 glMultMatrix*() 或其它坐標(biāo)變換指令 會(huì)使用一個(gè)新的變換矩陣M于當(dāng)前 modelview 矩陣 C 相乘得到一個(gè)新的變換矩陣 CM。然后所有頂點(diǎn)坐標(biāo)v 都會(huì)和這個(gè)新的變換矩陣相乘。 這個(gè)過程意味著最后發(fā)出的坐標(biāo)變換指令實(shí)際上是第一個(gè)應(yīng)用到頂點(diǎn)上的:CMv 。因此一種來理解坐標(biāo)變換次序的方法是:使用逆序來指定坐標(biāo)變換。

比如下面代碼:

gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity();
//apply transformation N
gl.glMultMatrixf(N);
//apply transformation M
glMultMatrixf(M);
//apply transformation L
gl.glMultMatrixf(L);
//draw vertex
...  

上面代碼, modelview 矩陣依次為I(單位矩陣),N,NM 最終為 NML ,最終坐標(biāo)變換的結(jié)果為 NMLv ,也就是N(M(Lv)) ,v 首先與 L 相乘,結(jié)果 Lv 再和M相乘,所得結(jié)果 MLv 再和N相乘。可以看到坐標(biāo)變換的次序和指令指定的次序正好相反。而實(shí)際代碼運(yùn)行時(shí),坐標(biāo)無需進(jìn)行三次變換運(yùn)算,頂點(diǎn) v 只需和計(jì)算出的最終變換矩陣 NML 相乘一次就可以了。

因此如果你采用世界坐標(biāo)系(原點(diǎn)和X,Y,Z軸方向固定)來思考坐標(biāo)變換,代碼中坐標(biāo)變換指令的次序和 頂點(diǎn)和矩陣相乘的次序相反。比如,還是上面的例子,如果你想最終的物體出現(xiàn)在X軸上,此時(shí)必須是先旋轉(zhuǎn)后平移,可以使用如下代碼(R 代表選擇矩陣,T 代表平移矩陣)

gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity();
//translation
gl.glMultMatrixf(T);
//rotation
gl.glMultMatrixf(R);
draw_the_object()  

另外一種想象坐標(biāo)變換的方法是忘記這種固定的坐標(biāo)系統(tǒng),而是使用物體本身的局部坐標(biāo)系統(tǒng),這種局部坐標(biāo)系和物體的相對(duì)位置是固定的。 所有的坐標(biāo)變換操作都是針對(duì)物體的局部坐標(biāo)系。使用這種方法,代碼中矩陣相乘的次序和相對(duì)局部坐標(biāo)系坐標(biāo)變換的次序是一致的。(不關(guān)使用哪種方法來想象坐標(biāo)變換,最終同樣變換結(jié)果代碼都是一樣的,只是理解的方法不同)。還是使用上面旋轉(zhuǎn)平移的例子。想象一個(gè)和物體連接一起的局部坐標(biāo)系,如下圖紅色的坐標(biāo)系,想象所有的坐標(biāo)變換都是相對(duì)這個(gè)局部坐標(biāo)系的,要使物體最終出現(xiàn)在 y=x 上,可以想象先轉(zhuǎn)動(dòng)物體及其局部坐標(biāo)系(R),然后再平移物體及其局部坐標(biāo)系(T),這時(shí)代碼的順序和相對(duì)于物體局部坐標(biāo)系的次序是相同的。

gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity();
//rotation
gl.glMultMatrixf(R);
//translation
gl.glMultMatrixf(T);
draw_the_object()  

http://wiki.jikexueyuan.com/project/opengl-es-guide/images/75.png" alt="" />

使用物體局部坐標(biāo)系,可以更好的了解理解如機(jī)械手和太陽系之類的圖形系統(tǒng)。

http://wiki.jikexueyuan.com/project/opengl-es-guide/images/76.png" alt="" />

Android OpenGL ES 的 GLU 包有一個(gè)輔助函數(shù) gluLookAt 提供一個(gè)更直觀的方法來設(shè)置modelview 變換矩陣:

void gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

http://wiki.jikexueyuan.com/project/opengl-es-guide/images/77.png" alt="" />

  • eyex,eyey,eyez 指定觀測(cè)點(diǎn)的空間坐標(biāo)。
  • tarx,tary,tarz ,指定被觀測(cè)物體的參考點(diǎn)的坐標(biāo)。
  • upx,upy,upz 指定觀測(cè)點(diǎn)方向?yàn)椤吧稀钡南蛄俊?

注意: 這些坐標(biāo)都采用世界坐標(biāo)系。

上一篇:關(guān)于EGL下一篇:顏色 Color