这一次整整把一章看完了,那就一下子来一章的内容吧。
用户输入主要包括键盘和鼠标输入,要处理这两类信息,必须使用OIS和frame listener。这需要创建一个新类继承Ogre中基本的framelistener,然后在构造函数中创建OIS系统和需要监控的设备,对信息的处理可以在framestarted中进行,也可以在frameended或者framerenderingqueue中进行,对输入的处理貌似一般在started中进行。
这次还用到了一个定时器timer,用来确定两次按键间隔大于0.25s,好用易懂,reset就好了。
要注意OIS系统的初始化、使用和析构。
#include "Ogre\ExampleApplication.h"
class Example25FrameListener:public Ogre::FrameListener
{
public:
Example25FrameListener(RenderWindow* win, Ogre::Camera* cam)
{
this ->_movementspeed = 3;
size_t windowHnd = 0; //从这里开始OIS系统的初始化,主要提供窗口句柄windowHnd
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));
_mouse = static_cast<OIS::Mouse*>(_man ->createInputObject(OIS::OISMouse, false));
_Cam = cam;
_PolyMode = Ogre::PolygonMode::PM_SOLID;
_timer.reset();
}
~Example25FrameListener()
{
_man ->destroyInputObject(_key);
_man ->destroyInputObject(_mouse);
OIS::InputManager::destroyInputSystem(_man);
}
bool frameStarted(const Ogre::FrameEvent& evt)
{
Ogre::Vector3 translate(0, 0, 0);
_key ->capture();
_mouse ->capture();
if(_key ->isKeyDown(OIS::KC_R) && _timer.getMilliseconds() > 250)//多边形模式的变化,这里用到了timer
{
if(_PolyMode == Ogre::PolygonMode::PM_SOLID)
{
_PolyMode = Ogre::PolygonMode::PM_WIREFRAME;
}
else if(_PolyMode == Ogre::PolygonMode::PM_WIREFRAME)
{
_PolyMode = Ogre::PolygonMode::PM_POINTS;
}
else if(_PolyMode == Ogre::PolygonMode::PM_POINTS)
{
_PolyMode = Ogre::PolygonMode::PM_SOLID;
}
_Cam ->setPolygonMode(_PolyMode);
_timer.reset();
}
if(_key ->isKeyDown(OIS::KC_W)) //镜头的位移
{
translate += Ogre::Vector3(0, 0, -10);
}
if(_key ->isKeyDown(OIS::KC_S))
{
translate += Ogre::Vector3(0, 0, 10);
}
if(_key ->isKeyDown(OIS::KC_A))
{
translate += Ogre::Vector3(-10, 0, 0);
}
if(_key ->isKeyDown(OIS::KC_D))
{
translate += Ogre::Vector3(10, 0, 0);
}
float rotX = _mouse ->getMouseState().X.rel * evt.timeSinceLastFrame * (-0.5); //镜头的旋转
float rotY = _mouse ->getMouseState().Y.rel * evt.timeSinceLastFrame * (-0.5);
_Cam ->yaw(Ogre::Radian(rotX));
_Cam ->pitch(Ogre::Radian(rotY));
_Cam ->moveRelative(translate * evt.timeSinceLastFrame * _movementspeed);
if(_key ->isKeyDown(OIS::KC_ESCAPE))
{
return false;
}
return true;
}
private:
OIS::InputManager* _man;
OIS::Keyboard* _key;
Ogre::Camera* _Cam;
OIS::Mouse* _mouse;
size_t _movementspeed;
Ogre::PolygonMode _PolyMode;
Ogre::Timer _timer;
};
class Example25:public ExampleApplication
{
public:
Ogre::FrameListener* FrameListener;
Example25()
{
FrameListener = NULL;
}
~Example25()
{
if(FrameListener)
{
delete FrameListener;
}
}
void createFrameListener()
{
FrameListener = new Example25FrameListener(mWindow, mCamera);
mRoot ->addFrameListener(FrameListener);
}
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::Light* light = mSceneMgr ->createLight("Light1");
light ->setType(Ogre::Light::LT_DIRECTIONAL);
light ->setDirection(Ogre::Vector3(1, -1, 0));
Ogre::SceneNode* node = mSceneMgr ->createSceneNode("Node1");
mSceneMgr ->getRootSceneNode() ->addChild(node);
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(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
}
void createCamera()
{
mCamera = mSceneMgr ->createCamera("MyCamera1");
mCamera ->setPosition(0, 100, 200);
mCamera ->lookAt(0, 0, 0);
mCamera ->setNearClipDistance(5);
}
private:
Ogre::SceneNode* _SinbadNode;
};
int main(void)
{
Example25 app;
app.go();
return 0;
}