如何在MFC程序中使用Open Inventor
本文将介绍如何在MFC程序中使用Open Inventor(以下简称OIV)开发库。文中将使用VC 2003作为开发环境,使用SIM公司( www.coin3d.org)公司提供的Coin3D OIV作为Open Inventor开发库。关于OIV在Visual C++中的设置,请阅读网站 “Open Inventor-Coin3D开发环境” 中的内容。
1
.创建工程
首先启动VC 2003,使用MFC Wizards创建一个MDI 应用程序(本文只讨论MDI类型的应用程序,但SDI或Dialog程序只需要稍微做一些修改,也是同样可以使用OIV的)。我们假定MDI应用程序的名称叫做“MFCViewer”。
2
.增加
Coin
和
SoWin
代码
1. 打开MFCViewer.cpp文件,在文件开始部分增加下列头文件:
#include <Inventor/Win/SoWin.h>
编辑CMFCViewerApp::InitInstance(),在函数中增加上:
SoWin::init("");
这行代码将初始化SoWin和Coin库,必须在调用任何Coin或SoWin函数之前调用这行代码。
2. 打开MFCViewerView.h文件,增加下列头文件列表(增加到预编译头文件-#ifdef/#pragma once/#endif 序列之后)
#include <Inventor/Win/SoWin.h>
#include <Inventor/Win/viewers/SoWinExaminerViewer.h>
增加一个公共数据成员变量
SoWinExaminerViewer * viewer;
SoWinExaminerViewer主要用于渲染我们的场景,以可以和显示的内容做交互式操作(像旋转物体,选择部分场景等)
3. 打开MFCViewerView.cpp文件,修改构造函数:
CMFCViewerView::CMFCViewerView()
{
viewer = NULL;
}
修改析构函数:
CMFCViewerView::CMFCViewerView()
{
if (viewer != NULL)
delete viewer;
}
3
.创建场景
我们希望当用户创建了一个新文档后(点击菜单File | New),新创建的窗口中会有一个OIV场景。
1. 打开MFCViewerDoc.h文件,在CMFCViewerDoc类定义之上增加下列代码:
class SoSeparator;
这行代码主要是告诉编译器,我们要使用一个叫做SoSeparator的类。
2. 向CMFCViewerDoc类增加一个公共数据成员变量:
SoSeparator *root;
这是我们场景的根节点。
3. 打开MFCViewerDoc.cpp文件,增加下列头文件:
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoTranslation.h>
#include <Inventor/nodes/SoText2.h>
这些都是我们准备在场景中使用的节点,因此需要首先包含它们的头文件。
4. 修改函数OnNewDocument()
BOOL CMFCViewerDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
root = new SoSeparator;
root->ref();
SoMaterial *myMaterial;
root->addChild(myMaterial = new SoMaterial);
myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0);
root->addChild(new SoCone);
SoSeparator * instructsep = new SoSeparator;
root->addChild(instructsep);
instructsep->addChild(myMaterial = new SoMaterial);
myMaterial->diffuseColor.setValue(0.5, 1.0, 1.0);
SoTranslation * instructtrans = new SoTranslation;
instructtrans->translation = SbVec3f(-2.0f, 1.3f, 2.0f);
instructsep->addChild(instructtrans);
SoText2 * instructions = new SoText2;
const char * str[] = {
"Instructions for the MFCViewer tutorial",
"",
"Left mouse button = rotate",
"Middle mouse button = move",
"CTRL + middle mouse button = zoom",
"Right mouse button = options"
};
instructions->string.setValues(0, sizeof(str) / sizeof(char *), str);
instructions->justification = SoText2::LEFT;
instructsep->addChild(instructions);
return TRUE;
}
我们通过向根节点增加子节点来建立场景。请记住,OIV会自己删除所有的场景对象,因此这里不需要程序员记住这些对象的指针,在以后的时候删除它们。(事实上如果这样做将会发生内存错误)。OIV是通过一种叫做引用计数的技术来实现这个功能的。
5. 修改构造和析构函数,增加上下列代码:
CMFCViewerDoc::CMFCViewerDoc()
{
root = NULL;
}
CMFCViewerDoc::~CMFCViewerDoc()
{
if (root)
root->unref();
}
调用
root->unref(),告诉OIV,我们已经不再使用根节点对象了。所以OIV将会自动删除根节点。
6. 打开MFCViewerView.cpp文件,增加上下列代码:
#include <Inventor/nodes/SoSeparator.h>
修改函数CMFCViewerView::OnDraw(CDC* pDC):
void CMFCViewerView::OnDraw(CDC* pDC)
{
CMFCViewerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (viewer == NULL)
{
viewer = new SoWinExaminerViewer( m_hWnd );
viewer->setDecoration(FALSE);
SoSeparator *root = GetDocument()->root;
viewer->setSceneGraph(root);
}
}
上面的代码将WinExaminerViewer嵌入到CMFCViewerView窗口中,其中WinExaminerViewer四周的 Toolbar(即Decoration)是不显示的。
编译并执行此应用程序
www.openinventor.cn