乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      OpenGL學(xué)習(xí)腳印: 關(guān)于gluLookAt函數(shù)的理解

       方海龍的書館 2014-10-28

      OpenGL學(xué)習(xí)腳印: 關(guān)于gluLookAt函數(shù)的理解

      寫在前面

                     本節(jié)借助gluLookAt函數(shù),推導(dǎo)世界坐標(biāo)轉(zhuǎn)換到照相機(jī)坐標(biāo)的一種方法,重點在于理解UVN相機(jī)坐標(biāo)系,以及變換矩陣的推導(dǎo)。限于筆者水平,如果錯誤請糾正我。



                    gluLookAt函數(shù)提供給用戶完成模式變換(model-view transformation)中,在將模型坐標(biāo)系轉(zhuǎn)換都世界坐標(biāo)系后,進(jìn)行世界坐標(biāo)系到照相機(jī)坐標(biāo)系的轉(zhuǎn)換。實際上,照相機(jī)的定位也是在世界坐標(biāo)系下定義的,這里的轉(zhuǎn)換,可以理解為:  從照相機(jī)的角度解釋世界坐標(biāo)系中物體的坐標(biāo)。通過構(gòu)造一個UVN坐標(biāo)系來簡化這一轉(zhuǎn)換。

                    先直觀感受下UVN,UVN坐標(biāo)系中的照相機(jī)模型如下圖所示:

       

                   借助下圖正式定義UVN相機(jī)坐標(biāo)系:


                     與UVN相關(guān)的概念包括:

      •            相機(jī)位置,或者叫做視點(eyepoint):  觀察參考點 (View Reference Point)
      •            相機(jī)鏡頭方向,通過觀察平面的法向量指定:   觀察平面法向量VPN (View Plane Normal)
      •            相機(jī)頂部正朝向:VUV (View Up Vector)

           形象的表達(dá)為:


          gluLookAt函數(shù)原型為:

         

      1. void gluLookAt(GLdouble eyeX,  GLdouble eyeY,  GLdouble eyeZ,   
      2.   
      3.                                GLdouble centerX,  GLdouble centerY,  GLdouble centerZ,  
      4.   
      5.                               GLdouble upX,  GLdouble upY,  GLdouble upZ);  


      官網(wǎng)關(guān)于此函數(shù)的描述:

      gluLookAt        通過指定一個視點、表面場景中心的參考點以及up向量來構(gòu)造一個視變換矩陣。

      這個矩陣將代表場景中心的參考點映射到-Z軸,視點映射成為原點。當(dāng)使用一個特定的投影矩陣時,場景的中心就映射到視口的中心。類似地,由up向量描述的方向投影到投影平面成為+y軸,這樣它在視口中向上指向。up向量必須不能與從視點到參考點的直線平行。
             
      那么如何確定u-v-n坐標(biāo)系呢?計算公式如下:



           這里需要注意: OpenGL中使用的相機(jī)坐標(biāo)系是右手坐標(biāo)系,UVN坐標(biāo)系是左手坐標(biāo)系。在構(gòu)造實際變換矩陣的過程中,OpenGL

      需要將-n軸翻轉(zhuǎn)為相機(jī)坐標(biāo)系的+z軸,uv軸定位相機(jī)坐標(biāo)系的+x和+y軸。這與推導(dǎo)相機(jī)變換矩陣一文最后的結(jié)果矩陣有所不同。


            如何構(gòu)造視變換矩陣?

           視變換就是在相機(jī)坐標(biāo)系下解釋世界坐標(biāo)系下的點。而這個變換矩陣的構(gòu)造,可以看做將相機(jī)坐標(biāo)系變換到與原來的世界坐標(biāo)系重合。而將世界坐標(biāo)系變換到與相機(jī)坐標(biāo)系重合,可以看做是這個所求變換的逆過程。

          將世界坐標(biāo)系變換到與相機(jī)坐標(biāo)系重合,實際上進(jìn)行了兩個步驟:  第一步將世界坐標(biāo)系旋轉(zhuǎn)一定角度記作變換R,再將世界坐標(biāo)系平移到視點位置記作T,那么這個變換矩陣記為M=TR。要將世界坐標(biāo)系的點變換到照相機(jī)坐標(biāo)系下,需要使用矩陣M的逆矩陣,即: inverse(M)=inverse(R)*inverse(T)。即所求變換矩陣為inverse(M)。

      平移矩陣的逆矩陣形式簡單,就是取平移量(eyex,eyey,eyez)的相反數(shù),即:

      那么現(xiàn)在的關(guān)鍵是如何求出旋轉(zhuǎn)矩陣R?

      上面我們構(gòu)造的UVN坐標(biāo)系u-v-n3個基向量可以構(gòu)造成矩陣:


      注意這里對n軸進(jìn)行了翻轉(zhuǎn),構(gòu)成右手照相機(jī)坐標(biāo)系。

      怎么看這個矩陣A呢,矩陣A實際上代表的就是一個旋轉(zhuǎn)矩陣(從矩陣形式上看出)。

      旋轉(zhuǎn)矩陣的一個特點就是它是正交矩陣,即有inverse(A) = transpose(A).(A^-1 = A^T)

      很多教材和博客都說,這里A矩陣可以看做是將世界坐標(biāo)系轉(zhuǎn)換到與照相機(jī)坐標(biāo)系重合時的旋轉(zhuǎn)矩陣,這一點怎么理解呢?

      個人理解,矩陣A第四列為0,0,0,1,可以看做是世界坐標(biāo)系和照相機(jī)坐標(biāo)系原點重合;根據(jù)《OpenGL學(xué)習(xí)腳印: 理解坐標(biāo)系及坐標(biāo)變換(上) 》中所講,矩陣前3列即變換后的基向量,那么這個基向量(都是單位向量)是如何計算出來的呢?就是通過旋轉(zhuǎn)原來的世界坐標(biāo)系的基向量來構(gòu)造的。因此,可以說矩陣A代表的就是將世界坐標(biāo)系旋轉(zhuǎn)到與相機(jī)坐標(biāo)系重合時的旋轉(zhuǎn)矩陣R,即R = A。

      則inverse(R) = inverse(A) = transpose(A)      即為:


      所以gluLookAt所求變換矩陣inverse(M)為:




      gluLookAt的默認(rèn)值是(0, 0, 0, 0, 0,-1, 0, 1, 0);通過計算可得出:u=(1,0,0),v=(0,1,0),n=(0,0,-1),這樣構(gòu)成的矩陣M^-1即為單位矩陣。


      下面通過代碼來驗證下結(jié)論。代碼繪制一個立方體,設(shè)置為透視投影,并通過gluLookAt設(shè)置相機(jī)方位來查看立方體。

      注意,為了便于觀察視變換矩陣,這里并沒有進(jìn)行其他模型變換;手動計算矩陣時使用了數(shù)學(xué)庫glm來進(jìn)行向量點積和叉積運(yùn)算。

       

      1. //計算gluLookAt矩陣  
      2.   
      3. #include <GL/glew.h>  
      4. #include <GL/freeglut.h>  
      5. #include <glm/glm.hpp>  
      6. #include <iostream>  
      7. #pragma comment(lib,"freeglut.lib")  
      8. #pragma comment(lib,"glew32.lib")  
      9.   
      10. void userInit();  
      11. void display( void );  
      12. void keyboardAction( unsigned char key, int x, int y );  
      13. void reshape(int w,int h);  
      14.   
      15. int main( int argc, char **argv )  
      16. {  
      17.     glutInit(&argc, argv);//初始化GLUT  
      18.   
      19.     glutInitDisplayMode( GLUT_RGBA|GLUT_DOUBLE);  
      20.     glutInitWindowPosition(100,100);  
      21.     glutInitWindowSize( 512, 512 );  
      22.     glutCreateWindow( "gluLookAt demo" );  
      23.        
      24.     glewInit();//使用GLEW時,使用該函數(shù)初始化GLEW  
      25.     userInit();//自定義的初始化函數(shù)  
      26.     glutReshapeFunc(reshape);  
      27.     glutDisplayFunc( display );  
      28.     glutKeyboardFunc( keyboardAction );  
      29.     glutMainLoop();  
      30.     return 0;  
      31. }  
      32. //自定義初始化函數(shù)  
      33. void userInit()  
      34. {  
      35.      glClearColor( 0.0, 0.0, 0.0, 0.0 );  
      36.      glColor4f(0.6f,0.5f,0.0,0.0);  
      37. }  
      38. //設(shè)置視變換矩陣  
      39. void setViewMatrix(GLdouble *theMatrix,GLdouble eyex,GLdouble eyey,GLdouble eyez,  
      40.                 GLdouble targetx,GLdouble targety,GLdouble targetz,  
      41.                 GLdouble vupx,GLdouble vupy,GLdouble vupz)  
      42. {     
      43.     glm::vec3 eye(eyex,eyey,eyez),target(targetx,targety,targetz),vup(vupx,vupy,vupz);  
      44.     //構(gòu)造n軸  
      45.     glm::vec3 nvec(target-eye);  
      46.     nvec=glm::normalize(nvec);  
      47.     //構(gòu)造u軸  
      48.     vup = glm::normalize(vup);  
      49.     glm::vec3 uvec = glm::cross(nvec,vup);  
      50.     uvec=glm::normalize(uvec);  
      51.     //構(gòu)造v軸  
      52.     glm::vec3 vvec = glm::cross(uvec,nvec);  
      53.     vvec=glm::normalize(vvec);  
      54.     //設(shè)置4x4矩陣  
      55.     memset(theMatrix,0,sizeof(GLdouble)*16);  
      56.   
      57.     theMatrix[0] = uvec.x;  
      58.     theMatrix[4] = uvec.y;  
      59.     theMatrix[8] = uvec.z;  
      60.     theMatrix[12 ] = -glm::dot(eye,uvec);  
      61.   
      62.     theMatrix[1] = vvec.x;  
      63.     theMatrix[5] = vvec.y;  
      64.     theMatrix[9] = vvec.z;  
      65.     theMatrix[13] = -glm::dot(eye,vvec);  
      66.   
      67.     //注意這行數(shù)據(jù)  
      68.     theMatrix[2] = -nvec.x;  
      69.     theMatrix[6] = -nvec.y;  
      70.     theMatrix[10] = -nvec.z;  
      71.     theMatrix[14] = glm::dot(eye,nvec);  
      72.   
      73.     theMatrix[15] = 1.0;  
      74. }  
      75. void reshape(int w,int h)  
      76. {  
      77.     glViewport(0,0,GLsizei(w),GLsizei(h));  
      78.     glMatrixMode(GL_PROJECTION);  
      79.     glLoadIdentity();  
      80.     gluPerspective(60.0,(GLfloat)w/(GLfloat)h,1.0,10.0);  
      81.     glMatrixMode(GL_MODELVIEW);  
      82.     glLoadIdentity();  
      83.   
      84.     //gluLookAt(2.0,0.0,1.8,0.0,0.0,0.0,0.0,1.0,0.0);  
      85.   
      86.     //手動構(gòu)造視變換矩陣  
      87.     GLdouble theMatrix[16];  
      88.     setViewMatrix(theMatrix,2.0,0.0,1.8,0.0,0.0,0.0,0.0,1.0,0.0);  
      89.     glMultMatrixd(theMatrix);  
      90.   
      91.     //打印當(dāng)前模視變換矩陣內(nèi)容  
      92.     GLdouble modelViewMat[16];  
      93.     glGetDoublev(GL_MODELVIEW_MATRIX,modelViewMat);  
      94.     for(int i = 0;i<4;i++)  
      95.        for(int j=0;j<4;j++)  
      96.     {  
      97.         fprintf(stdout,"%-.4f\t",modelViewMat[i+4*j]);  
      98.         if((j+1) %4 == 0) fprintf(stdout,"\n");  
      99.     }  
      100. }  
      101. //繪制回調(diào)函數(shù)  
      102. void display( void )  
      103. {  
      104.     glClear( GL_COLOR_BUFFER_BIT);//清除顏色緩存  
      105.     glLineWidth(2.0);  
      106.     glutWireCube(1.0);  
      107.     glutSwapBuffers();  
      108. }  
      109. //鍵盤按鍵回調(diào)函數(shù)  
      110. void keyboardAction( unsigned char key, int x, int y )  
      111. {  
      112.     switch( key ) {  
      113.     case 033:  // Escape key  
      114.     case 'q': case 'Q':  
      115.         exit( EXIT_SUCCESS );  
      116.         break;  
      117.     }  
      118. }  


      使用gluLookAt如下圖左右所示:

      手動計算視變換矩陣,效果如下圖所示:

      可以看出兩者是一樣的,二者的視變換矩陣打印出來均為:

      0.6690  0.0000  -0.7433 0.0000
      0.0000  1.0000  0.0000  0.0000
      0.7433  0.0000  0.6690  -2.6907
      0.0000  0.0000  0.0000  1.0000

      至此證明了上述推導(dǎo)的矩陣確實為OpenGL中使用的視變換矩陣。


      關(guān)于OpenGL gluLookAt官網(wǎng)提供了參考實現(xiàn),可以查看:  GluLookAt code

      另外關(guān)于頂部正朝向vup的理解有更好的通俗解釋,可以查看:Opengl---gluLookAt函數(shù)詳解 。


        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多