Ogre_初学指导_6_"帧监听(FrameListener) 及监听键盘(Keyboard)操作"

来源:互联网 发布:新版淘宝我的店铺在哪 编辑:程序博客网 时间:2024/04/30 01:27

帧监听(FrameListener) 及监听键盘(Keyboard)操作

帧监听是基于一个观察者的模式。

在OGRE中其工作流程是:

  • 在帧被渲染前,Ogre::Root 遍历所有被添加的FrameListener并调用其frameStarted()方法。直到frameStarted返回false时,帧监听终止,程序结束。

 

现在我们详细讲解帧监听的工作原理及操作。

 

一、运动方式:帧&时间

首先,我们可以在上一节的代码之上,进行添加。

创建一个新的监听类(MyFrameListener),它继承自:FrameListener。参考:小节末代码

 

1、基于“”的运动:让Sinbad模型,在每次帧渲染时更新其位置,以实现其平移效果。

  mNode->translate(Vector3(10,0,0));

2、基于“时间”的运动:因为电脑的性能不一样,更新帧的速率也就会不一样,比如一台新的电脑可能每秒100帧,但是一台旧的电脑却只能达到30帧,如果选用“帧”的运动方式,可能同一个程序,不同的电脑模型的运动速率却不相同!

            下面我们添加了evt.timeSinceLastFrame这样就可以实现基于“时间”的运动方式。

mNode->translate(Vector3(10,0,0)*evt.timeSinceLastFrame);

            因为evt(FrameEvent类)包含了在短时间内自从上一帧被渲染到现在的时间,

(Ogre::Vector3(10,0,0)*evt.timeSinceLastFrame);这行代码告诉模型每帧移动的大小。

对于每秒渲染10帧,与100帧的机器,其值分别是0.1f和0.01f,通过 * 这个值,我们就可以得到不同机器每帧的速度:(1,0,0)和(0.1,0,0),这样就可以实现“等时间等距离”的效果。

二、侦听用户操作:键盘(Keyboard)、鼠标(Mouse)

                我们将使用OIS(ObjectOriented Input System),OIS在Ogre SDK中自带。

以Keyboard为例。

首先创建键盘对象:OIS::Keyboard* _key;//如果是鼠标:OIS::Mouse*_mouse;

1、创建窗口句柄,以获取输入事件

win->getCustomAttribute("WINDOW",&windowHnd);

2、使用参数表创建输入系统

//创建输入系统

OIS::ParamListpl;

pl.insert(std::make_pair(std::string("WINDOW"),windowHndStr.str()));

_man=OIS::InputManager::createInputSystem(pl);

 

3、创建键盘接口,用于查询用户按下了哪个键

_key=static_cast<OIS::Keyboard*>(_man->createInputObject(OIS::OISKeyboard,false));

4、在started类中添加键盘状态获取函数capture

_key->capture();

5、写自己的键盘按键对应操作,如“Esc”表示退出

if(_key->isKeyDown(OIS::KC_ESCAPE))

{

            returnfalse;

}

 程序代码:

#include "ExampleApplication.h"


using namespace Ogre;


class MyFrameListener : public Ogre::FrameListener
{
private:
SceneNode *mNode;
OIS::InputManager* _man;
OIS::Keyboard* _key;
public:
MyFrameListener(SceneNode *node, RenderWindow* win)
{
mNode = node;
size_t windowHnd = 0;
std::stringstream windowHndStr;
win->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;//类型转换


//创建输入系统
OIS::ParamList pl;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
_man = OIS::InputManager::createInputSystem(pl);
_key = static_cast<OIS::Keyboard*>(_man->createInputObject(OIS::OISKeyboard, false));
}
~MyFrameListener()
{
_man->destroyInputObject(_key);//销毁键盘
OIS::InputManager::destroyInputSystem(_man);
}


bool frameStarted(const Ogre::FrameEvent &evt)
{
_key->capture();
if (_key->isKeyDown(OIS::KC_ESCAPE))
{
return false;
}
//模型节点更新位置
mNode->translate(Vector3(10,0,0) * evt.timeSinceLastFrame);
return true;
}
};


class example1 : public ExampleApplication
{
public:
example1()
{
mFrameListener = NULL;
}
~example1()
{
if (mFrameListener)
{
delete mFrameListener;
}
}
protected:
void createScene()
{
// add a plane
Plane plane(Vector3::UNIT_Y, -10);
Ogre::MeshManager::getSingleton().createPlane("plane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane, 1500, 1500, 200,200, true, 1, 5,5,Vector3::UNIT_Z);
Entity *ent = mSceneMgr->createEntity("LightPlaneEntity","plane");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
ent->setMaterialName("Examples/BeachStones");
//add a light
Light *light = mSceneMgr->createLight("Light1");
light->setType(Ogre::Light::LT_DIRECTIONAL);
light->setDirection(Vector3(1,-1,0));
//add Model
SceneNode *node = mSceneMgr->createSceneNode("Node1");
mSceneMgr->getRootSceneNode()->addChild(node);
Entity *Sinbad = mSceneMgr->createEntity("Sinbad", "Sinbad.mesh");
mSinbadNode = node->createChildSceneNode("SinbadNode");
mSinbadNode->setScale(3.0f,3.0f,3.0f);
mSinbadNode->setPosition(Vector3(0,4.0f,0));
mSinbadNode->attachObject(Sinbad);
//add Shadow
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
}
void createCamera()
{
mCamera = mSceneMgr->createCamera("MyCamera1");
mCamera->setPosition(0,100,200);
mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(5);
}
void createFrameListener()
{
mFrameListener = new MyFrameListener(mSinbadNode, mWindow);
mRoot->addFrameListener(mFrameListener);
}
private:
SceneNode *mSinbadNode;
FrameListener *mFrameListener;
};


int main()
{
example1 ex1;
ex1.go();
return 0;
}