<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 189,comments - 115,trackbacks - 0

    基于VC++的OpenGL編程講座之坐標(biāo)變換(1) 

    OpenGL通過(guò)相機(jī)模擬、可以實(shí)現(xiàn)計(jì)算機(jī)圖形學(xué)中最基本的三維變換,即幾何變換、投影變換、裁剪變換、視口變換等,同時(shí),OpenGL還實(shí)現(xiàn)了矩陣堆棧等。理解掌握了有關(guān)坐標(biāo)變換的內(nèi)容,就算真正走進(jìn)了精彩地三維世界。

    一、OpenGL中的三維物體的顯示

    (一)坐標(biāo)系統(tǒng)

    在現(xiàn)實(shí)世界中,所有的物體都具有三維特征,但計(jì)算機(jī)本身只能處理數(shù)字,顯示二維的圖形,將三維物體及二維數(shù)據(jù)聯(lián)系在一起的唯一紐帶就是坐標(biāo)。

    為了使被顯示的三維物體數(shù)字化,要在被顯示的物體所在的空間中定義一個(gè)坐標(biāo)系。這個(gè)坐標(biāo)系的長(zhǎng)度單位和坐標(biāo)軸的方向要適合對(duì)被顯示物體的描述,這個(gè)坐標(biāo)系稱為世界坐標(biāo)系。世界坐標(biāo)系是始終固定不變的。

    OpenGL還定義了局部坐標(biāo)系的概念,所謂局部坐標(biāo)系,也就是坐標(biāo)系以物體的中心為坐標(biāo)原點(diǎn),物體的旋轉(zhuǎn)或平移等操作都是圍繞局部坐標(biāo)系進(jìn)行的,這時(shí),當(dāng)物體模型進(jìn)行旋轉(zhuǎn)或平移等操作時(shí),局部坐標(biāo)系也執(zhí)行相應(yīng)的旋轉(zhuǎn)或平移操作。需要注意的是,如果對(duì)物體模型進(jìn)行縮放操作,則局部坐標(biāo)系也要進(jìn)行相應(yīng)的縮放,如果縮放比例在案各坐標(biāo)軸上不同,那么再經(jīng)過(guò)旋轉(zhuǎn)操作后,局部坐標(biāo)軸之間可能不再相互垂直。無(wú)論是在世界坐標(biāo)系中進(jìn)行轉(zhuǎn)換還是在局部坐標(biāo)系中進(jìn)行轉(zhuǎn)換,程序代碼是相同的,只是不同的坐標(biāo)系考慮的轉(zhuǎn)換方式不同罷了。

    計(jì)算機(jī)對(duì)數(shù)字化的顯示物體作了加工處理后,要在圖形顯示器上顯示,這就要在圖形顯示器屏幕上定義一個(gè)二維直角坐標(biāo)系,這個(gè)坐標(biāo)系稱為屏幕坐標(biāo)系。這個(gè)坐標(biāo)系坐標(biāo)軸的方向通常取成平行于屏幕的邊緣,坐標(biāo)原點(diǎn)取在左下角,長(zhǎng)度單位常取成一個(gè)象素。

    (二)三維物體的相機(jī)模擬

     為了說(shuō)明在三維物體到二維圖象之間,需要經(jīng)過(guò)什么樣的變換,我們引入了相機(jī)(Camera)模擬的方式,假定用相機(jī)來(lái)拍攝這個(gè)世界,那么在相機(jī)的取景器中,就存在人眼和現(xiàn)實(shí)世界之間的一個(gè)變換過(guò)程。

    圖一、相機(jī)模擬OpenGL中的各種坐標(biāo)變換


    從三維物體到二維圖象,就如同用相機(jī)拍照一樣,通常都要經(jīng)歷以下幾個(gè)步驟:

    1、將相機(jī)置于三角架上,讓它對(duì)準(zhǔn)三維景物,它相當(dāng)于OpenGL中調(diào)整視點(diǎn)的位置,即視點(diǎn)變換(Viewing Transformation)。

     2、將三維物體放在場(chǎng)景中的適當(dāng)位置,它相當(dāng)于OpenGL中的模型變換(Modeling Transformation),即對(duì)模型進(jìn)行旋轉(zhuǎn)、平移和縮放。

    3、選擇相機(jī)鏡頭并調(diào)焦,使三維物體投影在二維膠片上,它相當(dāng)于OpenGL中把三維模型投影到二維屏幕上的過(guò)程,即OpenGL的投影變換(Projection Transformation),OpenGL中投影的方法有兩種,即正射投影和透視投影。為了使顯示的物體能以合適的位置、大小和方向顯示出來(lái),必須要通過(guò)投影。有時(shí)為了突出圖形的一部分,只把圖形的某一部分顯示出來(lái),這時(shí)可以定義一個(gè)三維視景體(Viewing Volume)。正射投影時(shí)一般是一個(gè)長(zhǎng)方體的視景體,透視投影時(shí)一般是一個(gè)棱臺(tái)似的視景體。只有視景體內(nèi)的物體能被投影在顯示平面上,其他部分則不能。

    4、沖洗底片,決定二維相片的大小,它相當(dāng)與OpenGL中的視口變換(Viewport Transformation)(在屏幕窗口內(nèi)可以定義一個(gè)矩形,稱為視口(Viewport),視景體投影后的圖形就在視口內(nèi)顯示)規(guī)定屏幕上顯示場(chǎng)景的范圍和尺寸。

    通過(guò)上面的幾個(gè)步驟,一個(gè)三維空間里的物體就可以用相應(yīng)的二維平面物體表示了,也就能在二維的電腦屏幕上正確顯示了。總的來(lái)說(shuō),三維物體的顯示過(guò)程如下:

    圖二、三維物體的顯示過(guò)程


    基于VC++的OpenGL編程講座之坐標(biāo)變換(2)

    二、OpenGL中的幾種變換

     OpenGL中的各種轉(zhuǎn)換是通過(guò)矩陣運(yùn)算實(shí)現(xiàn)的,具體的說(shuō),就是當(dāng)發(fā)出一個(gè)轉(zhuǎn)換命令時(shí),該命令會(huì)生成一個(gè)4X4階的轉(zhuǎn)換矩陣(OpenGL中的物體坐標(biāo)一律采用齊次坐標(biāo),即(x, y, z, w),故所有變換矩陣都采用4X4矩陣),當(dāng)前矩陣與這個(gè)轉(zhuǎn)換矩陣相乘,從而生成新的當(dāng)前矩陣。例如,對(duì)于頂點(diǎn)坐標(biāo)v ,轉(zhuǎn)換命令通常在頂點(diǎn)坐標(biāo)命令之前發(fā)出,若當(dāng)前矩陣為C,轉(zhuǎn)換命令構(gòu)成的矩陣為M,則發(fā)出轉(zhuǎn)換命令后,生成的新的當(dāng)前矩陣為CM,這個(gè)矩陣再乘以頂點(diǎn)坐標(biāo) v,從而構(gòu)成新的頂點(diǎn)坐標(biāo)CMv。上述過(guò)程說(shuō)明,程序中繪制頂點(diǎn)前的最后一個(gè)變換命令最先作用于頂點(diǎn)之上。這同時(shí)也說(shuō)明,OpenGL編程中,實(shí)際的變換順序與指定的順序是相反的。

    (一)視點(diǎn)變換

     視點(diǎn)變換確定了場(chǎng)景中物體的視點(diǎn)位置和方向,就向上邊提到的,它象是在場(chǎng)景中放置了一架照相機(jī),讓相機(jī)對(duì)準(zhǔn)要拍攝的物體。確省時(shí),相機(jī)(即視點(diǎn))定位在坐標(biāo)系的原點(diǎn)(相機(jī)初始方向都指向Z負(fù)軸),它同物體模型的缺省位置是一致的,顯然,如果不進(jìn)行視點(diǎn)變換,相機(jī)和物體是重疊在一起的。

    執(zhí)行視點(diǎn)變換的命令和執(zhí)行模型轉(zhuǎn)換的命令是相同的,想一想,在用相機(jī)拍攝物體時(shí),我們可以保持物體的位置不動(dòng),而將相機(jī)移離物體,這就相當(dāng)于視點(diǎn)變換;另外,我們也可以保持相機(jī)的固定位置,將物體移離相機(jī),這就相當(dāng)于模型轉(zhuǎn)換。這樣,在OpenGL中,以逆時(shí)針旋轉(zhuǎn)物體就相當(dāng)于以順時(shí)針旋轉(zhuǎn)相機(jī)。因此,我們必須把視點(diǎn)轉(zhuǎn)換和模型轉(zhuǎn)換結(jié)合在一起考慮,而對(duì)這兩種轉(zhuǎn)換單獨(dú)進(jìn)行考慮是毫無(wú)意義的。
    除了用模型轉(zhuǎn)換命令執(zhí)行視點(diǎn)轉(zhuǎn)換之外,OpenGL實(shí)用庫(kù)還提供了gluLookAt()函數(shù),該函數(shù)有三個(gè)變量,分別定義了視點(diǎn)的位置、相機(jī)瞄準(zhǔn)方向的參考點(diǎn)以及相機(jī)的向上方向。該函數(shù)的原型為:

    void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble upx,GLdouble upy,GLdouble upz);

    該函數(shù)定義了視點(diǎn)矩陣,并用該矩陣乘以當(dāng)前矩陣。eyex,eyey,eyez定義了視點(diǎn)的位置;centerx、centery和centerz變量指定了參考點(diǎn)的位置,該點(diǎn)通常為相機(jī)所瞄準(zhǔn)的場(chǎng)景中心軸線上的點(diǎn);upx、upy、upz變量指定了向上向量的方向。

    通常,視點(diǎn)轉(zhuǎn)換操作在模型轉(zhuǎn)換操作之前發(fā)出,以便模型轉(zhuǎn)換先對(duì)物體發(fā)生作用。場(chǎng)景中物體的頂點(diǎn)經(jīng)過(guò)模型轉(zhuǎn)換之后移動(dòng)到所希望的位置,然后再對(duì)場(chǎng)景進(jìn)行視點(diǎn)定位等操作。模型轉(zhuǎn)換和視點(diǎn)轉(zhuǎn)換共同構(gòu)成模型視景矩陣。

    (二)模型變換

    模型變換是在世界坐標(biāo)系中進(jìn)行的。缺省時(shí),物體模型的中心定位在坐標(biāo)系的中心處。OpenGL在這個(gè)坐標(biāo)系中,有三個(gè)命令,可以模型變換。

    1、模型平移

    glTranslate{fd}(TYPE x,TYPE y,TYPE z);

    該函數(shù)用指定的x,y,z值沿著x軸、y軸、z軸平移物體(或按照相同的量值移動(dòng)局部坐標(biāo)系)。

    2、模型旋轉(zhuǎn)

    glRotate{fd}(TYPE angle,TYPE x,TYPE,y,TYPE z);

    該函數(shù)中第一個(gè)變量angle制定模型旋轉(zhuǎn)的角度,單位為度,后三個(gè)變量表示以原點(diǎn)(0,0,0)到點(diǎn)(x,y,z)的連線為軸線逆時(shí)針旋轉(zhuǎn)物體。例如,glRotatef(45.0,0.0,0.0,1.0)的結(jié)果是繞z軸旋轉(zhuǎn)45度。

    3、模型縮放

    glScale{fd}(TYPE x,TYPE y,TYPE z);

    該函數(shù)可以對(duì)物體沿著x,y,z軸分別進(jìn)行放大縮小。函數(shù)中的三個(gè)參數(shù)分別是x、y、z軸方向的比例變換因子。缺省時(shí)都為1.0,即物體沒(méi)變化。程序中物體Y軸比例為2.0,其余都為1.0,就是說(shuō)將立方體變成長(zhǎng)方體。

    (三)投影變換

    經(jīng)過(guò)模型視景的轉(zhuǎn)換后,場(chǎng)景中的物體放在了所希望的位置上,但由于顯示器只能用二維圖象顯示三維物體,因此就要靠投影來(lái)降低維數(shù)(投影變換類似于選擇相機(jī)的鏡頭)。

    事實(shí)上,投影變換的目的就是定義一個(gè)視景體,使得視景體外多余的部分裁剪掉,最終進(jìn)入圖像的只是視景體內(nèi)的有關(guān)部分。投影包括透視投影(Perspective Projection)和正視投影(Orthographic Projection)兩種。

     透視投影,符合人們心理習(xí)慣,即離視點(diǎn)近的物體大,離視點(diǎn)遠(yuǎn)的物體小,遠(yuǎn)到極點(diǎn)即為消失,成為滅點(diǎn)。它的視景體類似于一個(gè)頂部和底部都被進(jìn)行切割過(guò)的棱椎,也就是棱臺(tái)。這個(gè)投影通常用于動(dòng)畫(huà)、視覺(jué)仿真以及其它許多具有真實(shí)性反映的方面。

    OpenGL透視投影函數(shù)有兩個(gè),其中函數(shù)glFrustum()的原型為:

    void glFrustum(GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);

    它創(chuàng)建一個(gè)透視視景體。其操作是創(chuàng)建一個(gè)透視投影矩陣,并且用這個(gè)矩陣乘以當(dāng)前矩陣。這個(gè)函數(shù)的參數(shù)只定義近裁剪平面的左下角點(diǎn)和右上角點(diǎn)的三維空間坐標(biāo),即(left,bottom,-near)和(right,top,-near);最后一個(gè)參數(shù)far是遠(yuǎn)裁剪平面的Z負(fù)值,其左下角點(diǎn)和右上角點(diǎn)空間坐標(biāo)由函數(shù)根據(jù)透視投影原理自動(dòng)生成。near和far表示離視點(diǎn)的遠(yuǎn)近,它們總為正值。該函數(shù)形成的視景體如圖三所示。

    基于VC++的OpenGL編程講座之坐標(biāo)變換(圖三)
    圖三、透視投影視景體

    另一個(gè)透視函數(shù)是:

    void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear, GLdouble zFar);

    它也創(chuàng)建一個(gè)對(duì)稱透視視景體,但它的參數(shù)定義于前面的不同,參數(shù)fovy定義視野在X-Z平面的角度,范圍是[0.0, 180.0];參數(shù)aspect是投影平面寬度與高度的比率;參數(shù)zNear和Far分別是遠(yuǎn)近裁剪面沿Z負(fù)軸到視點(diǎn)的距離,它們總為正值。
    基于VC++的OpenGL編程講座之坐標(biāo)變換(圖四)
    圖四、透視投影視景體

    以上兩個(gè)函數(shù)缺省時(shí),視點(diǎn)都在原點(diǎn),視線沿Z軸指向負(fù)方向。

    正射投影,又叫平行投影。這種投影的視景體是一個(gè)矩形的平行管道,也就是一個(gè)長(zhǎng)方體,如圖五所示。正射投影的最大一個(gè)特點(diǎn)是無(wú)論物體距離相機(jī)多遠(yuǎn),投影后的物體大小尺寸不變。這種投影通常用在建筑藍(lán)圖繪制和計(jì)算機(jī)輔助設(shè)計(jì)等方面,這些行業(yè)要求投影后的物體尺寸及相互間的角度不變,以便施工或制造時(shí)物體比例大小正確。

    基于VC++的OpenGL編程講座之坐標(biāo)變換(圖五)

    圖五、正射投影視景體

    OpenGL正射投影函數(shù)也有兩個(gè),一個(gè)函數(shù)是:

    void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top, GLdouble near,GLdouble far)

    它創(chuàng)建一個(gè)平行視景體。實(shí)際上這個(gè)函數(shù)的操作是創(chuàng)建一個(gè)正射投影矩陣,并且用這個(gè)矩陣乘以當(dāng)前矩陣。其中近裁剪平面是一個(gè)矩形,矩形左下角點(diǎn)三維空間坐標(biāo)是(left,bottom,-near),右上角點(diǎn)是(right,top,-near);遠(yuǎn)裁剪平面也是一個(gè)矩形,左下角點(diǎn)空間坐標(biāo)是(left,bottom,-far),右上角點(diǎn)是(right,top,-far)。所有的near和far值同時(shí)為正或同時(shí)為負(fù)。如果沒(méi)有其他變換,正射投影的方向平行于Z軸,且視點(diǎn)朝向Z負(fù)軸。這意味著物體在視點(diǎn)前面時(shí)far和near都為負(fù)值,物體在視點(diǎn)后面時(shí)far和near都為正值。

    另一個(gè)函數(shù)是:

    void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)

    它是一個(gè)特殊的正射投影函數(shù),主要用于二維圖像到二維屏幕上的投影。它的near和far缺省值分別為-1.0和1.0,所有二維物體的Z坐標(biāo)都為0.0。因此它的裁剪面是一個(gè)左下角點(diǎn)為(left,bottom)、右上角點(diǎn)為(right,top)的矩形。

      基于VC++的OpenGL編程講座之坐標(biāo)變換(3) 

    (四)視口變換。

    視口變換就是將視景體內(nèi)投影的物體顯示在二維的視口平面上。運(yùn)用相機(jī)模擬方式,我們很容易理解視口變換就是類似于照片的放大與縮小。在計(jì)算機(jī)圖形學(xué)中,它的定義是將經(jīng)過(guò)幾何變換、投影變換和裁剪變換后的物體顯示于屏幕窗口內(nèi)指定的區(qū)域內(nèi),這個(gè)區(qū)域通常為矩形,稱為視口。OpenGL中相關(guān)函數(shù)是:

    glViewport(GLint x,GLint y,GLsizei width, GLsizei height);

    這個(gè)函數(shù)定義一個(gè)視口。函數(shù)參數(shù)(x, y)是視口在屏幕窗口坐標(biāo)系中的左下角點(diǎn)坐標(biāo),參數(shù)width和height分別是視口的寬度和高度。缺省時(shí),參數(shù)值即(0, 0, winWidth, winHeight) 指的是屏幕窗口的實(shí)際尺寸大小。所有這些值都是以象素為單位,全為整型數(shù)。

    (5)裁剪變換

    在OpenGL中,除了視景體定義的六個(gè)裁剪平面(上、下、左、右、前、后)外,用戶還可自己再定義一個(gè)或多個(gè)附加裁剪平面,以去掉場(chǎng)景中無(wú)關(guān)的目標(biāo),如圖六所示。

    基于VC++的OpenGL編程講座之坐標(biāo)變換(圖六)

    圖六、附加裁剪平面

    附加平面裁剪函數(shù)為:

    1、void glClipPlane(GLenum plane,Const GLdouble *equation);

    函數(shù)參數(shù)equation指向一個(gè)擁有四個(gè)系數(shù)值的數(shù)組,這四個(gè)系數(shù)分別是裁剪平面Ax+By+Cz+D=0的A、B、C、D值。因此,由這四個(gè)系數(shù)就能確定一個(gè)裁剪平面。參數(shù)plane是GL_CLIP_PLANEi(i=0,1,...),指定裁剪面號(hào)。

    在調(diào)用附加裁剪函數(shù)之前,必須先啟動(dòng)glEnable(GL_CLIP_PLANEi),使得當(dāng)前所定義的裁剪平面有效;當(dāng)不再調(diào)用某個(gè)附加裁剪平面時(shí),可用glDisable(GL_CLIP_PLANEi)關(guān)閉相應(yīng)的附加裁剪功能。

    下面這個(gè)例子不僅說(shuō)明了附加裁剪函數(shù)的用法,而且調(diào)用了gluPerspective()透視投影函數(shù),讀者可以細(xì)細(xì)體會(huì)其中的用法。例程如下:

    1. #include "glos.h"  
    2.  #include  
    3.  #include  
    4.  #include  
    5.  void myinit(void);  
    6.  void CALLBACK myReshape(GLsizei w, GLsizei h);  
    7.  void CALLBACK display(void);  
    8.  void CALLBACK display(void)  
    9.  {  
    10.    GLdouble eqn[4] = {1.0, 0.0, 0.0, 0.0};  
    11.    glClear(GL_COLOR_BUFFER_BIT);  
    12.    glColor3f (1.0, 0.0, 1.0);  
    13.    glPushMatrix();  
    14.    glTranslatef (0.0, 0.0, -5.0);  
    15.    /* clip the left part of wire_sphere : x<0 */  
    16.    glClipPlane (GL_CLIP_PLANE0, eqn);  
    17.    glEnable (GL_CLIP_PLANE0);  
    18.    glRotatef (-90.0, 1.0, 0.0, 0.0);  
    19.    auxWireSphere(1.0);  
    20.    glPopMatrix();  
    21.    glFlush();  
    22.  }  
    23.  void myinit (void)  
    24.  {  
    25.    glShadeModel (GL_FLAT);  
    26.  }  
    27.  void CALLBACK myReshape(GLsizei w, GLsizei h)  
    28.  {  
    29.    glViewport(0, 0, w, h);  
    30.    glMatrixMode(GL_PROJECTION);  
    31.    glLoadIdentity();  
    32.      gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);  
    33.    glMatrixMode(GL_MODELVIEW);  
    34.  }  
    35.  void main(void)  
    36.  {  
    37.    auxInitDisplayMode (AUX_SINGLE | AUX_RGB);  
    38.    auxInitPosition (0, 0, 500, 500);  
    39.    auxInitWindow ("Arbitrary Clipping Planes");  
    40.    myinit ();  
    41.    auxReshapeFunc (myReshape);  
    42.    auxMainLoop(display);  
    43.  }  

     

    posted on 2010-08-24 13:44 MEYE 閱讀(400) 評(píng)論(0)  編輯  收藏 所屬分類: Android3D
    主站蜘蛛池模板: 亚洲视频无码高清在线| 免费99精品国产自在现线| 亚洲AV无码一区二区三区DV| 九九热久久免费视频| 青青草国产免费国产是公开| 国产亚洲福利一区二区免费看| 亚洲av乱码一区二区三区按摩| 女人被男人躁的女爽免费视频| 亚洲综合精品第一页| 四虎影院在线免费播放| 亚洲精品无码久久久久APP| 免费高清小黄站在线观看| 亚洲国产精品网站在线播放| 日韩免费无码一区二区视频| 欧美色欧美亚洲另类二区| 免费a级黄色毛片| fc2免费人成为视频| 亚洲午夜久久久久久噜噜噜| 野花香在线视频免费观看大全| 无码久久精品国产亚洲Av影片| 99精品视频在线视频免费观看| 亚洲日产2021三区在线| 日韩av无码成人无码免费| 亚洲欧美国产国产一区二区三区 | 四虎国产精品成人免费久久 | 一区二区三区亚洲视频| 亚洲专区中文字幕| 一二三四视频在线观看中文版免费| 亚洲 欧洲 自拍 另类 校园| 精品少妇人妻AV免费久久洗澡 | 亚洲一区二区三区高清视频| 好爽…又高潮了免费毛片| 国产精品亚洲精品爽爽| 亚洲色婷婷综合开心网| 最新国产乱人伦偷精品免费网站| 久久亚洲精品国产精品| 免费看国产成年无码AV片| 妇女自拍偷自拍亚洲精品| 曰韩亚洲av人人夜夜澡人人爽| 日本在线免费观看| 亚洲综合校园春色|