【学习ARToolkit小记之六】 开发第一个ARToolkit程序(Developing your First Application)

接上一则:ARToolkit(5):解决“error LNK2019: 无法解析的外部符号 ___glutCreateWindowWithExit@8”错误(http://blog.csdn.net/qingyang8513/article/details/45339445


这部分内容参考了官网教程和网上一些帖子,同时添加了自己如何创建一个ARToolkit程序,而不是仅仅翻译官网的教程,到目前为止还没有找到一篇从创建工程开始的帖子。由于自己的水平有限,可能会有一些错误,仅供自己学习与记录,同时也给刚刚入门的小白们一个方向。

过程中可能会遇到一个问题,在上一则ARToolkit(5)中已有总结,如果遇到同样的问题请参考前一则内容。

下面使用VS2010从创建自己的项目开始,同时参考ARToolkit例程ARToolKit\examples\simple\simpleTest.c中的程序,并对程序做详细的注释。


一、开发环境

1、操作系统:Windows 7(64位)

2、编程环境:Microsoft Visual Studio 2010

3、ARToolkit版本:ARToolKit-2.72.1


二、创建自己的项目

1、打开Microsoft Visual Studio 2010,创建一个32位控制台程序;

2、输入项目名称,如这里我用的ARFirstApplication,选择项目目录,点击确定;

3、选择默认设置,完成项目创建;

4、打开ARToolKit\examples\simple\simpleTest.c文件,将全部代码复制到自己创建的项目的资源文件里,这里我的是ARFirstApplication.cpp;

5、点击“生成 --- 生成解决方案”,发现程序报错,详细错误如前一则内容ARToolkit(5);

6、按照前一则内容,将bin文件夹、Data文件夹和Wrl文件夹复制到相应位置,并设置VS附件库目录;

7、点击“生成 --- 生成解决方案”,此时已经显示生成成功。


成功创建自己的项目以后, 就可以按照ARToolkit例程中的程序框架编写自己的ARToolkit程序,当然首先应该完全清楚例程中的流程和每一步的含义,下面将ARToolKit\examples\simple\simpleTest.c中的代码贴出来,并做详细的注释,方便自己后续学习和使用。


三、代码详细注释

// ARFirstApplication.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#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>

using namespace std;
//
// Camera configuration.
//
#ifdef _WIN32
char			*vconf = "Data\\WDM_camera_flipV.xml";
#else
char			*vconf = "";
#endif

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

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

char           *patt_name      = "Data/patt.hiro";
int             patt_id;
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)
{
	glutInit(&argc, argv);
	init();

    arVideoCapStart();
    argMainLoop( NULL, keyEvent, mainLoop );
	//system("pause");
	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);
    }
}

/* main loop */
static void mainLoop(void)
{
    ARUint8         *dataPtr;		// 图像数据,unsigned char类型
    ARMarkerInfo    *marker_info;	// 标记块信息,结构体类型:面积、id、方向dir、自信度、中心点位置、四边的直线方程、顶点坐标4个
    int             marker_num;		// 标记块序号
    int             j, k;

    /* grab a vide frame */			// 从摄像头获取图像数据,如果未获取图像,则2ms后返回
    if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
        arUtilSleep(2);
        return;
    }
    if( count == 0 ) arUtilTimerReset();// 启动程序时,复位定时器
    count++;							// 获取图像后,计数器加一

    argDrawMode2D();					// 更新摄像头参数,为渲染2D和3D对象做准备
    argDispImage( dataPtr, 0,0 );		// 显示图像

    /* detect the markers in the video frame */		// 在摄像头输入帧中识别标记块,过程:阈值化、标记分类、轮廓提取、线角点估计。成功返回0,否则返回-1。
    if( arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0 ) {
        cleanup();
        exit(0);
    }

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

    /* check for object visibility */	// 寻找可识别的标记块,按照可信度大小选择可信度最大的一个,如果没有找到则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;
    }

    /* get the transformation between the marker and the real camera */
    arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);	// 获取摄像机和标记块之间的坐标变换,其中patt_trans存储变换矩阵是指从标记块坐标系(图像坐标系)到摄像机坐标系的变换矩阵

    draw();								// 渲染模型

    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();
}

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};
    
    argDrawMode3D();			// 更新摄像头参数用于3D渲染
    argDraw3dCamera( 0, 0 );	// 对argDrawMode3D()的补充
    glClearDepth( 1.0 );
    glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    
    /* load the camera transformation matrix */
    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 );
}


四、重要参考

1、官网教程:Documentation --- > Developing your First Application, Part 1(http://www.hitl.washington.edu/artoolkit/documentation/devstartup.htm

2、ARToolkit中文论坛:日记的ARTOOLKIT笔记(1):从流程开始看(http://www.artoolkit.net/viewthread.php?tid=3597&extra=page%3D1


在此,特别感谢ARToolkit中文论坛版主“杯具的黑白日记”,虽然已经时隔5年,但是他的良好习惯依然感染我让我这样详细的记录每一步学习历程,后续还会继续坚持下去,敬请期待!




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值