(3) OGRE的基石:场景管理器、场景节点、实体

来源:互联网 发布:ubuntu nodejs 编辑:程序博客网 时间:2024/05/18 19:43

提示

1、确定你已经按照前一教程配置好了第一个应用程序的环境

2、所有的代码,你应该自己去敲键盘,尝试多种情况并运行查看效果

 

简介

在这篇教程里,我会向您介绍OGRE最基础的构架:场景管理器,场景节点和实体

 

从这里开始

将前一教程的工程拷贝一份,我们将在他的基础上做一些功能扩充和展示。我们所需要修改的只有一个代码文件:TutorialApplication.cpp,而且我们只需要关注成员函数:createScene()。

OK,让我们边写代码边讲解吧,GO!

为成员函数createScene()补充如下代码:

编译运行下看看效果,你可以使用WASD来移动,鼠标移动镜头,ESC退出程序。

 

先了解几个概念

场景管理器

    在屏幕中显示的所有东西都是有场景管理器来管理。当你在场景中添加物体时(比如放一个人物模型),场景管理器会对他的位置信息进行维护。当你添加摄像机来观看某个场景时,场景管理器会记录摄像机的位置。OGRE里有多种的场景管理器:有的渲染地面;有的渲染BSP表等,后续我们再进一步理解他。

实体

    你可以把实体理解为任何一个3D模型,例如:一个机器人、一个玩家模型、一棵树、一条鱼,大地草原等。但灯光、摄像机、粒子、广告牌不是实体。

    在OGRE中,你不能直接将一个实体放入场景中,实体是和场景节点绑定的,场景节点指明了实体的位置信息。

场景节点

    可以简单的把场景节点认为是一些知名位置信息的点,这些点不能在屏幕中显示。通过场景节点,可以在上面挂载多个实体,最后将绑定后的实体显示出来。

    例如:你想在屏幕上显示一个可以发光的、在行走的人物,你必须这么来做:首先创建一个场景节点,然后创建一个人物对象实体,将此对象绑定到场景节点,之后还需要创建个光照模型并绑定到此场景节点。

    在场景中,场景节点的位置总是与它的父节点相关,每一个场景管理器都包含一个ROOT节点,他们构成一颗树。

 

代码分析

首先需要为整个场景设置环境光,这样才能看到显示的内容(如果是黑灯瞎火的,你看到的将是一片黑色)。通过setAmbientLight接口设置环境光的颜色。其中,变量 mSceneMgr 是当前场景管理器的一个对象,在类BaseApplication中创建了。

然后,创建一个实体,是个OGRE的LOGO头,通过createEntity接口来创建。对本接口做如下解释:第一个参数指明实体的名字,他应该是唯一的,不应该和其他任何实体对象重名,否则你将得到一个错误。第二个参数指明实体使用的网格(mesh),即描述模型信息的配置文件,在资源目录(即SDK目录下)可找得到。

实体创建完毕后,为了将其在指定的位置显示出来,还需要创建一个场景节点,并与之绑定。还记得每个场景管理器都有个根节点不?从这个节点开始创建吧:createChildSceneNode

这句代码首先调用场景管理器的 getRootSceneNode 方法来获取根节点,再使用根节点的 createChildSceneNode 方法创建一个场景节点。与实体一样,场景节点的名字也是唯一的。

最后,将实体与场景节点绑定在一起,这样机器人(Robot)就会在指定的位置被渲染,编译运行下看看效果,看到机器人了吗?很简单的一个过程,不是吗?

 

坐标和向量

为了继续后面的章节,这里需要先了解下OGRE使用的坐标和向量。与其它图形引擎一样,OGRE 也使用 XZ 面作为其水平面,Y 轴作为纵轴。当你面对着屏幕时,从左至右的方向为 X 轴正方向,从下至上为 Y 轴正方向,从里至外为 Z 轴的正方向。 如下图:

代码中的那个机器人,其位置在原点(0, 0, 0),因为我们没有指定其位置,默认就在这个点。其初始朝向为-x方向,这是由mesh文件决定的。

OGRE使用类Vector描述位置和方向,定义了2维、3维及4维向量,其中3维向量使用得最多。如果你对向量不了解,该好好复习下空间几何了,这在3D变成中非常非常重要。

 

添加其他对象

