第1周·星期一 第1个3D程序
1.前言
2003年有一个名为“Mega”的游戏开发小组撰写了“OGRE使用指南”,很多早期接触OGRE 3D的人(包括笔者在内)都是通过这篇文档开始了解图形引擎的。虽然今天看来,其中的内容有一些陈旧(OGRE 3D当时的版本应该是0.10.0左右,现在已经发展到1.6.x和1.7.x),不过正是这篇文档把在国外的OGRE 3D引擎引入中国游戏开发人员的视野中。
这“第1个3D程序”,是很好的入门课程。在撰写这本书的过程中笔者联系了该文档的作者之一任晓宇先生,得到了使用这节的授权,我们仍然采用本章教程作为星期一课程(做了些许修改)。
本章详细讲解了OGRE 3D图形引擎开发包中提供的一个演示程序EnvMapping,因为这个框架从那时一直沿用到今天的1.6.x版本,所以其中的内容同样适用我们今天的学习(正在开发中的1.7.x将会采用新的演示程序框架)。相应的代码在OgreShrewMouse解决方案的Day1工程中。
2.正文
OGRE 3D开发包中提供的框架和实际应用程序的关系如图2-2所示。
图2-2 OGRE 3D开发包中提供的框架和实际应用程序的关系
OGRE 3D的应用框架定义的ExampleApplication与ExampleFrameListener类已封装了3D应用程序的全部要素,应用开发人员所要做的主要工作如下。
(1)派生自己的应用程序类,重新实现createScene函数以创建场景。
(2)派生自己的监听器类,如果需要的话,重新实现frameStarted函数以实现特殊的输入控制和动画控制。
打开OgreShrewMouse解决方案中的Day1(OGRE 3D开发包中Demo_EnvMapping)工程,这是一个非常简单易懂的程序实例。
这个程序只有两个文件,即EnvMapping.h和EnvMapping.cpp。
EnvMapping.h文件定义了ExampleApplication类的派生类EnvMapApplication,并重新实现createScene函数创建了一个亮闪闪的具有环境帖图的食人魔头像,其代码如下:
class EnvMapApplication : public ExampleApplication { public: EnvMapApplication() {} protected: // 重新实现createScene函数,创建实际场景 void createScene(void) { // 设置环境光 mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5)); // 创建点光源l Light* l = mSceneMgr->createLight("MainLight"); // 设置点光源l的位置,默认颜色为白色 l->setPosition(20,80,50); // 读入ogrehead.mesh模型文件,创建为一个Entity Entity *ent = mSceneMgr->createEntity("head", "ogrehead.mesh"); // 设置食人魔Entity的材质为指定材质(环境贴图) ent->setMaterialName("Examples/EnvMappedRustySteel"); // 将食人魔Entity连接到场景根节点上 mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent); } };
一个基本的场景包括各种光、摄像机和模型等,其中没有显式创建摄像机的原因是采用了ExampleApplication类中创建的默认摄像机。每个模型文件载入后被创建为Entity。为了便于管理场景,OGRE 3D引入了场景节点的概念。所有的场景节点组合成一棵节点树,而全部Entity都挂在这棵节点树中的不同节点上。场景管理器mSceneMgr通过控制节点树的操控来完成控制场景物体的操控。关于这部分的内容请参看附录C中场景管理部分。
建立场景之后处理应用程序的入口问题,这部分代码在EnvMapping.cpp中,如下:
// 判断编译平台,Ogre3D支持跨平台的 #if OGRE_ PLATFORM==OGRE_ PLATFORM_ WIN32 // Win32平台 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else // 非Win32平台 int main(int argc, char **argv) #endif { // 创建应用程序对象 EnvMapApplication app; try { // 执行go函数,开始应用程序过程 app.go(); } // 异常处理 catch( Exception& e ) { #if OGRE_ PLATFORM==OGRE_ PLATFORM_ WIN32 // Win32平台异常提示 MessageBox( NULL, e.getFullDescription().c str(), "An exception has occured!", MB_ OK | MB_ ICONERROR|MB_ TASKMODAL); #else // 非Win32平台异常提示 std::cerr << "An exception has occured: " << e.getFullDescription(); #endif } return 0; }
已经编译通过后保存在OgreBook\Build\vc90\OgreShrewMouse\bin\Release目录中,可以运行Day1查看执行结果(这里假定使用VC9.0编译环境生成的Release版本,如果使用VC8.0或者VC7.1,项目会生成在vc80和vc71目录下;如果生成Debug版本,需要在相应Debug目录中寻找可执行文件。之后的课程工程代码的生成结果也类似,不再重复说明)。
3.截图
如图2-3所示。
图2-3 截图
4.结语
今天我们学习了一个简单的OGRE演示程序,其中提到了一些与OGRE 3D图形引擎相关的概念,我们会在这本书最后面的附录C中简单讲解这些内容。如果希望进一步了解,则请阅读《OGRE 3D程序设计》这本书(可以在http://ogre3d.cn网站上找到)。