基础教程一目录1简介2从这里开始3OGRE是怎样工作的3.1场景管理器基础3.2实体基础3.3场景节点基础4第一个OGRE程序5坐标和向量6添加其它的对象7实体深入了解8场景节点深入了解9额外尝试9.1缩放9.2旋转10小结11Ogre环境配置11.1动态链接库(DLLs)与插件(Plugins)11.2配置文件11.3一个更好的调试程序的方法简介在这篇教程里,我会向您介绍OGRE最基础的构架:场景管理器,场景节点和实体。由于我需要在这篇教程里把OGRE的基本概念介绍给你,所以我们不会接触太多的代码。在您阅读这篇教程的同时,您应该自己一点一点的添加代码来体会代码的作用,只有这样才可以真正理解这些概念。从这里开始在这篇教程里,我们将使用已经写好的代码作为模版。除了我们将要在createScene函数里面添加的代码之外,您可以暂时忽略其他的东西。在后面的教程里我会深入讲解OGRE程序是如何工作的,现在我们只需要从最简单的地方学起就行了。在您的编译器里创建一个新的工程,然后把下面的代码添加进去:#includeExampleApplication.hclassTutorialApplication:publicExampleApplication{protected:public:TutorialApplication(){}~TutorialApplication(){}protected:voidcreateScene(void){}};#ifOGRE_PLATFORM==OGRE_PLATFORM_WIN32#defineWIN32_LEAN_AND_MEAN#includewindows.hINTWINAPIWinMain(HINSTANCEhInst,HINSTANCE,LPSTRstrCmdLine,INT)#elseintmain(intargc,char**argv)#endif{//CreateapplicationobjectTutorialApplicationapp;try{app.go();}catch(Exception&e){#ifOGRE_PLATFORM==OGRE_PLATFORM_WIN32MessageBox(NULL,e.getFullDescription().c_str(),Anexceptionhasoccured!,MB_OK|MB_ICONERROR|MB_TASKMODAL);#elsefprintf(stderr,Anexceptionhasoccured:%s\n,e.getFullDescription().c_str());#endif}return0;}假如您能够成功编译这段代码,您在运行的时候可以用WASD键移动,鼠标来转镜头,ESC键来退出程序。OGRE是怎样工作的这是一个很广的题目,我们将从场景管理器开始然后进一步了解场景节点和实体。这三个类是所有OGRE程序的基石。场景管理器基础在屏幕上显示的所有东西都是由场景管理器来管理。当您在场景中添加物体时,场景管理器会记录这些物体的位置。当您添加摄像机来观看某个场景时,场景管理器会记录摄像机的位置。当您添加平面、广告牌、灯光时,场景管理器同样会管理他们。OGRE里有很多种场景管理器。有的场景管理器渲染地面,有的场景管理器渲染BSP表等等。在后面,我们将进一步了解场景管理器。实体基础一个实体是可以在场景中渲染的物体之一。您可以把实体理解为任何一个3D模型。一个机器人可以是一个实体,一条鱼可以是一个实体,大地草原可以是一个非常大的实体。灯光,摄像机,粒子,广告牌等不能成为实体。但在Ogre中你不能够直接将一个实体放入到场景中,而是将实体与场景节点绑在一起,这个场景节点则包括了实体的方位信息。场景节点基础场景节点将持续跟踪与它绑在一起的实体的方位。当你创建了一个实体时,它直到与一个场景节点绑定后才会被渲染。同样,一个场景节点也不能单独的在屏幕上显示出来,只有与一个实体绑定后才能在屏幕上显示。场景节点可以绑定多个实体。例如在屏幕上有在行走的一个人物对象,并且希望这个对象产生发光效果,要实现这些,首先你需要创建一个场景节点,然后再创建一个人物对象的实体并与场景节点绑定在一起,之后你还需要创建一个光照模型也与这个场景节点绑定在一起。场景节点同样可以与其它场景节点绑定以描述更完整的对象。我们在后续的章节中介绍场景节点更多的用法。在场景中,场景节点的位置总是与它的父节点相关。每一个场景管理器都包含一个根节点。第一个OGRE程序返回到我们刚才创建的代码,找到TutorialApplication::createScene成员函数。首先需要为整个场景设置环境光,这样才可以看到要显示的内容,通过调用setAmbientLight函数并指定环境光的颜色就可以做到这些。指定的颜色由红、绿、蓝三种颜色组成,且每种色数值范围在0到1之间。将下一句添加到createScene中:mSceneMgr-setAmbientLight(ColourValue(1,1,1));下一步创建一个Entity,通过调用SceneManager的createEntity方法来创建:Entity*ent1=mSceneMgr-createEntity(Robot,robot.mesh);变量mSceneMgr是当前场景管理器的一个对象,createEntity方法的第一个参数是为所创建的实体指定一个唯一的标识,第二个参数robot.mesh指明要使用的网格实体,robot.mesh网格实体在ExampleApplication类中被装载。这样,就已经创建了一个实体,但还需要创建一个场景节点来与它绑定在一起。既然每个场景管理器都有一个根节点,那我们就在根节点下创建一个场景节点。SceneNode*node1=mSceneMgr-getRootSceneNode()-createChildSceneNode(RobotNode);这句代码首先调用场景管理器的getRootSceneNode方法来获取根节点,再使用根节点的createChildSceneNode方法创建一个名为RobotNode的场景节点。与实体一样,场景节点的名字也是唯一的。最后,将实体与场景节点绑定在一起,这样机器人(Robot)就会在指定的位置被渲染:node1-attachObject(ent1);编译并运行你的程序,在屏幕上你将看到一个机器人。坐标和向量在我们继续之前,需要先了解一下OGRE的坐标和向量。与其它图形引擎一样,OGRE也使用XZ面作为其水平面,Y轴作为纵轴。当你面对着屏幕时,从左至右的方向为X轴正方向,从下至上为Y轴正方向,从里至外为Z轴的正方向。你现在可能注意到机器人正面朝X轴正方向,这也许是模型(mesh)设计时就预定好的方向。OGRE并不会假定你的模型的方位,你所载入的每一个模型都可能有不同的“标准”方向。OGRE使用Vectors类来描述方向和位置,定义了2维、3维及4维向量,其中3维向量使用得最多。如果你对向量的知识不熟悉,那建议你在正式使用OGRE之前先学习一些向量的知识,因为在复杂的程序设计中向量是非常重要的。添加其它的对象现在我们已经了解了OGRE中的方位了,让我们再次回到代码部分你就会发现在代码中并没有指定机器人的方向。实际上在OGRE中大量的函数都有自己默认的参数值,例如SceneNode::createChildSceneNode成员函数有三个参数:场景节点的名称、位置及方向,该成员的位置默认值为(0,0,0)。让我们创建另一个场景节点,这次我们指定它的方位信息:Entity*ent2=mSceneMgr-createEntity(Robot2,robot.mesh);SceneNode*node2=mSceneMgr-getRootSceneNode()-createChildSceneNode(RobotNode2,Vector3(50,0,0));node2-attachObject(ent2);这些代码看起来应该很熟悉,除了两个地方不同之外,其它部分与以前的代码都一样。首先我们创建的实体及场景节点的名称有细微的不同,其次创建场景节点时指定了节点的方位信息,我们让实体向X的正方向偏移了50个单位(这是相对与场景中的根节点而言,而所有的节点的位置都是相对于其父节点而言的)。编译并运行,你会发现屏幕上现在有两个[面对面]的机器人。实体深入了解实体类包含的内容相当的广,这里我不会向你介绍实体类的所有内容,只不过使你能够开始使用OGRE而已。不过我会向你介绍几个实体类有用的成员函数。第一个是Entity::setVisible和Entity::isVisible。利用这个函数,你可以设置任何一个实体为可见或不可见。当你想暂时隐藏一个实体时,与其销毁这个实体然后再在用的时候重新创建,不如简单的调用一下这个函数。注意你不需要“省着”用这些实体,任何一个对象的材质和贴图只会被载入到内存里一次,所以当你省系统资源的时候,你并没有真正节省多少。你唯一省掉的只不过是实体创建和毁灭的时间。getName函数返回实体的名称,getParentSceneNode函数返回这个实体绑定的节点。场景节点深入了解场景节点类同样相当复杂。场景节点能实现很多事情,所以我们只了解一些常用的。你可以利用getPosition或setPosition得到或者设定场景节点的位置(总是和父节点相对的)。你可以利用translate函数来移动对象。场景节点不仅仅决定一个对象的位置,它还可以控制一个对象的缩放比例和旋转角度。你可以用scale函数来设置一个对象的缩放比例,还可以用yaw,roll,pitch函数来旋转对象。你可以用resetOrientation来还原你对对象进行的所有旋转。你还可以用setOrientation,getOrientation和rotate函数对对象进行高级旋转。四元数会在后面的教程里对大家讲解。你现在已经见过attachObject函数了。当你想对绑定到场景节点上的对象进行操作时,这些函数会很有帮助:numAttachedObjects,getAttachedObject(这个函数有很多版本),detachObject(同样很多版本),detachAllObjects。还有一大堆函数是来处理父节点和子节点的。由于所有的移动都是相对于父节点的,我们可以很容易的使两个节点一起移动。我们现在已经有这些代码在我们的程序里:Entity*ent1=mSceneMgr-createEntity(Robot,robot.mesh);SceneNode*node1=mSceneMgr-getRootSceneNode()-createChildSceneNode(RobotNode);node1-attachObject(ent1);Entity*ent2=mSceneMgr-createEntity(Robot2,robot.mesh);SceneNode*node2=mSceneMgr-getRootSceneNode()-createChildSceneNode(RobotNode2,Vector3(50,0,0));node2-attachObject(ent2);假如我们将第5行从:SceneNode*node2=mSceneMgr-getRootSceneNode()-createChildSceneNode(RobotNode2,Vector3(50,0,0));改成:SceneNode*node2=node1-createChildSceneNode(RobotNode2,Vector3(50,0,0));这样一来RobotNode2就变成了RobotNode的子节点。移动node1会使node2跟着移动,移动node2却不会影响node1。下面的代码就只会移动RobotNode2:node2-translate(V