1.帧监听
现在我们代替其原有的FrameListener,使用我们自己定义的实现过程.这样我们就不能使用自带的Framelistener.
class Example25FrameListener : public Ogre::FrameListener
{
};
新建一个类,继承FrameListener.
private:
Ogre::SceneNode* _node;
_node:私有变量,指向场景节点指针.
以下是成员函数
bool frameStarted(const Ogre::FrameEvent &evt)
{
_node->translate(Ogre::Vector3(0.1,0,0));
return true;
}
frameStarted:在帧(帧,意思是指场景中的单个图像)被渲染之前,Ogre::Root 遍历所有被添加的Framelistener并调用其frameStarted()方法.每次调用这个函数时使相应的节点移动0.1.
如果想让帧移动的速率和机器无关,把_node->translate(Ogre::Vector3(10,0,0));换成如下一行.
_node->translate(Ogre::Vector3(10,0,0) * evt.timeSinceLastFrame);
evt.timeSinceLastFrame:字面意思.
void createFrameListener()
{
FrameListener = new Example25FrameListener(_SinbadNode);
mRoot->addFrameListener(FrameListener);
}
FrameListener:上述类定义的一个对象,
2.添加输入支持
添加用户输入对象作为成员变量到帧监听类中:
OIS::InputManager* _man;
OIS::Keyboard* _key;
InputManager: 定义一个输入管理器.
Keyboard: 定义一个控制键盘操作的指针.
构造函数修改为:
Example25FrameListener(Ogre::SceneNode* node,RenderWindow* win)
{
_node = node;
FrameListener = NULL;
size_t windowHnd = 0;
win->getCustomAttribute("WINDOW", &windowHnd); //获取窗口的句柄
windowHndStr << windowHnd;
OIS::ParamList pl; //创建OIS参数表
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 )); //创建一个键盘来监听用户的输入
}
RenderWindow* win:传来渲染窗口对象的指针.因为我们需要渲染窗口的句柄来创建输入系统.
windowHndStr<<windowHnd:把句柄从数值类型转化成字符串类型.
接下来是析构函数:
~Example27FrameListener()
{
_man->destroyInputObject(_key);
OIS::InputManager::destroyInputSystem(_man);
}
之前的frameStarted改为:
bool frameStarted(const Ogre::FrameEvent &evt)
{
_node->translate(Ogre::Vector3(0.1,0,0));
_key->capture(); //捕获按键
if(_key->isKeyDown(OIS::KC_ESCAPE))
{
return false;
}
return true;
}
因为监听类发生了变化,所以在createFrameListener中的初始化实例的过程也要发生变化:
void createFrameListener()
{
FrameListener = new Example25FrameListener(_SinbadNode,mWindow);
mRoot->addFrameListener(FrameListener);
}
mWindow:这个变量是从父类继承下来的,不需要我们实例化.
3.添加漫游摄像机
#include "Ogre\ExampleApplication.h"
class Example30FrameListener : public Ogre::FrameListener //公有继承帧监听类
{
private:
Ogre::SceneNode* _node; //场景节点指针
Ogre::Camera* _Cam; //摄像机指针,用来接受主类传过来的摄像机指针
OIS::InputManager* _man; //输入管理者
OIS::Keyboard* _key; //键盘控制
OIS::Mouse* _mouse; //鼠标控制
float _movementspeed; //移动速度
public:
Example30FrameListener(Ogre::SceneNode* node,RenderWindow* win,Ogre::Camera* cam) //需要三个参数:场景节点指针,渲染窗口指针,摄像机指针
{
_node = node; //你懂得
_Cam = cam; //你懂得
_movementspeed = 200.0f; //设置速度
size_t windowHnd = 0; //用来接收句柄的
std::stringstream windowHndStr; //定义句柄字符串
win->getCustomAttribute("WINDOW", &windowHnd); //用传进来的渲染窗口指针获取句柄
windowHndStr << windowHnd; //转str
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 )); //初始化键盘控制
_mouse = static_cast<OIS::Mouse*>(_man->createInputObject( OIS::OISMouse, false )); //初始化鼠标控制
}
bool frameStarted(const Ogre::FrameEvent &evt) //每渲染一帧前都会调用一次这个函数
{
Ogre::Vector3 translate(0,0,0); //每次都使它归0,避免速度一直叠加
_key->capture(); //捕获键盘和鼠标
_mouse->capture();
if(_key->isKeyDown(OIS::KC_ESCAPE))
{
return false;
}
if(_key->isKeyDown(OIS::KC_W))
{
translate += Ogre::Vector3(0,0,-1);
}
if(_key->isKeyDown(OIS::KC_S))
{
translate += Ogre::Vector3(0,0,1);
}
if(_key->isKeyDown(OIS::KC_A))
{
translate += Ogre::Vector3(-1,0,0);
}
if(_key->isKeyDown(OIS::KC_D))
{
translate += Ogre::Vector3(1,0,0);
}
float rotX = _mouse->getMouseState().X.rel * evt.timeSinceLastFrame* -1; //捕获鼠标绕X,Y旋转了多少,返回的是弧度
float rotY = _mouse->getMouseState().Y.rel * evt.timeSinceLastFrame * -1;
_Cam->yaw(Ogre::Radian(rotX)); //绕Y轴旋转摄像机
_Cam->pitch(Ogre::Radian(rotY)); //绕X轴旋转摄像机
_Cam->moveRelative(translate*evt.timeSinceLastFrame * _movementspeed); //让摄像机平移
return true;
}
};
class Example30 : public ExampleApplication
{
private:
Ogre::SceneNode* _SinbadNode; //Sinbad节点
public:
void createScene()
{
Ogre::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);
Ogre::Entity* ent = mSceneMgr->createEntity("LightPlaneEntity", "plane");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
ent->setMaterialName("Examples/BeachStones");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
mSceneMgr->getRootSceneNode()->addChild(node);
Ogre::Light* light = mSceneMgr->createLight("Light1");
light->setType(Ogre::Light::LT_DIRECTIONAL);
light->setDirection(Ogre::Vector3(1,-1,0));
Ogre::Entity* Sinbad = mSceneMgr->createEntity("Sinbad", "Sinbad.mesh");
_SinbadNode = node->createChildSceneNode("SinbadNode");
_SinbadNode->setScale(3.0f,3.0f,3.0f);
_SinbadNode->setPosition(Ogre::Vector3(0.0f,4.0f,0.0f));
_SinbadNode->attachObject(Sinbad);
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
}
void createCamera() //如果把这里的摄像机信息加入到createScene中去的话,则不能控制摄像头了
{
mCamera = mSceneMgr->createCamera("MyCamera1");
mCamera->setNearClipDistance(5);
mCamera->setPosition(0,100,200);
}
void createFrameListener() //顾名思义,创建帧监听
{
Ogre::FrameListener* FrameListener = new Example30FrameListener(_SinbadNode,mWindow,mCamera);
mRoot->addFrameListener(FrameListener);
}
};
int main (void)
{
Example30 app;
app.go();
return 0;
}