在MFC桌面程序中使用ARToolKit

 在widows下,ARToolKit提供了simpleLite样例,是控制台程序,具体介绍可参考文档:
simpleLite - The First ExampleApplication to Look At

https://artoolkit.org/documentation/doku.php?id=7_Examples:example_simplelite#AdvancedTopics

为了在Windows下使用ARToolKit,需要用MFC调用ARToolKit,主要问题是:

1、simpleLite使用glutMainLoop进入OPENGL的事件处理循环,在MFC中需要改写程序,通过MFC事件触发OPENGL在MFC窗口上画图。

2、simpleLite使用32位的OPENGL包,而ARToolKit的其他库是64位的,在64位系统(如win10)下进行调试时,程序飞掉,抛出:

线程 0x1370 已退出,返回值为 -2147024637 (0x80070103)

之类的异常,需要用64位编译,便于调试。

 本文的开发环境是:win10家庭中文版;VSUltimate2013。

开发过程如下:

0、编译环境配置

新建一个MFC单文档程序,64位编译Debug版。链接输入所需的ARtoolkit库和glut64库:


在MFC桌面程序中使用ARToolKit

 

库目录和链接目录都包含win64-x64目录:

在MFC桌面程序中使用ARToolKit


1、初始化OPENGL
在View的OnCreate中,初始化OPENGL。InitializeOpenGL函数的定义如下:

BOOL CSingleDocTestView::InitializeOpenGL(void)

{

    PIXELFORMATDESCRIPTOR pfd;

    int n;

    m_pDC = new CClientDC(this);

    ASSERT(m_pDC != NULL);

    // 设置当前的绘图像素格式 

    if (!SetupPixelFormat())

    {

        return FALSE;

    }

 

    n =::GetPixelFormat(m_pDC->GetSafeHdc());

    ::DescribePixelFormat(m_pDC->GetSafeHdc(),n, sizeof(pfd), &pfd);

    // 创建绘图描述表 

    m_hRC =wglCreateContext(m_pDC->GetSafeHdc());

    if (m_hRC == NULL)

    {

        return FALSE;

    }

    // 使绘图描述表为当前调用现程的当前绘图描述表 

    if (wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC) == FALSE)

    {

        return FALSE;

    }

    glClearDepth(1.0f);

    glEnable(GL_DEPTH_TEST);

    return TRUE;

}

 

2、初始化摄像头和标签加载程序

两个关键的函数:setupCamera和setupMarker。

从simpleLite中直接拷贝,在OnCreate中调用。

 

3、从摄像头获得视频图像

arVideoGetImage,在simpleLite的mainloop函数中调用。

4、在图像中检测标签

arDetectMarker,在simpleLite的mainloop函数中调用。

5、计算标签坐标系在摄像机坐标系中的变换

arGetTransMatSquare,在simpleLite的mainloop函数中调用。

以上3-5步骤,从simpleLite中拷贝mainloop函数,注释掉其中OPENGL画图的代码,包括计算重新画图的时间间隔,以及用于标记窗口重画的glutPostRedisplay函数,等等。

 

6、在标签上画出方块

从simpleLite中拷贝display、DrawCube函数。

为了界面刷新,在VIEW中增加定时器,调用mainLoop、display函数。

void CSingleDocTestView::OnTimer(UINT_PTR nIDEvent)

{

    // TODO:  在此添加消息处理程序代码和/或调用默认值

    if (nIDEvent == 1)    //定时器1处理函数,

    {

        mainLoop();

        display ();

    }

 

    CView::OnTimer(nIDEvent);

}

在display中,为了在VIEW上画图,在前面增加:

wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);

在后面增加

SwapBuffers(wglGetCurrentDC());

wglMakeCurrent(NULL, NULL);

注释掉原有的

//glutSwapBuffers();

就可以将OPENGL渲染后的图像输出到MFC窗口上了,如图所示:

在MFC桌面程序中使用ARToolKit