• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            The Coder

            I am a humble coder.

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              4 隨筆 :: 4 文章 :: 9 評論 :: 0 Trackbacks

            OpenGL 中場景進行變換,要經(jīng)歷一些過程:視圖變換 à 模型變換 à 投影變換,然后到了窗口坐標。這幾個變換開始的時候把我搞很混,這幾天整理一下。

            ?????? 一般書上把這幾個變換用照相機類比,其實每個變換都是產(chǎn)生著一個 4x4 矩陣,然后與當前矩陣 (Current Matrix) 相乘,得到一個坐標變換矩陣,最后把世界坐標系(歐式空間)中的物體變換到屏幕坐標系中。這里梳理一下概念:

            ?????? 1 、視圖變換( VIEW Transformation ):它類似將照相機指向物體,即確定視點(觀察點)的位置和觀察方向。一般用的函數(shù)為 glu 封裝的函數(shù):

            void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,? --------- 觀察點

            ?????? GLdouble centrex, GLdouble centrey, GLdouble centrez,? -- 視線方向:從 eye 指向 centre

            ?????? GLdouble upx, GLdouble upy, GLdouble upz ------------ 視圖體自下而上的方向

            ?)

            ?????? 這個函數(shù)會產(chǎn)生一個視圖矩陣,并右乘到當前矩陣上。模型變換通常發(fā)生在模型變換之前。其實,視圖變換也是通過平移和旋轉(zhuǎn)得到的,觀察位置與物體位置之間是個相對的狀態(tài),我們也把視圖變換和模型變換統(tǒng)一成一個變換,產(chǎn)生一個矩陣:模型視圖變換矩陣。

            ?????? 2 、模型變換 (MODEL Transformation) :它確定模型的位置和方向,對模型進行旋轉(zhuǎn)、平移和縮放。用到三個子函數(shù): glTranslate*(x, y, z) 、 glRotate*(x, y, z) glScale*(x, y, z) 。每個函數(shù)都會產(chǎn)生一個矩陣,并右乘當前矩陣。

            ?????? 3 、投影變換( PROJECTION Transformation ):產(chǎn)生一個六面的視圖體,把視圖體以外的場景剪裁掉,把視圖體內(nèi)的物體、場景作為繪制對象,讓“照相機拍攝”。兩種投影方式,兩個投影函數(shù): glFrustum(left, right, bottom, top, near, far) ,

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

            這兩個函數(shù)的參數(shù)非常對稱,都是構(gòu)筑了一個六面體,形成可視范圍。它們都產(chǎn)生一個矩陣,并左乘當前矩陣。(當然,還有 glu 的兩個函數(shù))。

            ??????

            ?????? 要理解整個過程,關(guān)鍵在理解當前變換矩陣 CTM ,(簡稱為 C )。它是一個狀態(tài)概念,應(yīng)用到 OpenGL 流水線中的每一個定點: P = C*P’ 。這條等式是對同一個點在兩個坐標系體統(tǒng)之間進行轉(zhuǎn)換,從右邊的坐標系下的坐標( P’ )轉(zhuǎn)換到左邊的坐標系下的坐標( P )。而矩陣 C 4x4 的齊次坐標矩陣,它都蘊含著一個局部坐標系信息:以右邊坐標系為參考坐標系統(tǒng),左邊坐標系的位置和方向。

            ?????? 用手工定義一個矩陣,如下(按 OpenGL 矩陣方式定義。與數(shù)學定義矩陣的方式轉(zhuǎn)置):

            ?????? CTM[16] = { a0, a1, a2, a3,???????? // x 軸的方向向量

            ???????????????????? ?? a4, a5, a6, a7,????????? // y 軸的方向向量

            ???????????????????? ?? a8, a9, a10, a11,????????????? // z 軸的方向向量

            ???????????????????? ?? a12, a13, a14, a15??? // 原點的位置

            ??????????????????????????? }

            ??????

            ?????? 再來考察當前變換矩陣 CTM ,它是在 OpenGL 流水線中一個模型視圖矩陣和一個投影矩陣的復(fù)合。 CTM = P*C*M 。(注意到上面提到的左乘右乘了嗎?)
            ?aa.bmp

            我們來分析一個簡單的例子: 

            ?

            ?

            ?1 #define ?NUM?0.70710678118654746
            ?2 // 注意這個矩陣是正交的,沒有正交就用,好像有放縮作用
            GLfloat Tmat1[16] = { NUM, NUM, 0.0, 0.0,
            ??????????????????? -NUM, NUM, 0.0, 0.0,
            ???????????????????? 0.0, 0.0, 1.0, 0.0,
            ???????????????????? 0.0, 0.0, 0.0, 1.0};

            GLfloat Tmat2[16] = { 1.0, 0.0, 0.0, 0.0,
            ????????????????????? 0.0, 1.0, 0.0, 0.0,
            ????????????????????? 0.0, 0.0, 1.0, 0.0,
            ????????????????????? 1.0, 0.0, 0.0, 1.0,
            ??????????????????????? };

            ?7 void ?setupRC( void )
            ?8 {
            ?9 ????glClearColor( 0.0f ,? 0.0f ,? 0.0f ,? 1.0f );
            10 ????glShadeModel(GL_FLAT);
            11 }

            12
            13 void ?RenderScene( void )
            14 {
            15 ????printf( " RenderScene\n " );??
            16 glClear(GL_COLOR_BUFFER_BIT);
            17 glColor3f( 0.0f ,? 1.0f ,? 1.0f );
            18 ????glMatrixMode(GL_MODELVIEW);
            19 ????glLoadIdentity();
            20 ????gluLookAt( 0.0 ,? 0.0 ,? 5.0 ,???????? // ?view?point
            21 ?????????????? 0.0 ,? 0.0 ,? 0.0 ,???????? // ?focus?point
            22 ?????????????? 0.0 ,? 1.0 ,? 0.0 );??????? // ?up?vector
            23
            24 ? ?glutSolidCube( 0.5 );???????????????? //  原點的參考位置
            25 ????glMultMatrixf(Tmatr1);???????????????? // 這個矩陣的動作和下面的兩個變換是一樣的。
            ???????????????glMultMatrixf(Tmatr2);
            26 // ????glRotatef(45.0,?0.0,?0.0,?1.0);
            27 // ????glTranslatef(3.0,?0.0,?0.0);
            28 ????glutSolidCube( 1.0 );
            29
            30 ????glutSwapBuffers();
            31 }

            32
            33 void ?ChangeSize( int ?w,? int ?h)
            34 {
            35 ????printf( " ChangeSize\n " );??? // 從這里看出,是先調(diào)用ChangeSize()的
            36 ????GLfloat?nRange? = ? 10.0f ;
            37
            38 ???? if (h? == ? 0 )
            39 ????????h? = ? 1 ;
            40 ????GLfloat?fRatio? = ?(GLfloat)w? / ?(GLfloat)h;
            41
            42 ????glMatrixMode(GL_PROJECTION);
            43 ????glLoadIdentity();
            44
            45 ???? if (w? <= ?h)
            46 ????????glOrtho( - nRange,?nRange,? - nRange? / ?fRatio,?nRange? / ?fRatio,? 1.0 ,?nRange);
            47 ???? else
            48 ????????glOrtho( - nRange? * ?fRatio,?nRange? * ?fRatio,? - nRange,?nRange,? 1.0 ,?nRange);
            49
            50 ????glViewport( 0 ,? 0 ,?w?,h);
            51
            52 ????glMatrixMode(GL_MODELVIEW);
            53 ????glLoadIdentity();
            54 }

            55
            56 int ?main( int ?argc,? char * ?argv[])
            57 {
            58 ????glutInit( & argc,?argv);
            59 ????glutInitDisplayMode(GLUT_RGB? | ?GLUT_DOUBLE);
            60 ????glutInitWindowSize( 800 ,? 600 );
            61 ????glutCreateWindow( " example " );
            62
            63 ????glutReshapeFunc(ChangeSize);
            64 ????glutDisplayFunc(RenderScene);
            65
            66 ????setupRC();
            67
            68 ????glutMainLoop();
            69
            70 ????std::cout? << ? " Hello?world! " ? << ?std::endl;
            71 ???? return ? 0 ;
            72 }

            73

            glRotatef(45.0, 0.0, 0.0, 1.0)???

            glTranslatef(3.0, 0.0, 0.0);  

            這兩個變換,可以看成:

            ?????? glMultMatrixf(R);

            ?????? glMultMatrixf(T);

            R,T 都是右乘到 CTM CTM = CTM * R * T

            對模型變換的理解有兩種:

            1、在全局固定坐標系下,對物體進行變換。這時候,我們要以相反的順序來考慮代碼中的變換函數(shù)了,它的實際過程是這樣 P = CTM *( R*(T* p’)) 。

            首先、對物體進行平移,平移到坐標( 3.0, 0.0, 0.0 )?! ∪缓?,把物體相對原點繞z軸旋轉(zhuǎn)45度。

            2、物體捆綁在局部坐標系下,所有的變換都是坐標系進行的。這時,我們用順序來看這個變換。

            glRotatef(45.0, 0.0, 0.0, 1.0) 產(chǎn)生一個齊次矩陣 R( 這可是代表一個局部坐標系哦 ) ? ,即局部坐標系 R 相對剛才開始的坐標系 I (單位矩陣)作了旋轉(zhuǎn)變換,繞旋轉(zhuǎn)了45度。

            glTranslatef(3.0, 0.0, 0.0) 產(chǎn)生一個齊次矩陣 T (也是代表了一個局部坐標系),相對 R 坐標系沿x軸( R 系)平移了3個單位,得到了自己的局部坐標系 T 。

            最后在這個局部坐標系 T 下畫了 Cube 。

            代碼中的 Tmat = R * T ,它也是從 T 坐標系變換到 R 坐標系,再變換到最后的模型視圖的世界坐標系。

            ?

            ?

            后注:

            ?????? 對坐標系的幾何變換是 既采用基于齊次坐標的矩陣表達形式 ! 又在歐氏幾何的 Cartesian 坐標系下以對其進行說明性的定義 . 由于齊次坐標是射影幾何的語言工具 ! 前者表明幾何變換的表達是基于射影幾何的后者則帶有歐氏幾何色彩 ,所以對它的表述清晰統(tǒng)一的表述比較難。本文寫的也比較零散,有語焉不詳、理解錯誤指出,請多多指正!

            ?

            posted on 2006-08-11 22:27 TH 閱讀(5941) 評論(8)  編輯 收藏 引用

            評論

            # re: OpenGL的視圖變換 2006-08-15 12:09 可冰
            可以完全用OpenGL來做GUI嗎,比如文本輸入框、對話框等等,比起MFC來哪個好用一些。我最近要做GUI程序,但又不想學MFC,不知道該用什么好。  回復(fù)  更多評論
              

            # re: OpenGL的視圖變換 2006-08-15 16:03 TH
            @可冰
            呵呵,OpenGL本身是沒有對窗口進行處理能力的.需要借助GLUT庫,處理一些簡單的窗口應(yīng)用.當然處理能力可能不是很強.
            還有一個庫GLUI也許可以滿足你的要求:
            /**
            GLUI is a GLUT-based C++ user interface library which provides controls such as buttons, checkboxes, radio
            buttons, spinners, and listboxes to OpenGL applications. It is window-system independent, relying on GLUT to
            handle all system-dependent issues, such as window and mouse management.
            **/
            當然還有很多很優(yōu)秀的GUI庫.如smartwin++,wxWidgets等.每種都有其不同的設(shè)計特點.按需學習了~~~  回復(fù)  更多評論
              

            # re: OpenGL的視圖變換 2006-09-08 00:49 嘿嘿
            被這個冬冬搞的暈死了   回復(fù)  更多評論
              

            # re: OpenGL的視圖變換 2006-10-02 20:01 hrbeu
            我的頭都暈死了 變換感覺沒有什么難得的啊 可是操作起來 我已經(jīng)迷糊了
            還好 還有一起學OpenGl的朋友 讓我覺得不再孤獨   回復(fù)  更多評論
              

            # re: OpenGL的視圖變換[未登錄] 2007-03-22 09:08 sophia
            好東東
            這兩天看得頭暈
            上午正想準備,看到了,
            收藏了!

            模型變換是對坐標系的變換!  回復(fù)  更多評論
              

            # re: OpenGL的視圖變換 2007-03-31 20:06 hao a
            hao a a a a   回復(fù)  更多評論
              

            # re: OpenGL的視圖變換 2007-10-21 23:48 roger
            好像有點小錯誤,“它都蘊含著一個局部坐標系信息:以右邊坐標系為參考坐標系統(tǒng),左邊坐標系的位置和方向?!?
            P=MP',設(shè)P是O系坐標,P'是O'系坐標, 那么,按照上述結(jié)論,以O(shè)‘系為參考,O坐標系的描述為M。那么帶入P=MP',有:
            I=MM

            這是錯誤的。

            其實:設(shè)S為O系下O‘系的坐標,那么有:
            O系下O‘系的描述=M*O’系下O‘系的描述,即:
            S=M*I
            S=M
            所以M是O系下O‘系的坐標,即左邊坐標系下,右邊坐標系的坐標。

            比如,O系下O'系的原點在(3,0,0)’處,那么有:
            M=
            1003
            0100
            0010
            0001

            假設(shè)O‘系中有一個點(3,0,0,1)‘,那么,O系中,它在:
            M*P‘=(6,0,0,0)  回復(fù)  更多評論
              

            # re: OpenGL的視圖變換 2009-02-06 04:17 xinxin
            博主這文章的觀眾還是挺多的,而且博主挺謙虛的呵呵.
            但是,我在此留言是希望讀者在以此文為參考的同時也再在搜索引擎上搜索一下其他文章...
            因為這里頭的講述的某些小地方實在是容易讓人誤解的。特別是左右乘的概念。
            而我相信博主思路是正確的,這些都是表述上的問題而已。  回復(fù)  更多評論
              

            久久婷婷色香五月综合激情| 久久亚洲国产午夜精品理论片 | 久久人爽人人爽人人片AV | 大美女久久久久久j久久| 99久久免费只有精品国产| 久久综合视频网站| 久久久久国产精品嫩草影院| 狠狠色婷婷久久一区二区三区| 久久夜色精品国产亚洲| 97精品依人久久久大香线蕉97| 久久伊人精品青青草原高清| 国产毛片欧美毛片久久久| 9191精品国产免费久久| 久久精品国产亚洲av麻豆色欲| 久久精品国产黑森林| 狠狠色丁香久久婷婷综| 97久久婷婷五月综合色d啪蜜芽 | 日本精品一区二区久久久| 精品久久久无码人妻中文字幕豆芽| 久久精品国产亚洲av瑜伽| 97久久精品国产精品青草| 亚洲综合熟女久久久30p| 亚洲午夜福利精品久久| 国产精品免费看久久久香蕉| 97精品国产91久久久久久| 久久亚洲精品中文字幕| 国产精品乱码久久久久久软件 | 99久久婷婷国产综合精品草原| 一本色道久久88精品综合| 久久丫忘忧草产品| 成人午夜精品无码区久久| 伊人久久大香线蕉精品不卡| 久久亚洲天堂| 2021国内精品久久久久久影院| 久久国产精品无码网站| 国产午夜精品久久久久九九电影| 亚洲一区中文字幕久久| 国产成人无码精品久久久免费 | 亚洲欧美久久久久9999| 中文字幕精品无码久久久久久3D日动漫 | 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 |