经过前两两篇博文的解说。我们已经完毕了渲染工作,但仅仅是渲染而没有交互性,本篇博文我们就来加上事件的处理方法。

首先我们须要为项目加入一个帧监听类:CMyFrameListener,为了直观,在这直接贴上代码

头文件

#pragma once
#include "ogre.h"
#include "OgreConfigFile.h"
#include "OgreFrameListener.h"
#include "OgreStringConverter.h"
#include "OIS.h" #include "MyOgreApp.h"
#include <OISEvents.h>
#include <OISInputManager.h>
#include <OISKeyboard.h>
#include <OISMouse.h> #include <SdkTrays.h>
#include <SdkCameraMan.h>
using namespace Ogre;
class CMyFrameListener: public FrameListener, public OIS::MouseListener,public Ogre::WindowEventListener, public OIS::KeyListener
{
public:
CMyFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneMgr, Light* light);
~CMyFrameListener(void);
bool frameRenderingQueued(const Ogre::FrameEvent& evt);
bool mouseMoved(const OIS::MouseEvent &e);
bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id);
bool mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id);
bool keyPressed(const OIS::KeyEvent &e);
bool keyReleased(const OIS::KeyEvent &e); protected: Ogre::SceneManager *mSceneMgr;//场景管理器
Ogre::SceneNode* mCamNode;//摄像机节点
Ogre::Camera* mCamera;//摄像机
Ogre::RenderWindow* mWindow;//渲染窗体
Ogre::Light* light;//灯光 OIS::Keyboard* mKeyboard;//键盘
OIS::Mouse* mMouse; //鼠标
OIS::InputManager* mInputManager;//输入管理器 // OgreBites::SdkTrayManager* mTrayMgr;
OgreBites::SdkCameraMan* mCameraMan; // basic camera controller
bool mRBtdown;
};

源文件

#include "StdAfx.h"
#include "MyFrameListener.h" CMyFrameListener::CMyFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneMgr, Light *l): mMouse(0),
mKeyboard(0), mInputManager(0), mWindow(win), mCamera(cam), light(l)
{
mRBtdown = false;
mCamNode=cam->getParentSceneNode();
mSceneMgr = sceneMgr; size_t windowHnd = 0;
std::ostringstream windowHndStr;
OIS::ParamList pl; mCameraMan = new OgreBites::SdkCameraMan(mCamera); windowHnd = (size_t )AfxGetMainWnd()->GetSafeHwnd(); // 这里这个窗体句柄就是传入的MFC主窗体
windowHndStr << windowHnd;
// OIS的窗体必需要顶层窗体,所以仅仅有传MFC的主窗体给他,传view就不行
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); // 设置鼠标显示和非游戏独占,这样鼠标能够显示在屏幕上并能够移动到窗体外
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
// 键盘非游戏独占
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
mInputManager = OIS::InputManager::createInputSystem(pl); mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true )); mMouse->setEventCallback(this);
mKeyboard->setEventCallback(this);
} CMyFrameListener::~CMyFrameListener(void)
{
mInputManager->destroyInputObject(mMouse);
mInputManager->destroyInputObject(mKeyboard);
OIS::InputManager::destroyInputSystem(mInputManager);
mInputManager = 0;
} bool CMyFrameListener::frameRenderingQueued(const Ogre::FrameEvent& e){ mMouse->capture();
mKeyboard->capture();
mCameraMan->frameRenderingQueued(e);
return true;
} bool CMyFrameListener::mouseMoved(const OIS::MouseEvent &e)
{
if (mRBtdown)
{
mCameraMan->injectMouseMove(e);
} return true;
} bool CMyFrameListener::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
{
// mCameraMan->injectMouseDown(e, id);
if (id == OIS::MB_Right)
{
mRBtdown = true;
} return true;
} bool CMyFrameListener::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
{ // mCameraMan->injectMouseUp(e, id);
if (id == OIS::MB_Right)
{
mRBtdown = false;
}
return true;
}
//键盘响应
bool CMyFrameListener::keyPressed(const OIS::KeyEvent &e)
{ mCameraMan->injectKeyDown(e); return true;
} bool CMyFrameListener::keyReleased(const OIS::KeyEvent &e)
{
mCameraMan->injectKeyUp(e);
return true;
}

此类实现了对于鼠标和键盘事件的监听与响应。按住鼠标右键拖动可旋转摄像机角度,WASD和方向键可移动摄像机位置。里面的代码都非常easy,我就不再赘述了。

以下改动CMyOgreApp类其可以响应鼠标和键盘的事件。

1、首先在MyOgreApp.h中加入监听类的引用

#include "MyFrameListener.h"

2、声明一个CMyFrameListener类的变量

class CMyFrameListener* mListener;

3、声明一个函数

void createFrameListener(void);

4、在MyOgreApp.cpp文件里定义createFrameListener()

void CMyOgreApp::createFrameListener(void)
{
mListener= new CMyFrameListener(mWindow, mCamera, mSceneMgr, light);
mRoot->addFrameListener(mListener);
}

5、在go() 函数中调用createFrameListener()

bool CMyOgreApp::go(CRect rt, HWND hWnd)
{
createRoot();
setupResources();
setupRenderSystem();
createRenderWindow(hWnd, rt.Width(), rt.Height());
chooseSceneManager();
createCamera();
createViewport();
initializeResourceGroups();
createScene();
createFrameListener();//创建侦听
return true;
}