OGRE中很多接口都提供了默认的参数,例如,SceneNode::createChildSceneNode成员函数有三个参数:场景节点的名称、位置及方向,该成员的位置默认值为(0,0,0)。让我们再创建另一个场景节点,这次我们指定它的方位信息:

和之前做法相识,只是我们多指定了一些额外信息:位置,他举例ROOT节点x方向100单位(像素),再提及下,所有子节点的位置都是相对于父节点而言。运行代码比较下两个机器人的位置差别。

 

进一步了解实体

实体类(Entity)含的内容相当的广,这里我不会向你介绍实体类的所有内容,只不过使你能够开始使用OGRE而已。不过我会向你介绍几个实体类有用的成员函数。

第一个是Entity::setVisible和Entity::isVisible。利用这个函数,你可以设置任何一个实体为可见或不可见。当你想暂时隐藏一个实体时,与其销毁这个实体然后再在用的时候重新创建,不如简单的调用一下这个函数。注意你不需要“省着”用这些实体,任何一个对象的材质和贴图只会被载入到内存里一次,所以当你省系统资源的时候,你并没有真正节省多少。你唯一省掉的只不过是实体创建和毁灭的时间。

getName函数返回实体的名称,getParentSceneNode函数返回这个实体绑定的节点。

 

进一步了解场景节点

SceneNode同样很复杂,通过他我们可以做很多事情,这里我们只覆盖最常用的几个功能。

你可以利用getPositionsetPosition得到或者设定场景节点的位置 (总是和父节点相对的)。你可以利用translate函数来移动对象。

场景节点不仅决定了实体的位置,他还控制一个实体对象的缩放比例和旋转角度。你可以用scale函数来设置一个对象的缩放比例,还可以用yaw, roll, pitch函数来旋转对象。你可以用resetOrientation来还原你对对象进行的所有旋转。你还可以用setOrientation, getOrientationrotate函数对对象进行高级旋转。四元数会在后面的教程里对大家讲解。

你现在已经见过attachObject函数了。当你想对绑定到场景节点上的对象进行操作时,这些函数会很有帮助:numAttachedObjects, getAttachedObject(这个函数有很多版本), detachObject(同样很多版本), detachAllObjects。还有一大堆函数是来处理父节点和子节点的。

由于所有的移动都是相对于父节点的,我们可以很容易的使两个节点一起移动。

 

确认下,你当前已经有如下代码了:

修改下第8行的代码为:

这样,headNode2就成为headNode的一个子节点了。移动headNode会同时移动headNode2,反之却不会。

尝试下,如下代码只移动headNode2

如下代码移动headNode,同时其子节点headNode2也被移动:

解释下这个变换。我们总场景的根节点开始,他的位置永远在(0, 0, 0)。根节点下面挂这headNode节点,做了一次平移操作,那么新的位置为:(0, 0, 0) + (25, 0, 0) = (25, 0, 0),即root + headNode。headNode2为headNode的子节点,其位置就是root + headNode + headNode2 = (0, 0, 0) + (25, 0, 0) + (100, 0, 0)。

最后说一下,你可以使用场景管理器的成员函数getSceneNodegetEntity来获取场景节点和实体,这样你就不用保留你创建他们时使用的指针了。但你仍然应该保留很常用的实体指针。

 

再来一些额外的尝试

缩放

通过scale函数可以对模型网格进行比例缩放,修改createScene为(Light的代码保留):

编译看看效果,并调整下各参数值对比效果。

 

旋转

你可以用yaw, pitch, roll来旋转对象。Yaw是Y轴的旋转,Pitch是X轴,Roll是Z轴。如下图(右手坐标系,还记得不?):

   

试一下变换角度(Degree)和合并多种旋转方式,编译看看效果:

 

OGRE环境配置

本课(甚至整个教程)涉及到的大部分文件(dll和cfg)都可以在 ${OgreSDK}/bin/debug或release 目录里找到。你创建的debug程序应该使用debug目录里的文件,而release程序应当使用release目录里的文件。

注意,在这里多数情况是指在Windows环境下的。

动态链接库(DLLs)与插件(Plugins)

Ogre被分为若干类共享库。

第一类是原始库,以及它的依赖库。Ogre库全都包含在OgreMain.dll里。这个dll还需要其它的一些库,比如cg.dll。这些dll必须毫无例外地包含在每一个ogre应用中。

