如何使用OGRE做游戏?
OGRE使用指南:
在这里我们将学习OGRE的方方面面:SceneManager,SceneNode,Entity.我们会重点介绍一些在OGRE中使用的概念.
随着我们了解得越来越多,我们将能够编写自己得游戏,代码量会越来越大!
让我们开始吧:
首先让我们来写一些代码,这些是我们游戏得基本框架,随着我们框架得逐步完善,你将慢慢明白
OGRE的流程:
#include "ExampleApplication.h"
class TutorialApplication : public ExampleApplication
{
protected:
public:
TutorialApplication()
{
}
~TutorialApplication()
{
}
protected:
void createScene(void)
{
}
};
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
TutorialApplication app;
try {
app.go();
} catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!",
MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occured: %s/n",
e.getFullDescription().c_str());
#endif
}
return 0;
}
如果你是在windows平台下开发,并且已经安装了 OGRE SDK,确定把"[OgreSDK_DIRECTORY]/samples/include"添加到工程的引用库里面.请先正确编译和运行上面的代码再接着看以下内容,这将使你更加有信心.尽管它运行时只有的界面和一个盒子,这将使OGRE世界中的"Hello World".
请确定再可执行文件的目录下有以下两个文件:plugins.cfg,resources.cfg.plugins.cfg告诉OGRE将使用哪个运行库(Direct3D9 or OpenGL).Resources.cfg被ExampleApplication所使用并且指定纹理,网格脚本的路径.以上两个文件都使文本文件,必要时编辑它们,以确保路径时正确的。否则将出现错误。
OGRE是如何工作的?
这是一个相当宽泛的问题,只研究一点显然不能够得到答案。我们将相继介绍
SceneManagers,Entities,SceneNodes.这三个类是OGRE的基石.
SceneManager 基础:
我们再屏幕上看到的一切都通过SceneManager来管理,当你把一个物体放到场景中去的时候,SceneManager就是我们来跟踪它们位置的类.当你创建了一个相机来观察场景的时候,SceneManager将用来跟踪相机的位置,当你创建了飞机,灯光等等,SceneManager来跟踪他们.
正如我们以后将要看到的一样,有很多中SceneManager,有用来渲染terrain的SceneManager,有用来渲染BSP图的SceneManager等等.
Octree Scene Manager
Terrain Scene Manager
Nature Scene Manager
Paging Scene Manager
BSP Scene Manager
DotSceneOctree SceneManager
我们将再以后详细介绍每个 SceneManager
Entity 基础:
一个Entity就是我们将要渲染到屏幕上的一个对象,我们可以把Entity想象成任何3D网格模型.一个系统任务可以是一个Entity,一条鱼是一个Entity,游戏中的地形也是Entity.但是,灯光,例子,相机等等都不是 Entity.
这里有一点我们需要注意,那就是OGRE将所要渲染的物体与它们的位置分开了,这就意味着我们不能只创建一个Entity,然后把它放置到现场中,只能通过将它与一个SceneNode绑定才能够放置它到场景中,SceneNode中包括了位置的信息.
SceneNode 基础:
在前面我们已经提到,SceneNode中维护着与它绑定的对象的位置,当你创建了一个Entity对象时,只有你将它与一个SceneNode对象绑定时才能在场景中渲染它.它们之间的这种关心时对应的,我们也不能直接将一个SceneNode对象直接在场景中渲染,直到有Entity绑定在它身上.
一个SceneNode可以由很多对象绑定到它身上,比如说有一个人在走动情景,我们想在他周围加上灯光.我们可以这样来实现:让我们首先来创建一个SceneNode对象,然后创建人物Entity,并且把它绑定在先创建的那个SceneNode上,然后我们再创建灯光对象,并且将灯光与SceneNode绑定.不仅如此,SceneNode还可以跟其它的SceneNode绑定,这样就可以形成一个有层次的结构.我们应该记住很重要
的一点,那就是一个SceneNode的位置是跟它父节点的位置是相关的,并且每个SceneManager都包含一个
SceneNode层次结构的根节点.
现在回到我们刚才的"hello world",找到函数:TutorialApplication::createScene,现在我们只关
心这个函数.我们要做的第一件事情就是打开环境光.这通过调用函数setAmbientLight来实现,它接受一
个颜色参数以用来指定光的颜色.这里需要注意的是颜色值RGB的分量都是在0和1之间的.
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
接下来我们就要创建一个Entity,看下面的代码:
Entity *ent1=mSceneMgr->createEntity("Robot","robot.mesh");
Ok,现在你的头脑中肯定产生了很多问题:mSceneMgr是什么?在上个函数中的各个参数的含义是什么?
现在让我来告诉你:mSceneMgr包含了当前的SceneManger对象(ExampleApplication为我们做了这些).再
来看createEntity的参数,第一个参数是我们所要创建的Entity的名字,每个Entity都必须有一个唯一的
名字.如果创建一个同名的Entity就会有错误发生."robot.mesh"是我们所创建的Entity所用到的网格.
我们所要用到的网格被ExampleApplication预先导入了.
好,我们现在创建了Entity,按照我们前面所说,现在该为它创建一个SceneNode.因为每个
SceneManager都有个根节点,现在我们就来创建它的子节点:
SceneNode * node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode");
上面的语句首先是调用了getRootSceneNode来得到当前的SceneManager,然后就来创建它的子节点.
参数就是我们所创建的SceneNode的名字,同Entity一样,不能有重名的.
最后我们要把Entity绑定在SceneNode上,以使得Entity有一个位置用来渲染.
node1->attachObject(ent1);
好的,现在就来了编译我们的程序,就将看到一个人物站在场景中.
注意:robot.mesh没有在ogreCore.zip中,修改resources.cfg:
FileSystem=../../media/materials/programs
FileSystem=../../media/materials/scripts
FileSystem=../../media/materials/textures
FileSystem=../../media/models
以使得我们的程序能正常工作.
坐标与向量:
在我们继续之前,先来看一下OGRE中的坐标系跟向量对象. OGRE跟其它的图形引擎一样使用x,z来表
示水平平面, 用y来表示垂直方向.面对你的显示器,x轴是从左到右,右边是正方向;y轴是从下到上,上
方是正方向;z轴是从里向外,外面是正方向.
OGRE是用向量类来表示位置跟方向的,Vector2,Vector3,Vector4是OGRE中定义的三种向量,然而我们
最常使用的是Vector3.在继续前进之前请确定你右足够的向量方面的数学知识,这对以后的学习是非常
重要的.
添加更多对象:
现在你明白了坐标系统如何工作的,现在让我们继续看我们的代码.我们如何来指定对象的位置呢?大
多数的函数都是右默认值的,比如说,SceneNode::createChildSceneNode成员函数右三个参
数:SceneNode的名字,位置,朝向.它的位置,正如我们先前看到的一样默认是在(0,0,0)处,现在让我们来
重新创建一个节点,这次我们让它处在不同的位置:
Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode(
"RobotNode2", Vector3( 50, 0, 0 ) );
node2->attachObject( ent2 );
这里的代码大多数跟以前是一样的,有两处小区别:一个是名称,再一个就是对象的初始位置,这
次我们是把对象放在了(50,0,0)处.
下面我们来列举一些Entity的常用函数:
setVisible()
isVisible()
getName()
getParentSceneNode()
至于Entity类是如何实现的,大家现在先不要急于了解这些,以后的学习中慢慢体会,一开始就过度
了解细节有可能打击我们的积极性.
SceneNode的一些常用函数:
//位置相关
getPositiion()
setPosition()
translate()
//旋转
scale()
yaw()
roll()
pitch()
resetOrientation()
setOrientation()
getOrientation()
rotate()
//其它
attachObject()
numAttachedObject()
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 );
如果我们把第五行:
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.下面这行代码就只移动了node2:
node2->translate( Vector3( 10, 0, 10 ) );
下面的这段代码是移动的node1,因为node2是node1的子节点,所以niode2也就跟着移动了.
node1->translate( Vector3( 25, 0, 0 ) );
练习一下这些代码:
缩放:
Entity *ent = mSceneMgr->createEntity( "Robot", "robot.mesh" );
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
node->attachObject( ent );
node->scale( .5, 1, 2 );
ent = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode2", Vector3( 50,
0, 0 ) );
node->attachObject( ent );
node->scale( 1, 2, 1 );
旋转:
Entity *ent = mSceneMgr->createEntity( "Robot", "robot.mesh" );
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode(
"RobotNode", Vector3( -100, 0, 0 ) );
node->attachObject( ent );
node->yaw( Degree( -90 ) );
ent = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode2");
node->attachObject( ent );
node->pitch( Degree( -90 ) );
ent = mSceneMgr->createEntity( "Robot3", "robot.mesh" );
node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode3", Vector3(
100, 0, 0 ) );
node->attachObject( ent );
node->roll( Degree( -90 ) );
本文地址:http://www.45fan.com/dnjc/67893.html