【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的值都是通過標識卡的座標系來決定的。我們要分清,什麼時候是攝像機的座標系,什麼時候是標識卡的座標系。