生成并执行。使用鼠标和键盘就能够控制摄像机运动了。

至此,整个工作就完毕了,希望这几篇文章能帮到还在受这个问题困扰的朋友。

 PS:整个项目都在我上传的资源中,配置好环境变量,再依照里面的说明简单配置下就能编译执行

Demo地址:http://download.csdn.net/detail/guoyk1990/7360731

Ogre嵌入MFC傻瓜全然教程(三)的更多相关文章

  1. VS2010/MFC编程入门教程之目录和总结

    鸡啄米的这套VS2010/MFC编程入门教程到此就全部完成了,虽然有些内容还未涉及到,但帮助大家进行VS2010/MFC的入门学习业已足够.以此教程的知识为基础,学习VS2010/MFC较为深入的内容 ...

  2. webpack之傻瓜式教程

    接触webpack也有挺长一段时间了,公司的项目也是一直用着webpack在打包处理,但前几天在教新人的情况下,遇到了一个问题,那就是:尽管网上的webpack教程满天飞,但是却很难找到一个能让新人快 ...

  3. CRL快速开发框架系列教程三(更新数据)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  4. 手把手教从零开始在GitHub上使用Hexo搭建博客教程(三)-使用Travis自动部署Hexo(1)

    前言 前面两篇文章介绍了在github上使用hexo搭建博客的基本环境和hexo相关参数设置等. 基于目前,博客基本上是可以完美运行了. 但是,有一点是不太好,就是源码同步问题,如果在不同的电脑上写文 ...

  5. 无废话ExtJs 入门教程三[窗体:Window组件]

    无废话ExtJs 入门教程三[窗体:Window组件] extjs技术交流,欢迎加群(201926085) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3 ...

  6. CocoStudio教程三:认识并利用CocoStudio的果实 运行2.2.1版本

    原文:CocoStudio教程三:认识并利用CocoStudio的果实 原文用的老版,用2.21搞起来好像有些问题,然后自己摸索了下,有的都是乱找的方法,只求能运行... 1,原文的CCJsonRea ...

  7. Android Studio系列教程三--快捷键

    Android Studio系列教程三--快捷键 2014 年 12 月 09 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzhang.com/ ...

  8. Laravel教程 三:视图变量传递和Blade

    Laravel教程 三:视图变量传递和Blade 此文章为原创文章,未经同意,禁止转载. Blade 上一篇我们简单地说了Router,Views和Controllers的工作流程,这一次我就按照上一 ...

  9. NGUI系列教程三

    接下来我们再来看Progress Bar和Slider,对比参数我们可以发现,Progress Bar和slider的明显区别在于slider多一个Thumb选项,这里的Thumb就是我们拖动的时候点 ...

随机推荐

  1. SVN - 笔记

    SVN(版本控制) 1.什么是SVN · 多人共同开发同一个项目,内部最大的问题是,在比较短的时间内如果有多人同时开发同一个文件,会造成彼此的代码相互覆盖的情况发生. · 管理着随时间改变的数据,这些 ...

  2. 第三届蓝桥杯 c/c++真题

    第三届蓝桥杯真题 c/c++ 以下题目我自己也并不是所有的题目都是一次性就能做对或是有结题思路的.有些题目也是经过查证网上相关的资料或是参考了别人的代码和解题思路才做出来的.总的来看,这份题目考了很多 ...

  3. 09-IOSCore - 应用互动、UIImagePickerController

    一.调用系统程序/服务 1. 应用互动数据权限 1) 跟自己本地数据交互 2) 跟网络服务器/云数据交互 3) 跟系统数据服务交互 4) 跟其它应用程序交互 2. 基础 URL 统一资源定位 一个特殊 ...

  4. Wince下实现ImageButton

    我们在winform中给按钮设置个背景图片超级简单,是不?可是在wince下面就没那么简单了,下面我来介绍一种方式来实现ImageButton. 实现思路是重新写一个usercontrol就ok.具体 ...

  5. Java__jar包的简单操作

    工作需要研究了下jar,这里就举个简单的例子,以helloworld为例吧 1.启动eclipse编写代码: 次步不做赘述 package cn.test.jar; public class Hell ...

  6. telerik 控件 SCRIPT5007: 无法获取未定义或 null 引用的属性“documentElement” (IE 文档模式)

    IE对盒模型的渲染在 Standards Mode和Quirks Mode是有很大差别的,在Standards Mode下对于盒模型的解释和其他的标准浏览器是一样,但在Quirks Mode模式下则有 ...

  7. 第1章 软件测试基本概念(Week1,3月3日)

    一.对软件的认识 1. 什么是软件 2. 软件的分类 3. 软件开发的生命周期模型 (1)瀑布模型 (2)Scrum 其实对用瀑布模型这种臃肿不堪.要求严格.而无法适应软件开发周期变化的开发模型,渐渐 ...

  8. 终于懂了:Delphi消息的Result完全是生造出来的,不是Windows消息自带的(Delphi对Windows编程体系的改造越大,学习收获就越大)——消息是否继续传递就看这个Result

    Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据的含义也不一样. t ...

  9. 在jsp页面下, 让eclipse完全支持HTML/JS/CSS智能提示(转)

      我们平时用eclipse开发jsp页面时智能提示效果不太理想,今天用了两个小时发现了eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用ecl ...

  10. Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法

    Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx" ...