简介:本教程基于Ogre Wiki上的Basic Tutorial系列,并依据笔者使用的vs2005+sp1+OgreSDK1.4.3开发环境简化整理而来,其中穿插着笔者自己的理解。这是教程的第一部分,也是我的学习笔记。
正文:凡是翻译过几篇技术类文章的人都深知从头至尾忠实重现作者的原意是一件多么令人头疼的事情。当我从诸多曾经许诺要翻译的文章中爬出来的时候,我决定这次不做那样一个“傻子”,重写那些文章要比翻译它们快乐的多。
在开始前,我希望统一我们的开发环境——VS2005+OgreSDK1.4.3。有两点需要注意:
一、请确认你的VS2005安装了sp1补丁包,这一点非常重要,否则你可以正确的编译Ogre程序,但你死活运行不起它们来。
二、请确认你的Ogre是合适的版本,也就是OGRE 1.4.3 SDK for Visual C++ .Net 2005(8.0)SP1,你可以从http://www.ogre3d.org/index.php?option=com_content&task=view&id=411&Itemid=131免费获得。
创建你的第一个Ogre应用程序
现在,对表之后,行动开始。哦,等一下,忘了给你们发枪了。请到http://ogreconglo.sourceforge.net/phpBB2/viewtopic.php?p=4领取枪械。是Ogre产的Ogre Application Wizard,不要着急,人人都有。把它解压到合适的位置,我推荐的位置当然是OgreSDK目录下了,然后运行里面的VC8_Setup.js安装。兄弟们,准备好了吗?现在行动真的要开始了。
打开vs2005,新建一个项目,"文件"->"新建"->"项目"->"Visual C++",在"Visual Studio已安装的模板"选择"OGRE SDK Application"。设置好工程名和存储路径后点"确定"按钮。
弹出了向导,选项保持默认就好了,点"finish"完成。
是不是个Win32项目的向导一样简单?下面按F7编译一下。
如果没有操作失误的话,会得到这样的结果
运行却会出现如图的错误,缺少相应的文件,运行不起来。一种解决办法是把缺少的文件复制过来,但你必须知道需要什么文件,不适合新手。另一种方法是,你注意到“Copying exe to samples bin directory ...”一句了吗?EXE文件拷贝到哪里去了?拷贝到“/OgreSDK/bin/debug”中去了,找到了吗?运行试试,成功了吧。
揭开向导的面纱
你可能在想Ogre Application Wizard(之后简称OAW)到底做了什么呢?就像当初我使用Win32应用程序向导创建了那个HelloWorld之后想的一样。其实OAW只做了两件事,一是创建了几个源文件,另一个是设置了IDE的参数,这也是最重要的一步。下面我们来手动做一次OAW做的事情,以便加深印象,为了以后的方便又一小部分操作是不同的。
关闭刚才的解决方案,新建一个项目,"文件"->"新建"->"项目"->"Visual C++"->"Win32",在"Visual Studio已安装的模板"选择"Win32项目"。设置好工程名和存储路径后点"确定"按钮。(我用的工程名和解决方案名都是test2,路径名为D:/GameDevelop)
在向导的"应用程序设置"中选择"Windows应用程序"和"空项目",点击完成。
除了几个工程文件,向导没再多做任何事情。为了这个项目的独立性与方便性,我们还要复制"/OgreSDK"下的"/bin"和"/media"到"D:/GameDevelop/test2"里,并创建"include"、"src"和"scripts",这样你在"D:/GameDevelop/test2"下将看到6个文件夹。
然后创建一个"SampleApp.cpp",保存路径为"D:/GameDevelop/test2/src",内容如下:
保存,按F7编译一下。
出错了,找不到"ExampleApplication.h"。其中的"ExampleApplication"又是什么呢?它是Ogre为初学者设计的实例程序类(可能是个程序框架什么的,我是这么理解的),以便你可以快速的开始Ogre编程的学习。"ExampleApplication.h"在"/OgreSDK/samples/include"下。默认情况下,IDE是不会找到这里的。还记得我说过Ogre程序向导做过什么吗?对了,设置我们的IDE环境。下面我们就来一步步地把IDE设置好。
"项目"->"属性",打开"test2 属性页",展开"配置属性"。设置:
"调试"->"工作目录"为"../bin/Debug",
"C/C++"->"常规"->"附加包含目录"中添加"../include"、"$(OGRE_HOME)/include"和"$(OGRE_HOME)/samples/include",
"C/C++"->"代码生成"->"运行时库"为"多线程调试 DLL (/MDd)"(这个好像就是默认的),
"链接器"->"常规"->"输出文件"为"../bin/Debug/$(ProjectName).exe",
"链接器"->"常规"->"附加库目录"中添加"$(OGRE_HOME)/lib",
"链接器"->"输入"->"附加依赖项"中添加"OgreMain_d.lib"和"OIS_d.lib"(如果是Release版则添加"OgreMain.lib"和"OIS.lib")
设置好了,再编译一次试试。如果你看懂了以上部分,并且编译通过的话,我们就可以继续了,之后的内容将修改前面这个程序来向你展示Ogre的世界。
OGRE是如何工作的
SceneManager、Entity和SceneNode是Ogre的3个基础模块。
其中SceneManager是管理者,所有显示在屏幕上的东西都由SceneManager管理。SceneManager的类型众多,随着教程的推进,你会慢慢的了解它。
Entity就是你想要渲染的物体的模型,它们使用mesh(Ogre使用的一种文件格式)描述。在Ogre中你需要注意,物体模型是与它的位置和方向分开的。这就意味着你不能直接把一个物体放在场景里,你必须将Entity和一个SceneNode相关联,而这个SceneNode包含了位置和方向的信息。
正如前面所说,SceneNode可以和Entity相关联,关联的数量是不受限制的。这有什么用处呢?例如,你想制作一个人物在屏幕上行走,同时有一圈神圣的光环绕着他。实现这个的一种方法就是先创建一个SceneNode,然后创建一个人物的Entity并与SceneNode关联。接着再创建一个光的Entity也与SceneNode关联。人和光就这么联系在一起了,简单吧。
SceneNode不光可以和Entity相关联,和其他的SceneNode关联也是允许的。这将有助于你创建结构层次复杂的游戏世界。如果你不太明白,就想想windows中的窗口,子窗口套在父窗口里,层层嵌套就组成了一个程序的界面,而这里组成的是游戏世界的一部分,可能是人、房子,也可能是些别的什么东西。
SceneNode可以有孩子(ChildSceneNode),当然也就有父亲(ParentSceneNode)。(典型的树状结构嘛)
windows中所有窗口的根都是桌面(Desktop),在Ogre中每一个SceneManager也有这样一个根(RootSceneNode),它和其他所有的SceneNode关联着。
一个更加丰富的世界
刚才创建的程序中空荡荡的,除了数值和Logo什么也没有。现在我们添加一些代码让这个世界丰富起来。在刚才的代码中找到TutorialApplication::createScene成员函数,今天后面的代码都是添加在这个函数中的。
为了能看清楚我们将要做的事情,首先要设置场景的光线。
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
然后创建一个物体。
Entity *ent1 = mSceneMgr->createEntity("Robot","robot.mesh");
对了,还要有与之关联的SceneNode。
SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode");
最后,把它们关联在一起。
node1->attachObject(ent1);
好了,就是它了!编译运行你的程序,你会看到一个机器人站在屏幕上。如果你想了解这几个函数的具体用法请查看"OGRE API Reference",你可以在开始菜单中找到,作用相当于OGRE的MSDN。
坐标和向量
在继续深入之前,我们需要讨论一下屏幕坐标和Ogre向量对象。和许多图形引擎一样,Ogre使用x和z轴表示水平面,y轴作垂直轴。现在看着你的显示器,x轴是从你显示器的左边到右边,向右为x的正方向。y轴是从你显示器的底部到顶部,向上为y的正方向。z轴是从你的显示器屏幕内部向外延伸,向外为z的正方向。如图:
我们的机器人为什么是朝向x轴正方向的?这是mesh自身的属性,取决于它是如何设计的。Ogre不对你如何确定你模型的方向作任何假设。你所加载的每一个mesh都有它自己的开始方向。
Ogre使用向量(Vector)类而不是点(Point)类来描述位置和方向。向量的定义分2个向量(Vector2)、3个向量(Vector3)和4个向量(Vector4),其中Vector3最常用。如果你不熟悉向量,我建议你在开始用Ogre做任何事前先复习一下(向量),这对你将来复杂的编程会很有帮助。
下面我们再添加一个物体。