思考一个问题,artoolkit可以利用opengl绘制的正方体、球形。那么我们是否可以用自己的三维模型去替代它们你?
wrl文件是一种虚拟现实文本格式文件,也是VRML的场景模型文件的扩展名。将三维模型保存成wrl格式,在通过openVRML支持artoolkit 绘制三维模型。
配置openVRML环境
想要编译simplevrml.c 首先要 配置openVRML的环境,如下:
【include】
OpenVRML\dependencies\include
OpenVRML\include
【lib】
OpenVRML\dependencies\lib
OpenVRML\lib
【连接器-输入】
openvrml.lib
openvrml-gl.lib
antlr.lib
regex.lib
这时候编译还是会报错,出现C2001的,lib无法解析
【解决方案】 重新编译openVRML。
打开 OpenVRML\src\openvrml-0.14.3\ide-projects\Windows\VisualC7\OpenVRML\openvrml.sln
然后编译生成 4个lib,并把lib 放置在 OpenVrML\lib的 位置
simplevrml.c 源码分析
simplevrml.c 使用的MainLoop()框架与之前的simpletest不同。simpletest的框架以opengl为主,而simplevrml.c的框架则是以ar为主。
变量声明
#define VIEW_SCALEFACTOR 0.025 //一个ARToolKit单位变成0.025个OpenGL单位。
#define VIEW_SCALEFACTOR_1 1.0 // 1.0 ARToolKit unit becomes 1.0 of my OpenGL units.
#define VIEW_SCALEFACTOR_4 4.0 // 1.0 ARToolKit unit becomes 4.0 of my OpenGL units.
#define VIEW_DISTANCE_MIN 4.0 // 目标与摄像机距离小于4.0不显示
#define VIEW_DISTANCE_MAX 4000.0 // 目标与摄像机距离大于4000不显示
//OpenGL初始化参数设置Preferences.
static int prefWindowed = TRUE;
static int prefWidth = 640; //全屏模式的宽度
static int prefHeight = 480;//全屏模式的高度
static int prefDepth = 32;//全屏模式的位深度
static int prefRefresh = 0; //全屏模式刷新率
static ARUint8 *gARTImage = NULL;//获取图像
static int gARTThreshhold = 100; //标识检测时的二值化阈值
static long gCallCountMarkerDetect = 0;//初始化ARToolKit 帧频计数器为0
//Transformation matrix retrieval.//转换矩阵检索
static int gPatt_found = FALSE;//用gPatt_found判断是否找到标识
static ARParam gARTCparam;
static ARGL_CONTEXT_SETTINGS_REF gArglSettings = NULL;
static ObjectData_T *gObjectData;
static int gObjectDataCount;
setupCamera()
setupCamera()函数 主要的作用是打开相机,导入相机参数,设置相机大小,初始化相机参数, 捕获图像
//打开相机,导入相机参数,更改相机长宽大小,初始化相机参数,捕获图像
static int setupCamera(const char *cparam_name, char *vconf, ARParam *cparam)
{
ARParam wparam;//储存相机参数
int xsize, ysize;//储存图像大小的值
//打开视频路径
if (arVideoOpen(vconf) < 0) {
fprintf(stderr, "setupCamera(): Unable to open connection to camera.\n");
return (FALSE);
}
//得到当前视频图像的大小
arVideoInqSize(&xsize, &ysize);
//导入相机参数,重新定义窗口大小
arParamLoad(cparam_name, 1, &wparam);
arParamChangeSize(&wparam, xsize, ysize, cparam);
//显示参数值
arParamDisp(cparam);
//初始化相机参数
arInitCparam(cparam);
//开始捕获图像
arVideoCapStart();
return (TRUE);
}
setupMarkersObjects()
setupMarkersObjects()函数 主要作用是 导入一个或者多个标识的图像矩阵
//导入一个或多个标识的图像矩阵
static int setupMarkersObjects(char *objectDataFilename)
{
//导入一个或多个标识图---训练标识及其相关的位图文件,这里使用了object.c文件中的read_VRMLdata()函数
if ((gObjectData = read_VRMLdata(objectDataFilename, &gObjectDataCount)) == NULL) {
fprintf(stderr, "setupMarkersObjects(): read_VRMLdata returned error !!\n");
return (FALSE);
}
printf("Object count = %d\n", gObjectDataCount);
return (TRUE);
}
Display()
当窗口需要重新绘制模型的时候,调用该函数。
static void Display(void)
{
int i;
GLdouble p[16];
GLdouble m[16];
//第一步:清除屏幕,显示最新的后台缓冲帧
glDrawBuffer(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the buffers for new frame.
arglDispImage(gARTImage, &gARTCparam, 1.0, gArglSettings);
arVideoCapNext(); //开启下一帧
gARTImage = NULL; //当调用了arVideoCapNext()函数后,此时图像数据不再有效,等待接收下一帧图像。
//第二步:寻找标识,并根据相机参数设置投影矩阵
if (gPatt_found) {
// 如果找到标识,就执行下面的程序
arglCameraFrustumRH(&gARTCparam, VIEW_DISTANCE_MIN, VIEW_DISTANCE_MAX, p);
//把相机参数转换成OpenGL投影矩阵16的数组,然后直接导入,
//生成的三维物体就会匹配真实的相机视角
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(p);
glMatrixMode(GL_MODELVIEW);
// Viewing transformation.视景变换
glLoadIdentity();
for (i = 0; i < gObjectDataCount; i++) {//对标识进行遍历
if ((gObjectData[i].visible != 0) && (gObjectData[i].vrml_id >= 0)) {//如果该标识被设置为可见(该设置在Idle()函数中完成)且ID正确那么就执行以下代码
arglCameraViewRH(gObjectData[i].trans, m, VIEW_SCALEFACTOR_4);
/*
创建一个视景矩阵,传递给OpenGL设置虚拟相机的视景变换。
转换标识转换矩阵成OpenGL视景矩阵,这16个值就是真实相机的位置和方向,
使用他们设置虚拟相机的位置,
使三维目标准确的放置在物理标识上。
*/
glLoadMatrixd(m);//这里是设置虚拟相机的位置。
//第三步:在标识上画出虚拟物体。
arVrmlDraw(gObjectData[i].vrml_id);//根据前面加载的模型ID绘制模型
}
}
}
glutSwapBuffers();//清理缓存
}
object_data_vrml 文件解读
#the number of patterns to be recognized
2
#pattern 1
VRML ../Wrl/bud_B.dat
../Data/patt.hiro
80.0
0.0 0.0
#pattern 2
VRML ../Wrl/snoman.dat
../Data/patt.kanji
80.0
0.0 0.0
- # 开头的为注释
- 第一个行标识 pattern被标识的个数为 2
- “VRML ../Wrl/bud_B.dat” 标识第一个pattern 模型的路径
- ../Data/patt.hiro 为对应标识的路径
- 标识的宽度为80,标识的中心坐标为(0,0)
../Wrl/bud_B.dat
bud_B.wrl
0.0 0.0 0.0 # Translation
0.0 0.0 0.0 0.0 # Rotation
10.0 10.0 10.0 # Scale
- 第一行是 vrml 模型文件
- 第二行 平移参数
- 第三行 旋转参数
- 第四行 缩放参数