1. 程式人生 > >【ARTOOlkit】openGL的glVertex()函式的用法

【ARTOOlkit】openGL的glVertex()函式的用法

       本篇文章算是對OpenGL內容的一些補充,這章內容是教會大家如何在模型外面用函式構建其他模型,繼上篇文章的一個小發現,上篇內容是發現一個標識可以通過函式構建多個模型。

       這次我們利用OpenGL中的模式GL_LINE_LOOP和模式GL_LINES來在茶壺模型外面畫一個長方體。OpenGL中定義的定點放在函式glBegin和glEnd之間,由函式glBegin 的引數指定繪製圖元的型別。

在glBegin()和glEnd()之間可呼叫的函式

函式 函式意義

glVertex*() 設定頂點座標

glColor*() 設定當前顏色

glIndex*() 設定當前顏色表

glNormal*() 設定法向座標

glEvalCoord*() 產生座標

glCallList(),glCallLists() 執行顯示列表

glTexCoord*() 設定紋理座標

glEdgeFlag*() 控制邊界繪製

glMaterial*() 設定材質

首先,我們給大家介紹一下這兩個函式,這兩個函式是glBegin 可支援的OpenGL圖元

GL_LINES:     將指定的頂點用於建立線段。每兩個頂點指定一條單獨的線段。如果頂點的個數是奇數,則忽略最後一個。

GL_LINE_LOOP :     特性和GL_LINE_STRIP相似,只不過最後一條線段是在指定的最後一個和第一個頂點之間繪製。典型情況下,這用於繪製哪些可能違反了GL_POLYGON用法規則的封閉區域。

表示方法:

                      glBegin(GL_LINE_LOOP);

                            glVertex3f( 90.0f, 60.0f, 0.0f );

                            glVertex3f( 90.0f, 60.0f, 0.0f );

                      glEnd();

glVertex3f(x, y, z),這個函式是在空間中確定點的函式。我們用這個函式在茶壺模型外面構建了長方體,並把他寫到我們自己寫的static void drawCuboid()函式中,然後在draw()函式裡面執行,具體程式碼如下,我們的程式碼是在simple2的基礎上添加了程式碼,新增的部分我用紅色標記。

#ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> #include <stdlib.h> #ifndef __APPLE__ #include <GL/gl.h> #include <GL/glut.h> #else #include <OpenGL/gl.h> #include <GLUT/glut.h> #endif #include <AR/gsub.h> #include <AR/video.h> #include <AR/param.h> #include <AR/ar.h>

/* set up the video format globals */

#ifdef _WIN32 char            *vconf = "Data\\WDM_camera_flipV.xml"; #else char            *vconf = ""; #endif

int             xsize, ysize; int             thresh = 100; int             count = 0;

int             mode = 1;//標識位

char           *cparam_name    = "Data/camera_para.dat"; ARParam         cparam;

char           *patt_name      = "Data/patt.hiro"; int             patt_id; int             patt_width     = 80.0; double          patt_center[2] = {0.0, 0.0}; double          patt_trans[3][4];

static void   init(void); static void   cleanup(void); static void   keyEvent( unsigned char key, int x, int y); static void   mainLoop(void); static void   draw( double trans[3][4] );

int main(int argc, char **argv) {     glutInit(&argc, argv);     init();

    arVideoCapStart();     argMainLoop( NULL, keyEvent, mainLoop );     return (0); }

static void   keyEvent( unsigned char key, int x, int y) {     /* quit if the ESC key is pressed */     if( key == 0x1b ) {         printf("*** %f (frame/sec)\n", (double)count/arUtilTimer());         cleanup();         exit(0);     }     //如果鍵盤輸入c     if( key == 'c' ) {         printf("*** %f (frame/sec)\n", (double)count/arUtilTimer());         count = 0;

        mode = 1 - mode;//讓每次鍵盤輸入c都讓mode變化         //此處mode轉換為布林型,如果mode=0,則為假arGetTransMatCont         if( mode ) printf("Continuous mode: Using arGetTransMatCont.\n");         //如果mode不為假,輸出arGetTransMat          else      printf("One shot mode: Using arGetTransMat.\n");     } }

/* main loop */ static void mainLoop(void) {     static int      contF = 0;//靜態變數     ARUint8         *dataPtr;     ARMarkerInfo    *marker_info;     int             marker_num;     int             j, k;

    /* grab a vide frame */     if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {         arUtilSleep(2);         return;     }     if( count == 0 ) arUtilTimerReset();     count++;

    argDrawMode2D();     argDispImage( dataPtr, 0,0 );

    /* detect the markers in the video frame */     if( arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0 ) {         cleanup();         exit(0);     }

    arVideoCapNext();

    /* check for object visibility */     k = -1;     for( j = 0; j < marker_num; j++ ) {         if( patt_id == marker_info[j].id ) {             if( k == -1 ) k = j;             else if( marker_info[k].cf < marker_info[j].cf ) k = j;         }     }     if( k == -1 ) {         contF = 0;         argSwapBuffers();         return;     }

    /*計算攝像頭的轉移矩陣,標識卡和攝像機之間的轉移資訊通過使用函式*/     //mode為0     if( mode == 0 || contF == 0 ) {         arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);     }     else {         //mode為1         arGetTransMatCont(&marker_info[k], patt_trans, patt_center, patt_width, patt_trans);     }     contF = 1;

    draw( patt_trans );

    argSwapBuffers(); }

static void init( void ) {     ARParam  wparam;

    /* open the video path */     if( arVideoOpen( vconf ) < 0 ) exit(0);     /* find the size of the window */     if( arVideoInqSize(&xsize, &ysize) < 0 ) exit(0);     printf("Image size (x,y) = (%d,%d)\n", xsize, ysize);

    /* set the initial camera parameters */     if( arParamLoad(cparam_name, 1, &wparam) < 0 ) {         printf("Camera parameter load error !!\n");         exit(0);     }     arParamChangeSize( &wparam, xsize, ysize, &cparam );     arInitCparam( &cparam );     printf("*** Camera Parameter ***\n");     arParamDisp( &cparam );

    if( (patt_id=arLoadPatt(patt_name)) < 0 ) {         printf("pattern load error !!\n");         exit(0);     }

    /* open the graphics window */     argInit( &cparam, 1.0, 0, 0, 0, 0 ); }

/* cleanup function called when program exits */ static void cleanup(void) {     arVideoCapStop();     arVideoClose();     argCleanup(); }//利用GL_LINE_LOOP和GL_LINES畫長方體,在茶壺外面畫長方體 static void drawCuboid()//畫長方體 {     glBegin(GL_LINE_LOOP);               glVertex3f( 90.0f, 60.0f, 0.0f );               glVertex3f( -90.0f, 60.0f, 0.0f );               glVertex3f( -90.0f, 60.f, 50.0f );               glVertex3f( 90.0f, 60.0f, 50.0f );

              glVertex3f( 90.0f, -60.0f,50.0f );               glVertex3f( -90.0f, -60.0f, 50.0f );               glVertex3f( -90.0f, -60.f, 0.0f );               glVertex3f( 90.0f, -60.0f, 0.0f );     glEnd();

    glBegin(GL_LINES);               glVertex3f( 90.0f, -60.0f, 0.0f );               glVertex3f( 90.0f,-60.0f, 50.0f );               glVertex3f( -90.0f, -60.0f,0.0f );               glVertex3f( -90.0f, 60.0f, 0.0f );

              glVertex3f( -90.0f, -60.f, 50.0f );               glVertex3f( -90.0f, 60.0f, 50.0f );               glVertex3f( 90.0f, 60.0f, 0.0f );               glVertex3f( 90.0f, 60.0f, 50.0f );     glEnd(); } static void draw( double trans[3][4] ) {     double    gl_para[16];     GLfloat   mat_ambient[]     = {0.0, 0.0, 1.0, 1.0};     GLfloat   mat_flash[]       = {0.0, 0.0, 1.0, 1.0};     GLfloat   mat_flash_shiny[] = {50.0};     GLfloat   light_position[]  = {100.0,-200.0,200.0,0.0};     GLfloat   ambi[]            = {0.1, 0.1, 0.1, 0.1};     GLfloat   lightZeroColor[]  = {0.9, 0.9, 0.9, 0.1};          argDrawMode3D();     argDraw3dCamera( 0, 0 );     glClearDepth( 1.0 );     glClear(GL_DEPTH_BUFFER_BIT);     glEnable(GL_DEPTH_TEST);     glDepthFunc(GL_LEQUAL);          /* load the camera transformation matrix */     argConvGlpara(trans, gl_para);     glMatrixMode(GL_MODELVIEW);     glLoadMatrixd( gl_para );

    glEnable(GL_LIGHTING);     glEnable(GL_LIGHT0);     glLightfv(GL_LIGHT0, GL_POSITION, light_position);     glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);     glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);     glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash);     glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);         glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);     glMatrixMode(GL_MODELVIEW);

    glRotatef(90,1,0,0);//旋轉函式,如果不旋轉,茶壺的底座就不在標識卡上     glTranslatef( 25.0, 25.0, 10.0 );//平移函式     glutSolidTeapot(50.0);//茶壺函式     drawCuboid();//畫長方體     glLineWidth(10.0);//設定線寬

    glDisable( GL_LIGHTING );

    glDisable( GL_DEPTH_TEST ); }

結果顯示如下

其中我還添加了一個可以改變構建的長方體的線寬,glLineWidth就是這個函式。

這篇文章教了我們OpenGL中的知識,不僅可以考給出的函式模型來顯示在標識卡上,也可以自己畫出模型,其中用 glVertex3f()函式時,需要確定函式裡面的引數,也就是x,y,z的值,這個需要自己確定出自己已有模型的位置,才好輸入到 glVertex3f函式的引數中,這個我認為是比較難確定的部分。這裡面x,y,z的值都是通過標識卡的座標系來決定的。我們要分清,什麼時候是攝像機的座標系,什麼時候是標識卡的座標系。