【学习ARTookit】——SimpleTest详解

#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>

#ifndef __APPLE__
#include <GL/gl.h>
#define GLUT_DISABLE_ATEXIT_HACK
#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>

//
// Camera configuration.
//
#ifdef _WIN32
char            *vconf = "Data\\WDM_camera_flipV.xml";  // 摄像机默认参数
#else
char            *vconf = "";
#endif

int             xsize, ysize;  // 窗口 XY 尺寸 
int             thresh = 100;  // 这个参数与摄像头检测标识图部分有关,二值化闸值 
int             count = 0; // 计数器,记录帧数的,后面有专门处理帧的部分 

char           *cparam_name    = "Data/camera_para.dat"; // 摄像机特征参数
ARParam         cparam;

char           *patt_name      = "Data/patt.yourpat"; // 标识图
int             patt_id;

// 标记的大小,下面这3个都是记录标识图几何外形的,在坐标变换时用 
double          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( void );

// 程序入口
int main(int argc, char **argv)
{
    // 初始化OpenGL
    glutInit(&argc, argv);

    // 初始化摄像机参数和显示窗口
    init();

    // 启动摄像机
    arVideoCapStart();

    // 注册响应事件函数(分别是鼠标事件,键盘事件,帧循环)
    argMainLoop( NULL, keyEvent, mainLoop );

    return (0);
}

// 键盘事件响应函数
static void  keyEvent( unsigned char key, int x, int y)
{
    /* 点击ESC退出 */
    if( key == 0x1b ) {
        printf("*** %f (frame/sec)\n", (double)count/arUtilTimer());
        cleanup();  // 释放资源,退出时清理使用过的内存等资源 
        exit(0);
    }
}

/* 主循环:完成标识物的检测和位置的重定位,并渲染模型 */
static void mainLoop(void)
{
    ARUint8         *dataPtr;   // 图像数据 
    ARMarkerInfo    *marker_info;  // 标志信息
    int             marker_num;   // 寻找到的标记号码 
    int             j, k;

    /* 捕捉一个输入视频帧 */
    if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
        arUtilSleep(2);  // 调用延时,如果2毫秒内没有获取图像则程序返回 
        return;
    }

    // 定时器复位 
    if( count == 0 ) arUtilTimerReset();
    count++; // 帧数+1 

    // 渲染前更新摄像头参数,主要是为渲染 2D 或 3D 对象做准备的 
    argDrawMode2D();
    argDispImage( dataPtr, 0,0 );

    // 在摄像头画面中检测标记图案,如果出错,程序退出 
    // 参数说明: dataPtr 帧数据,thresh 二值化闸值,&marker_info 标识特征信息 
    // &marker_num 标识数量 
    if( arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0 ) {
        cleanup();
        exit(0);
    }

    // 获取下一帧图像 
    arVideoCapNext();

    // 下面这部分是寻找标记图案的 
    k = -1; // 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 ) {
        argSwapBuffers(); // 屏幕缓冲 
        return;
    }

    /* 获取标识卡和摄像机之间的转移信息 */
    // 计算出标识图案和摄像头之间的坐标变化
    arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);
    printf("%f%f%f\n",patt_trans[0][3],patt_trans[1][3],patt_trans[2][3]);

    draw(); // 绘图

    argSwapBuffers(); // 屏幕缓冲 
}

// 初始化函数
static void init( void )
{
    ARParam  wparam;

    /* 打开视频通道,vconf包含初始视频的配置,在顶部被定义 */
    if( arVideoOpen( vconf ) < 0 ) exit(0);

    /* 获取视频图像大小,以像素为单位 */
    if( arVideoInqSize(&xsize, &ysize) < 0 ) exit(0);
    printf("Image size (x,y) = (%d,%d)\n", xsize, ysize);

    /* 设置初始相机参数,cparam_name包含摄像机参数 */
    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);
    }

    /* 打开图像窗口,第二个参数为缩放值,适应视频图像格式的值设为1.0,设为2.0时是双倍大小 */
    argInit( &cparam, 1.0, 0, 0, 0, 0 );
}


/* 当退出程序时回收资源 */
static void cleanup(void)
{
    /* 停止视频处理 */
    arVideoCapStop();

    /* 关闭视频路径 */
    arVideoClose();

    /* 清理以及回收资源 */
    argCleanup();
}

// 绘制3D模型,这部分完全属于OpenGL的内容
static void draw( void )
{
    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};

    // 3D绘图模式
    argDrawMode3D(); //切换为3D渲染模式的渲染视图。
    argDraw3dCamera( 0, 0 );
    glClearDepth( 1.0 );//深度缓存,1.0是最大深度,整个物体都被显示
    glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);// 目标像素与当前像素在z方向上值大小比较,
    // GL_LEQUAL:如果目标像素z值<=当前像素z值,则绘制目标像素

    /* 加载摄像机转换矩阵 */
    argConvGlpara(patt_trans, gl_para);//简将ARToolKit矩阵格式转换为openGL矩阵格式。
    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);


    glTranslatef( 0.0, 0.0, 25.0 );
    glutSolidCube(50.0); // 绘制一个50的正方体 
    glDisable( GL_LIGHTING );

    glDisable( GL_DEPTH_TEST );
}

猜你喜欢

转载自blog.csdn.net/qq_37308779/article/details/79596708