在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库:
库目录和链接目录都包含win64-x64目录:
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窗口上了,如图所示: