ogre中级教程Word格式文档下载.docx
- 文档编号:5344588
- 上传时间:2023-05-05
- 格式:DOCX
- 页数:116
- 大小:90.80KB
ogre中级教程Word格式文档下载.docx
《ogre中级教程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《ogre中级教程Word格式文档下载.docx(116页珍藏版)》请在冰点文库上搜索。
前期准备
首先,这个指南假设你已经知道如何设置Ogre的项目环境以及如何正确编译项目。
该例子同样使用STL
中的queue数据结构。
那么预先了解如何使用queue是必要的,至少你需要知道什么是模版。
如果你不熟悉STL,那么我像你推荐STL参考[ISBN
0596005563],它可以帮助你在将来花费更少的时间。
准备开始
首先,你需要为这个Demo创建一个新项目,在项目中添加一个名为"
MoveDemo.cpp"
的文件并加入如下代码:
#include"
ExampleApplication.h"
#include<
deque>
usingnamespacestd;
classMoveDemoListener:
publicExampleFrameListener
{
public:
MoveDemoListener(RenderWindow*win,Camera*cam,SceneNode*sn,
Entity*ent,deque<
Vector3>
&
walk)
:
ExampleFrameListener(win,cam,false,false),mNode(sn),mEntity(ent),mWalkList(walk)
{
}//MoveDemoListener
/*Thisfunctioniscalledtostarttheobjectmovingtothenextposition
inmWalkList.
*/
boolnextLocation()
returntrue;
}//nextLocation()
boolframeStarted(constFrameEvent&
evt)
returnExampleFrameListener:
:
frameStarted(evt);
}
protected:
RealmDistance;
//Thedistancetheobjecthaslefttotravel
Vector3mDirection;
//Thedirectiontheobjectismoving
Vector3mDestination;
//Thedestinationtheobjectismovingtowards
AnimationState*mAnimationState;
//Thecurrentanimationstateoftheobject
Entity*mEntity;
//TheEntityweareanimating
SceneNode*mNode;
//TheSceneNodethattheEntityisattachedto
std:
deque<
mWalkList;
//Thelistofpointswearewalkingto
RealmWalkSpeed;
//Thespeedatwhichtheobjectismoving
};
classMoveDemoApplication:
publicExampleApplication
MoveDemoApplication()
~MoveDemoApplication()
//Theentityoftheobjectweareanimating
//TheSceneNodeoftheobjectwearemoving
//Adequecontainingthewaypoints
voidcreateScene(void)
voidcreateFrameListener(void)
mFrameListener=newMoveDemoListener(mWindow,mCamera,mNode,mEntity,mWalkList);
mFrameListener->
showDebugOverlay(true);
mRoot->
addFrameListener(mFrameListener);
#ifOGRE_PLATFORM==OGRE_PLATFORM_WIN32
#defineWIN32_LEAN_AND_MEAN
windows.h"
INTWINAPIWinMain(HINSTANCEhInst,HINSTANCE,LPSTRstrCmdLine,INT)
#else
intmain(intargc,char**argv)
#endif
//Createapplicationobject
MoveDemoApplicationapp;
try{
app.go();
}catch(Exception&
e){
MessageBox(NULL,e.getFullDescription().c_str(),"
Anexceptionhasoccured!
"
MB_OK|MB_ICONERROR|MB_TASKMODAL);
fprintf(stderr,"
Anexceptionhasoccured:
%s/n"
e.getFullDescription().c_str());
return0;
}
在我们继续讲解之前,你可以编译这部分代码看下效果。
设置场景
在我们开始之前,需要注意的是已经在MoveDemoApplication中预先定义的三个变量。
我们创建的entity实例保存在变量mEntity中,我们创建的node实例保存在mNode中,另外mWalkList包含了所有我们希望对象行走到的节点。
定位到MoveDemoApplication:
createScene函数并且加入以下代码。
首先,我们来设置环境光(ambient
light)到最大,这样可以让我们看到我们放在场景中的所有对象。
//Setthedefaultlighting.
mSceneMgr->
setAmbientLight(ColourValue(1.0f,1.0f,1.0f));
接下来我们来在屏幕上创建一个可以使用的机器人。
要做到这点我们需要在创建SceneNode之前先为机器人创建一个entity使得我们可以对其进行旋转。
//Createtheentity
mEntity=mSceneMgr->
createEntity("
Robot"
"
robot.mesh"
);
//Createthescenenode
mNode=mSceneMgr->
getRootSceneNode()->
createChildSceneNode("
RobotNode"
Vector3(0.0f,0.0f,25.0f));
mNode->
attachObject(mEntity);
以上这些都是非常基础的,所以我认为不需要再对以上的描述做任何解释。
在接下来的代码片断,我们将开始告诉机器人那些地方是它需要到达的。
这里需要你们了解一些STL的知识,deque对象是一个高效的双端对列。
我们只需要使用它的几个简单的方法。
push_front和push_back方法分别将对象放入队列的前端和后端,front和back方法分别返回当前队列前端和后端的元素(PS:
注意,这里最好有判空的习惯,用if(
empty())
)pop_front和pop_back两个方法分别从队列两端移除对象。
最后,empty方法返回该队列是否为空。
下面这些代码添加了两个Vector到队列中,在后面我们移动robot的时候会用到它们。
//Createthewalkinglist
mWalkList.push_back(Vector3(550.0f,
0.0f,
50.0f
));
mWalkList.push_back(Vector3(-100.0f,
0.0f,-200.0f));
接下来,我们在场景里放置一些物体,以标记这个机器人应该朝哪走去。
这样使我们能看见机器人在场景里相对于其它物体进行移动。
注意它们的位置的负Y部分,这些物体被放在机器人移动目的地的正下方,当它到达指定地点时,它就站在这些物体上面。
//Createobjectssowecanseemovement
Entity*ent;
SceneNode*node;
ent=mSceneMgr->
Knot1"
knot.mesh"
node=mSceneMgr->
createChildSceneNode("
Knot1Node"
Vector3(
0.0f,-10.0f,
25.0f));
node->
attachObject(ent);
setScale(0.1f,0.1f,0.1f);
Knot2"
Knot2Node"
Vector3(550.0f,-10.0f,
50.0f));
Knot3"
Knot3Node"
Vector3(-100.0f,-10.0f,-200.0f));
最后,我们要创建一个摄像机从适合的角度来观察它。
我们来把摄像机移动到更多的位置。
//Setthecameratolookatourhandywork
mCamera->
setPosition(90.0f,280.0f,535.0f);
pitch(Degree(-30.0f));
yaw(Degree(-15.0f));
现在编译并运行代码。
你应该能看到这个样子:
[[1]]
在进入下一个部分之前,注意一下MoveDemoListener的构造器,它在MoveDemoApplication:
createFrameListener方法里的第一行被调用。
除了传入BaseFrameListener的标准参数,还有场景节点、实体、双端队列。
动画
现在我们来设置一些基本的动画。
在Ogre里动画是非常简单的。
要做的话,你需要从实体对象里获取AnimationState,设置它的选项,并激活它。
这样就能使动画活动起来,但你还必须在每一帧后给它添加时间,才能让动画动起来。
我们设置成每次移动一步。
首先,找到MoveDemoListener的构造器,并添加以下代码:
//Setidleanimation
mAnimationState=ent->
getAnimationState("
Idle"
);
mAnimationState->
setLoop(true);
setEnabled(true);
第二行从实体中获取到了AnimationState。
第三行我们调用setLoop(true
),让动画不停地循环。
而在一些动画里(比如死亡动画),我们可能要把这个设置为false。
第四行才把这个动画真正激活。
但等等...我们从哪里获取的“Idle”?
这个魔术般的常量是怎么飞到这里来的?
每个mesh都有它们自己定义的动画集。
为了能够查看某个mesh的全部动画,你需要下载OgreMeshViewer才能看到。
现在,如果我们编译并运行这个demo,我们看见了...nothing!
这是因为我们还需要在每一帧里根据时间来更新这个动画的状态。
找到MoveDemoListener:
frameStarted方法,在方法的开头添加这一行:
addTime(evt.timeSinceLastFrame);
现在来编译并运行程序。
你应该可以看了一个机器人正在原地踏步了。
移动角色
现在我们执行棘手的任务,开始让这个机器人从一点走到另一点。
在我们开始之前,我想介绍一下保存在MoveDemoListener类里的成员变量。
我们将使用4个变量来完成移动机器人的任务。
首先,我们把机器人移动的方向保存到mDirection里面。
我们再把当前机器人前往的目的地保存在mDestination里。
然后在mDistance保存机器人离目的地的距离。
最后,在mWalkSpeed里我们保存机器人的移动速度。
首先清空MoveDemoListener构造器,我们会用稍微不同的代码来替换。
我们要做的第一件事是设置这个类的变量。
我们将把行走速度设为每秒35个单位。
有一个大问题要注意,我们故意把mDirection设成零向量,因为后面我们会用它来判断机器人是否正在行走。
//Setdefaultvaluesforvariables
mWalkSpeed=35.0f;
mDirection=Vector3:
ZERO;
好了,搞定了。
我们要让机器人动起来。
为了让机器人移动,我们只须告诉它改变动画。
然而,我们只想要若存在另一个要移动到的地点,就让机器人开始移动。
为了这个目的,我们调用nextLocation
函数。
把代码加到MoveDemoListener:
frameStarted方法的顶部,在调用AnimationState:
addTime之前:
if(mDirection==Vector3:
ZERO)
if(nextLocation())
//Setwalkinganimation
mAnimationState=mEntity->
Walk"
如果你现在编译并运行,这个机器人将原地行走。
这是由于机器人是以ZERO方向出发的,而我们的MoveDemoListener:
nextLocation函数总是返回true。
在后面的步骤中,我们将给MoveDemoListener:
nextLocation函数添加更多的一点智能。
现在,我们准备要真正在场景里移动机器人了。
为了这样做,我们需要在每一帧里让我移动一点点。
frameStarted方法,我们将在调用AnimationState:
addTime之前,我们先前的if语句之后,添加以下代码。
这段代码将处理当机器人实际移动的情况;
mDirection
!
=Vector3:
ZERO。
else
Realmove=mWalkSpeed*evt.timeSinceLastFrame;
mDistance-=move;
现在,我们要检测一下我们是否“走过”了目标地点。
即,如果现在mDistance小于0,我们需要“跳”到这点上,并设置移动到下一个地点。
注意,我们把mDirection设置成零向量。
如果nextLocation方法不改变mDirection(即没有其它地方可去),我们就不再四处移动了。
if(mDistance<
=0.0f)
setPosition(mDestination);
现在我们移动到了这个点,我们需要设置运动到下一个点。
只要我们知道有否需要移动到下一个地点,我们就能设置正确的动画;
如果有其它地点要去,就行走。
如果没有其它目的地,则停滞。
//Setanimationbasedoniftherobothasanotherpointtowalkto.
if(!
nextLocation())
//SetIdleanimation
}
//RotationCodewillgoherelater
注意,如果queue里已经没有更多的地点要走的话,我们没有必要再次设置行走动画。
既然机器人已经在行走了,没有必要再告诉他这么做。
然而,如果机器人还要走向另一个地点,我们就要把它旋转以面对那个地点。
现在,我们在else括号旁边留下注释占位符;
记住这个地点,因为我们后面还要回来。
这里考虑的是当我们离目标地点很近的时候。
现在我们需要处理一般情况,当我们正在到达而没有到达的时候。
为此,我们在机器人的行走方向上对它进行平移,用move变量指定的值。
通过添加以下代码来实现:
translate(mDirection*move);
}//else
}//if
我们差不多做完了,除了还要设置运动需要的变量。
如果我们正确地设置了运动变量,我们的机器人就会朝它该去的方向行走。
看看MoveDemoListener:
nextLocation方法,如果我们用完了所有的地点,它返回false。
这是函数的第一行。
(注意你要保留函数底部的return
true语句)
if(mWalkList.empty())
returnfalse;
现在我们来设置变量。
首先我们从双端队列里取出一个向量。
通过目标向量减去场景节点的当前向量,我们得取方向向量。
然而我们仍有一个问题,还记得我们要在frameStarted方法里用mDirection乘以移动量吗?
如果我们这么做,我们必须把方向向量转换成单位向量(即,它的长度等于一)。
normalise函数为我们做了这些事,并返回向量的原始长度。
唾手可得,我们需要设置到目的地的距离。
mDestination=mWalkList.front()
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ogre 中级 教程