详解ARTookit——simpleTest

经过寒假的学习,基本将OpenGL过了一遍,接下来将继续深入了解ARToolkit的例子,这次来看下第一个例子,下面我将源码给出,带有详细的注释,希望有所帮助。

#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>
//
// 相机配置
//
#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.hiro";//标识图
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 );
//static void   drawCuboid();
//主函数
int main(int argc, char **argv)
{
    //初始化OpenGL
    glutInit(&argc, argv);
    //初始化视频捕捉以及读入ARToolkit应用的初始参数信息
    init();
    //调用视频开始函数,输入实时状态
    arVideoCapStart();
    //启动了主要的程序循环
    argMainLoop( NULL, keyEvent, mainLoop );
    return 0;//返回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);
    }
}
//主循环
/* main loop */
static void mainLoop(void)
{
    // 图像数据,unsigned char类型
    ARUint8         *dataPtr;
    // 标记块信息,结构体类型:面积、id、方向dir、自信度、中心点位置、四边的直线方程、顶点坐标4个   
    ARMarkerInfo    *marker_info;
    // 标记信息
    int             marker_num; 
    //寻找到的标记号码
    int             j, k;
    //通过函数arVideoGelImage来捕捉一个输入视频帧,从摄像头获取图像
    if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
        // 从摄像头获取图像数据,如果未获取图像,则2ms后返回  
        arUtilSleep(2);
        return;
    }
    if( count == 0 ) arUtilTimerReset();// 启动程序时,复位定时器 
    count++; // 获取图像后,帧数加一 
    //渲染前更新摄像头参数,主要是为渲染 2D 或 3D 对象做准备的 
    argDrawMode2D();
     // 显示图像  
    argDispImage( dataPtr, 0,0 );
    //在摄像头画面中检测标记图案,如果出错,程序退出
//参数说明: dataPtr 帧数据, thresh 二值化阈值,&marker_info 标识特征信息
//&marker_num 标识数量 ,成功返回0,否则返回-1。
    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;
    }
    // 获取摄像机和标记块之间的坐标变换,其中patt_trans存储变换矩阵是指从标记块坐标系(图像坐标系)到摄像机坐标系的变换矩阵  
    arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);
    //调用绘图函数,使虚拟物体可以被叠加在标识卡上
    draw();
    // 清除渲染缓冲区 
    argSwapBuffers();
}
//应用程序初始化
static void init( void )
{
    //有很多这种类的存在,有兴趣的可以去看看如何实现,没兴趣的可
    //以无视它,只到有什么用,怎么用就好
    ARParam  wparam;
    //打开摄影机路径,出错退出*/
    if( arVideoOpen( vconf ) < 0 ) exit(0);
     // 确定视频图像的大小,出错退出
    if( arVideoInqSize(&xsize, &ysize) < 0 ) exit(0);
    printf("Image size (x,y) = (%d,%d)\n", xsize, ysize);
    //设置初始相机参数*/
    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);
    }
     //打开图形窗口
    //第二个参数定义了一个缩放函数
    argInit( &cparam, 1.0, 0, 0, 0, 0 );
}
//退出时清理程序使用过的内存等资源并关闭视频捕捉
static void cleanup(void)
{
    //停止捕捉
    arVideoCapStop();
    //关闭视频设备
    arVideoClose();
    //清理以及回收资源,真的别指望WINDOWS会自动帮你释放资源
    argCleanup();
}
//画上虚拟物体
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();
    // 对argDrawMode3D()的补充  
    argDraw3dCamera( 0, 0 );
    glClearDepth( 1.0 );
    glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    // 将ARToolkit下的参数矩阵转换为OpenGL下的参数矩阵(使用齐次坐标系)
    argConvGlpara(patt_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);
    //模型的坐标(X,Y,Z)
    //想使用自己的模型,或者修改坐标,那就要操作下面这两个函数了
    glTranslatef( 0,0,0);
    glutSolidTeapot(50.0);//绘制一个边长为50的茶壶
    //drawCuboid();
    glDisable( GL_LIGHTING );
    glDisable( GL_DEPTH_TEST );
}
/*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.0f,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.0f,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.0f,50.0f);  
        glVertex3f(-90.0f,60.0f,50.0f);
        glVertex3f(90.0f,60.0f,0.0f);  
        glVertex3f(90.0f,60.0f,50.0f);
    glEnd();
}*/

效果图如下:

这里写图片描述

接下来我们将在茶壶周围画上一个长方体,具体操作如下,将上面代码中的注释掉的代码复原,即可。这时OpenGL的功能就体现出来了,在draw函数中,增加一个函数,drawCuboid()这个函数主要是调用OpenGL中划线的函数,将八个点连起来,形成一个长方体,值得注意的是坐标轴的转换,OpenGL的坐标轴与ARToolkit标识卡的坐标轴相同,可以自己用 glTranslatef()函数来调整平移的距离,从而知道画出的图形的坐标轴。
效果图如下:

这里写图片描述

希望小伙伴们赶快尝试吧!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值