Ogre应用之一:MFC+Ogre+OSI搭建
来源:互联网 发布:淘宝手机详情加链接 编辑:程序博客网 时间:2024/06/10 17:45
Ogre应用之一MFC+Ogre+OSI搭建
by:唐崇(theone7)
虫子||CSDN技术博客(http://blog.csdn.net/theone7)
引言:这系列的文章来自于学校毕业设计的选题—“3D售楼处”,在小组中我负责3D图形的渲染,采用的是Ogre引擎来做。由于在准备研究生,断断续续地用将近一个的月的时间完成了一个Demo。
一、将Ogre嵌入MFC框架
用过Ogre的同学都知道:在SDK中,官方提供了一个很好的例子来介绍如何使用Ogre。而网上很多教程是直接继承例子中的类来实现想要的工作的,感觉这会多出很多不需要的东西。所以在我的Demo中是直接新建一个类,只加上自己想要的东西。(下面只列出了本文有关的代码)
class COGRE_Manager{//单例模式构建{{private:explicit COGRE_Manager();public:~COGRE_Manager();inline static COGRE_Manager& GetSingleton(){static COGRE_Manager m_ogreManager;return m_ogreManager;}//单例模式构建结束}}//<功能接口>:public://初始化bool StartUp(HWND m_hWnd, int width, int height ,HWND hMainWnd);//<数据接口>:public://< 获得私有成员变量>: //ogre根对象 Ogre::Root* GetRoot(void) const {return mRoot;}//摄像机对象 Ogre::Camera* GetCamera(void) const {return mCamera;} //场景管理器对象 Ogre::SceneManager* GetSceneManager(void) const {return mSceneMgr;}//渲染窗口对象 Ogre::RenderWindow* GetRenderWindow(void) const {return mWindow;}//<私有方法>:private: //创建ogre根对象 void CreateRoot(); //设置渲染系统 void SetupRenderSystem(); //创建渲染窗口 void CreateRenderWindow(HWND m_hWnd, int width, int height);//渲染场景管理器 void ChooseSceneManager();//创建摄像机 void CreateCamera();//创建视口 void CreateViewport();//创建场景 void CreateScene();//创建帧监听对象 void CreateFrameListener(HWND hMainWnd);//<实现细目>:private:Ogre::Root* mRoot;Ogre::RenderWindow* mWindow;Ogre::SceneManager* mSceneMgr;Ogre::Camera* mCamera;COGRE_FrameListener* mFrameListener;Ogre::String mPluginsCfg;};
当运行Ogre的例子时,会发现它不是基于Windows的。默认的创建渲染窗口根本就不需要Windows窗口,直接一个Create就好。无奈我的项目需要使用MFC框架,其实也不难,做好一下三件事就行。
1.渲染配置
Ogre官方提供的例子中,会先弹出Oger配置框,再根据用户的选择进行渲染。既然用的是MFC框架,直接渲染到Windows窗口中,自然要把程序开始时蹦出的配置框去掉。自己把渲染系统参数设置好即可:
void COGRE_Manager::SetupRenderSystem(){// 设置渲染子系统Ogre::RenderSystem *rs = mRoot->getRenderSystemByName("Direct3D9 Rendering Subsystem");mRoot->setRenderSystem(rs);// 设置配置选项rs->setConfigOption("Full Screen", "No");rs->setConfigOption("Video Mode", "1024 x 768 @ 32-bit colour");}
2.渲染窗口
如果要使用Windows窗口作为Ogre的渲染窗口,则得取消Ogre默认自己创建窗口。Ogre支持采用外部窗口,这里需要将MFC中的View类作为渲染窗口。在创建渲染窗口时,需传入View的句柄作为参数:
void COGRE_Manager::CreateRenderWindow( HWND m_hWnd, int width, int height ){// root初始化的时候,设置false值来告知Root不用给我们自动创建渲染窗口// 这样我们可以MFC的窗口来进行渲染mRoot->initialise(false);Ogre::NameValuePairList miscParams; // 参数列表, 作为createRenderWindow函数的最后一个参数miscParams["externalWindowHandle"] = Ogre::StringConverter::toString((long)m_hWnd);mWindow = mRoot->createRenderWindow("OgreRenderWindow", width, height, false, &miscParams);}
3.渲染循环
OGRE官方例子中使用的是startRendering()来让程序进入渲染循环的。此方法将消息交给了系统。这会与MFC的消息循环起冲突,比如说WM_PAINT和OGRE一起渲染。解决办法就是做到一个循环中来,正好OGRE有提供只渲染一帧的方法renderOneFrame();
将渲染一帧的函数放入到View类的OnDraw函数里面,用定时器来循环调用使其达到渲染循环的效果。
void COgreDemoView::OnDraw(CDC* /*pDC*/){ COgreDemoDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; if(m_isFirstDraw) { //第一次画图时,初始化数据 m_isFirstDraw = FALSE; GetClientRect(&m_ViewRect); COGRE_Manager::GetSingleton().StartUp(m_hWnd,m_ViewRect.Width(),m_ViewRect.Height(),AfxGetApp()->GetMainWnd()->GetSafeHwnd()); SetTimer(1, 10, NULL); } if(m_isStart) { COGRE_Manager::GetSingleton().GetRoot()->renderOneFrame(); }}
在这里使用SetTimer设定一个定时器。再提供它的响应函数:
void COgreDemoView::OnTimer(UINT_PTR nIDEvent){ if(m_isStart) { COGRE_Manager::GetSingleton().GetRoot()->renderOneFrame(); } CView::OnTimer(nIDEvent);}
通过SetTimer设定的参数。该响应函数每10ms触发一次。这样,就可以达到10ms fps即100fps的渲染效果了。
通过这三个方面,渲染的工作就已经实现了与MFC的结合。接下来,就是IOS的设定了。之前版本的OGRE是采用外部的CEGUI来负责IO处理的,不过最新版本已经不再用CEGUI了,而是用自身提供的IOS。这样一来也方便了我们的开发。另外提一句,本来是想直接使用MFC的消息处理机制来处理鼠标键盘IO的,但在做鼠标拾取时无奈的发现MFC获得的鼠标位置精确度太低了。所以还是老老实实的使用OIS。
二、设定OIS
OIS在创建输入系统的时候,它要控制的窗口必须是顶层窗口,就是说你传view视图的窗口句柄给他不行,必须要MFC程序的主框架窗口。所以这样一来,我们要提供2个的窗口句柄给OGRE了。一个是View的句柄,作渲染用;一个是主框架窗口,作为键盘鼠标的IO处理。另外,要使用OIS,需创建一个监听类,就像Ogre案例中的一样它需继承 Ogre::FrameListener,OIS::MouseListener,OIS::KeyListener 这几个类。
嗯,下面是设定代码:
COGRE_FrameListener::COGRE_FrameListener(COGRE_Manager*manager,HWND hMainWnd):mIsRBDowm(false),mPreState(),misLBDown(false),mCurrentObject(),mCount(0),mTrayMgr(0){ mSceneMgr =manager->GetSceneManager(); mCamera =manager->GetCamera(); mWindow =manager->GetRenderWindow(); mRaySceneQuery =mSceneMgr->createRayQuery(Ogre::Ray()); size_t windowHnd = 0; std::ostringstreamwindowHndStr; OIS::ParamList pl; mWindow->getCustomAttribute("WINDOW", &windowHnd); windowHnd = (size_t)hMainWnd; // 这里这个窗口句柄就是我们传入的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"))); ShowCursor(0); //隐藏系统鼠标指针 // 键盘非游戏独占 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); // 这样InputManager就建好了,但为了从键盘、鼠标、或是手柄中获得输入,还必须创建这些对象: mKeyboard=static_cast<OIS::Keyboard*>(mInputManager->createInputObject(OIS::OISKeyboard,true)); mMouse=static_cast<OIS::Mouse*>(mInputManager->createInputObject(OIS::OISMouse,true)); mKeyboard->setEventCallback(this); //键盘回调 mMouse->setEventCallback(this); //鼠标回调//设置鼠标移动的范围{{ CRect temp; ((CMainFrame *)AfxGetMainWnd())->GetActiveView()->GetWindowRect(temp); mMouse->getMouseState().width = temp.Width(); mMouse->getMouseState().height = temp.Height();//设置完毕}} mTrayMgr = new OgreBites::SdkTrayManager("InterfaceName", mWindow, mMouse); mTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);}
接下来要做的事就是在监听IO的函数做响应的处理了。按照自己的需求填写一下函数
bool frameStarted(const Ogre::FrameEvent &evt);
bool mouseMoved(const OIS::MouseEvent &e);
bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonIDid);
bool mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonIDid);
bool keyPressed(const OIS::KeyEvent &e);
bool keyReleased(const OIS::KeyEvent &e);
这样,OGRE+MFC+OSI就搭建好了。
下面是效果图:
- Ogre应用之一:MFC+Ogre+OSI搭建
- MFC(VS2010) + OGRE 环境搭建
- 菜鸟学习OGRE和天龙八部之一:OGRE+MFC+OIS
- 菜鸟学习OGRE和天龙八部之一:OGRE+MFC+OIS
- ogre+mfc
- ogre+MFC
- Ogre
- ogre
- OGRE
- OGRE
- ogre
- OGRE
- ogre
- OGRE嵌入到MFC
- ogre与mfc结合
- Ogre + MFC + OIS
- OGRE 渲染 到 MFC
- OGRE + MFC 多线程框架
- java nio Selector的使用-客户端
- CBitmapButton 使用方法
- linux hello word 始末!
- 1004 Let the Balloon Rise
- 自己一直在使用的客户端验证脚本
- Ogre应用之一:MFC+Ogre+OSI搭建
- HTTP协议
- WebGL自学教程——WebGL示例:13. 混合
- java抽象类(笔记)
- Java中Runtime对象
- Java编译过程、c/c++编译过程区别
- Oracle创建悲观锁和乐观锁
- 文泉驿字体
- kbm---关于多层架构