【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),这个函数是在空间中确定点的函数。我们这里X,Y,Z的值都是通过标识卡的坐标系来确定的。如下图所示,。

【ARTOOlkit】openGL的glVertex()函数的用法_第1张图片

我们用这个函数在茶壶模型外面构建了长方体,并把他写到我们自己写的static void drawCuboid()函数中,然后在draw()函数里面执行,具体代码如下,我们的代码是在simple2的基础上添加了代码,添加的部分我用红色标记。

#ifdef _WIN32
#include
#endif
#include
#include
#ifndef __APPLE__
#include
#include
#else
#include
#include
#endif
#include
#include
#include
#include

/* 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 );

              glVertex3f( 90.0f, 40.0f, 0.0f );
              glVertex3f( -90.0f, 40.0f, 0.0f );
              glVertex3f( -90.0f, 40.0f, 50.0f );
              glVertex3f( 90.0f, 40.0f, 50.0f );

              glVertex3f( 90.0f, -40.0f, 50.0f );
              glVertex3f( -90.0f, -40.0f, 50.0f );
              glVertex3f( -90.0f, -40.0f, 0.0f );
              glVertex3f( 90.0f, -40.0f, 0.0f );

              glVertex3f( 90.0f, 20.0f, 0.0f );
              glVertex3f( -90.0f, 20.0f, 0.0f );
              glVertex3f( -90.0f, 20.0f, 50.0f );
              glVertex3f( 90.0f, 20.0f, 50.0f );

              glVertex3f( 90.0f, -20.0f, 50.0f );
              glVertex3f( -90.0f, -20.0f, 50.0f );
              glVertex3f( -90.0f, -20.0f, 0.0f );
              glVertex3f( 90.0f, -20.0f, 0.0f );

              glVertex3f( 90.0f, 0.0f, 0.0f );
              glVertex3f( -90.0f, 0.0f, 0.0f );
              glVertex3f( -90.0f, 0.0f, 50.0f );
              glVertex3f( 90.0f, 0.0f, 50.0f );

              glVertex3f( 90.0f, -0.0f, 50.0f );
              glVertex3f( -90.0f, -0.0f, 50.0f );
              glVertex3f( -90.0f, -0.0f, 0.0f );
              glVertex3f( 90.0f, -0.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 );

              glVertex3f( 90.0f, -40.0f, 0.0f );
              glVertex3f( 90.0f, -40.0f, 50.0f );

              glVertex3f( 90.0f, 40.0f, 0.0f );
              glVertex3f( 90.0f, 40.0f, 50.0f );

              glVertex3f( 90.0f, -20.0f, 0.0f );
              glVertex3f( 90.0f, -20.0f, 50.0f );

              glVertex3f( 90.0f, 20.0f, 0.0f );
              glVertex3f( 90.0f, 20.0f, 50.0f );

              glVertex3f( 90.0f, 0.0f, 0.0f );
              glVertex3f( 90.0f, 0.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 );
}

结果显示如下

【ARTOOlkit】openGL的glVertex()函数的用法_第2张图片
其中我还添加了一个可以改变构建的长方体的线宽,glLineWidth就是这个函数。

这篇文章教了我们OpenGL中的知识,不仅可以考给出的函数模型来显示在标识卡上,也可以自己画出模型,其中用 glVertex3f()函数时,需要确定函数里面的参数,也就是x,y,z的值,这个需要自己确定出自己已有模型的位置,才好输入到 glVertex3f函数的参数中,这个我认为是比较难确定的部分。这里面x,y,z的值都是通过标识卡的坐标系来决定的。我们要分清,什么时候是摄像机的坐标系,什么时候是标识卡的坐标系。

你可能感兴趣的:(AR)