OpenGL中不設置模型,投影,視口,所繪制的幾何圖形的坐標只能是-1到1(X軸向右,Y軸向上,Z軸垂直屏幕向外)。
產生目標場景的過程類似於用照相機進行拍照:
(1)把照相機固定在三角架上,並讓他對准場景
從不同位置觀察場景(視圖變換)
(2)對場景進行安排,使各個物體在照片中的位置是我們所希望的
移動,旋轉或者放大縮小場景中的物體(模型變換)
(3)選擇照相機鏡頭,並調整放大倍數(調焦)
顯示物體時,可以選擇物體是如何投影到屏幕上(投影變換)
(4)確定照片的大小,放大照片還是縮小照片
把圖形畫下來,是要占據整個屏幕還是屏幕的一部分(視口變換)
OpenGL中的各種轉換是通過矩陣運算實現的,具體的說,就是當發出一個轉換命令時,該命令會生成一個4X4階的轉換矩陣(OpenGL中的物體坐標一律采用齊次坐標,即(x, y, z, w),故所有變換矩陣都采用4X4矩陣),當前矩陣與這個轉換矩陣相乘,從而生成新的當前矩陣。例如,對於頂點坐標v ,轉換命令通常在頂點坐標命令之前發出,若當前矩陣為C,轉換命令構成的矩陣為M,則發出轉換命令后,生成的新的當前矩陣為CM,這個矩陣再乘以頂點坐標v,從而構成新的頂點坐標CMv。上述過程說明,程序中繪制頂點前的最后一個變換命令最先作用於頂點之上。這同時也說明,OpenGL編程中,實際的變換順序與指定的順序是相反的。
一、視點變換
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble upx,GLdouble upy,GLdouble upz);
glTranslate{fd}(TYPE x,TYPE y,TYPE z);
glRotate{fd}(TYPE angle,TYPE x,TYPE,y,TYPE z);
glScale{fd}(TYPE x,TYPE y,TYPE z);
(1)OpenGL透視投影函數有兩個
1. 其中函數glFrustum()的原型為:
void glFrustum(;GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
它創建一個透視視景體。其操作是創建一個透視投影矩陣,並且用這個矩陣乘以當前矩陣。這個函數的參數只定義近裁剪平面的左下角點和右上角點的三維空間坐標,即(left,bottom,-near)和(right,top,-near);最后一個參數far是遠裁剪平面的Z負值,其左下角點和右上角點空間坐標由函數根據透視投影原理自動生成。near和far表示離視點的遠近,它們總為正值。
2、glPerspective( GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far)
創建一個表示對稱透視視圖平截頭體的矩陣,並把它與當前矩陣相乘。fovy是YZ平面上視野的角度,范圍【0,180】。aspect是這個平截頭體的縱橫比,也就是寬度除於高度。near和far值分別是觀察點與近側裁剪平面以及遠側裁剪平面的距離(沿Z軸負方向)這兩個值都是正的。
正投影的主要函數
1、glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
創建一個平行視景體(就是一個長方體空間區域)。實際上這個函數的操作是創建一個正射投影矩陣,並且用這個矩陣乘以當前矩陣。其中近裁剪平面是一個矩形,矩形左下角點三維空間坐標是(left,bottom,-near),右上角點是(right,top,-near);遠裁剪平面也是一個矩形,左下角點空間坐標是(left,bottom,-far),右上角點是(right,top,-far)。注意,near和far都是正值。只有在視景體里的物體才能顯示出來,我感覺你最后兩個參數取得有點問題,而且你改成0,0后,視景體深度沒有了,整個視景體都被壓成個平面了,當然就顯示不正確了。
3、glOrtho2D( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
創建一個表示把二維坐標投影到屏幕上的矩陣,並把當前矩陣與它相乘,裁剪區域為矩形。
把像素繪制到屏幕上glViewport()定義視口,前兩個參數最左下方,后兩個參數寬度和高度。
4、視口變換
在窗口中定義一個像素矩形,最終的圖像將映射到這個矩形中。
glViewport( Glint x, Glint y, GLsizei width, GLsizei height );XY指定了視口的左下角,WH指定了視口的高度和寬度。在默認情況下,視口的初始值是(0,0,winwidth,winheight)。
視口的縱橫比一般和視景體的縱橫比相同。當窗口的大小發生變化時,並不會自動影響視口,應用程序應該檢測窗口大小改變事件。
六、矩陣棧的操作
1.模型轉換與視點轉換:
void glLoadMatrix{fd}(const TYPE *m)
設置當前矩陣中的元素值。函數參數*m是一個指向16個元素(m0, m1, ..., m15)的指針,這16個元素就是當前矩陣M中的元素,其排列方式如下
M = | m0 m4 m8 m12 |
| m1 m5 m9 m13 |
| m2 m6 m10 m14 |
| m3 m7 m11 M15 |
矩陣以列作為主要的排列方式。
2. void glMultMatrix{fd}(const TYPE *m)
用當前矩陣去乘*m所指定的矩陣,並將結果存放於*m中。當前矩陣可以是用glLoadMatrix() 指定的矩陣,也可以是其它矩陣變換函數的綜合結果。
該方法用任意矩陣去乘以當前矩陣,該方法不返回任何值。
說明:
The glMultMatrix function multiplies the current matrix by the one specified in m. That is, if M is the current matrix and T is the matrix passed to glMultMatrix, then M is replaced with M • T.
如果M是當前矩陣, T是該方法中的參數指定的矩陣。則該方法調用之后,當前矩陣變為 M = M * T.
The current matrix is the projection matrix, modelview matrix, or texture matrix, determined by the current matrix mode (see glMatrixMode).
The m parameter points to a 4x4 matrix of single-precision or double-precision floating-point values stored in column-major order. That is, the matrix is stored as shown in the following image.
3. glMatrixMode
指定當前矩陣類型:可以設置以下矩陣類型。
| Value | Meaning |
|---|---|
|
Applies subsequent matrix operations to the modelview matrix stack.【模型視圖矩陣】 |
|
Applies subsequent matrix operations to the projection matrix stack.【投影矩陣】 |
|
Applies subsequent matrix operations to the texture matrix stack.【紋理矩陣】 |
4.矩陣堆棧操作:glPushMatrix(),glPopMatrix()
說明,OpenGL中有兩個最基本的矩陣,模型視景矩陣和投影矩陣,它們都有相應的矩陣堆棧,這些矩陣的當前值就是在矩陣堆棧中的最頂層元素。對於轉換操作,發出轉換命令后生成的新的當前矩陣就存儲在矩陣堆棧中,因此,我們可以利用矩陣堆棧存儲當前值,並在需要的時候將當前值彈出堆棧。
舉例來說,我們現在需要繪制一個自行車,設置自行車的兩個輪子相對於坐標原點是對稱的。我們可以這樣繪制:將坐標系原點移動到前車輪中心,然后進行繪制,完成后,計算前車輪中心到后車輪中心的距離,並將坐標系原點移動到后車輪中心,再繪制后車輪。顯然,這種繪制順序是不科學的,如果需要繪制更多的對稱物體,那么這種計算量會非常大,而且容易產生錯誤。
這種問題,我們使用矩陣堆棧可以很容易得到解決。在繪制前車輪之前,將當前矩陣保存在矩陣堆棧中,然后將坐標原點移動到前車輪中心,繪制前車輪,繪制結束后,將保存的當前矩陣彈出矩陣堆棧,這時堆棧頂部的矩陣仍為原坐標系,下一步只需相對於原坐標系移動相應距離到后車輪進行繪制,這樣,所有物體的位置都是相對於原坐標系進行設置,程序計算量得到縮減,而且不容易出錯誤。