第二类库是插件。Ogre将很大一部分功能抽到这些库里面,以方便能根据具体需要来开启或关闭这些功效。Ogre包含的基本插件拥有以"Plugin_"开头的文件名。如果需要,你能亲自写一个插件,但我们的教程将不涉及这些内容。Ogre还为渲染系统提供插件(如OpenGL、 DirectX等)。这些插件以"RenderSystem_"为前缀。有了这些插件,你就可以方便地在应用程序中添加或者移除渲染系统。这是非常有用的,如果你正在写一个OpenGL专门的着色程序,并希望当运行在DirectX上时不执行它,你则只要移除这个渲染系统,它就不存在了。另外,如果你致力于一个非标准的平台,你可以写你自己的渲染系统插件,但我们的教程不涉及。我们将在下一课告诉你如何移除插件。

第三类库是第三方库和帮助库。Ogre本身只是一个图形渲染引擎,它并不包含像GUI系统、输入控制、物理引擎这类东西,你需要其它第三方帮助库。CEGUI 库就是一个能轻松整合进Ogre的GUI系统,以"CEGUI*"开头的dll文件和"OgreGUIRenderer.dll"就是它的一部分。我们将在以后的教程里介绍CEGUI。鼠标键盘输入则通过OIS来实现(一个输入系统),它包含在OIS.dll里。还有其它很多能够提供更多功能的库(不包含在SDK),比如音效和物理。你能在Wiki或论坛里找到更多的信息。

总之准则就是,当你在本地调试你的程序时,你可以将所有的功能都“打开”(也就是说,不移除任何东西)。当你准备发布你的程序时,你应用 Release模式构建它,包括所有你用到了的dll文件。而且你应该移动那些你没有使用的dll。如果你的程序没有用到CEGUI,而是使用了OIS,就不要包含CEGUI 进来,但你必须包含OIS的dll,否则的你程序跑不起来。

配置文件

Ogre的运行需要几个配置文件。它们用来控制哪些插件需要加载,程序的资源在哪里定位等等。我们来简单地看一下每个配置文件是用来做什么的。

plugins.cfg 这个文件指定应用程序使用的插件。如果你要在程序中添加或移除某个插件,就要修改这个文件。要去掉某个插件,只需要删除某一行,或用#直接注释掉它。你想要添加一个插件,就要添加像"Plugin=[PluginName]"这样的一行。注意,你不要在插件名后面加上.dll后缀。你的插件同样不必以"RenderSystem_" 或 "Plugin_" 开头。通过修改"PluginFolder"变量,你还可以定义Ogre搜索插件的目录。你可以使用绝对或相对路径,但不能使用像$(SomeVariable)这样的环境变量。

resources.cfg 这个文件含有Ogre搜索资源的目录列表。资源包括:脚本、模型、纹理等等。你同样可以使用绝对或相对路径,但你不能使用如$(SomeVariable)环境变量。注意,Ogre不会搜索子目录,所以你如果有多层目录必须手工输入它们。比如,你有一个目录树,像"res/meshes" and "res/meshes/small",你就要为这些路径添加两个入口。

media.cfg 这个文件告诉Ogre更多关于某些资源的细节。目前你不太可能改动这个文件,所以我们跳过去。

ogre.cfg 这个文件是Ogre的配置窗口生成的。这个文件与你的个人电脑和显示配置相关。当你把应用程序发布给别人时,不必配提供这个文件,因为他们的设置很可能不同。注意,你不能直接编辑这个文件,而要使用那个配置窗口。

quake3settings.cfg 这个文件是与BSPSceneManager一起使用的。除非你使用这个场景管理器(目前你不会使用),否则你不需要这个文件,我们忽略它。同样地,除非你正在使用BSPSceneManager,你不要把这个文件与你的程序一起发布,就算那样,它也可能会完全不一样,这要看你程序的需求。

以上是所有Ogre需要操作的文件。Ogre要能找到"plugins.cfg", "resources.cfg", 和 "media.cfg",它才能正确运行。在后续的教程里,我们将会深入介绍这些文件,以及如何改变它们的地址,用它们来做更高级的事情。

 

小结

现在已经掌握了OGRE的基石——实体,场景节点,场景管理器。你并不需要对上面所讲的那些函数都了如指掌。由于他们是很基础的东西,我们会经常使用。随着对OGRE了解的深入,你应该可以自然而然的掌握他们。

原创粉丝点击