MFC(VS2010) + OGRE 环境搭建

来源:互联网 发布:java外部接口 编辑:程序博客网 时间:2024/05/21 11:27

    文章参考了《Ogre嵌入MFC傻瓜完全教程》(http://blog.csdn.net/guoyk1990/article/details/25915065)和Ogre官方网站上的示例(http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Setting+Up+An+Application+-+Visual+Studio&structure=Development)。实际操作过程中出现了一些问题,故将全部工作完整地记录下来,以备不时之需,也给广大朋友一个参考。记住:即便是“傻瓜完全教程”,也不可能完全照搬。

一、准备工作

        本人的配置Windows7 64位系统、VS2010(32位)、OgreSDK_vc10_v1-8-1      

       下载OGRESDK:http://www.ogre3d.org/download/sdk  ,并运行 安装到 D盘根目录。

二、环境变量配置

        官方示例中采用cmd命令进行配置,本人不善于这种方式,操作起来没有安全感。故采用更直观的方式:

        在用户变量和系统变量中均新建一项 OGRE_HOME 值为:D:\OgreSDK_vc10_v1-8-1

        在path中添加一项:%OGRE_HOME%

       

        本人最初仅仅是在系统变量中新建了该项,但在运动程序时,发现配置并没有成功,干脆两种变量都加,问题解决了。

        配置好环境变量之后要重启电脑。

三、建立MFC单文档应用程序

       1. 工程名称:OgreTest2,配置如下:

2. 项目属性配置

进入属性页,选择“所有配置”,

配置属性—>常规

输出目录:bin\$(Configuration)\

中间目录:obj\$(Configuration)\

mfc的使用:使用标准 Windows 库

字符集:使用多字节字符集

       

配置属性—>调试

命令:  $(OGRE_HOME)\Bin\$(Configuration)\$(ProjectName).exe

工作目录: $(OGRE_HOME)\Bin\$(Configuration)


配置属性—>C/C++—>常规

附加包含目录

$(OGRE_HOME)\include
$(OGRE_HOME)\include\OIS
$(OGRE_HOME)\include\OGRE
$(OGRE_HOME)\Samples\Common\include
$(OGRE_HOME)\boost


配置属性—>C/C++—>预处理器

预处理器定义

添加一项:_AFXDLL


配置属性—>链接器—>常规

附加目录库:

$(OGRE_HOME)\lib\$(Configuration)
$(OGRE_HOME)\boost\lib


配置 切换为“Debug”:


配置属性—>链接器—>输入

附加依赖项:

OgreMain_d.lib
OIS_d.lib


配置 再切换为“Release”:

配置属性—>链接器—>输入

附加依赖项:

OgreMain.lib
OIS.lib


至此,完成配置工作,在分别在DEBUG和RELEASE模式下,点击生成命令,成功!


四、渲染场景至MFC窗口


1. 项目->添加类->C++类


      添加的类名为“CMyOgreApp”,源代码如下:

头文件

#pragma once#include "ogre.h"#include "OgreConfigFile.h"#include "OgreFrameListener.h"#include "OgreStringConverter.h"#include "OIS.h"#include <SdkTrays.h>#include <SdkCameraMan.h>#include "MyFrameListener.h"using namespace Ogre;class CMyOgreApp{public:CMyOgreApp(void);~CMyOgreApp(void);Ogre::Root* getRoot(void) const {return mRoot;}Ogre::Camera* getCamera(void) const {return mCamera;}Ogre::SceneNode* getCamNode(void) const {return mCamNode;}Ogre::SceneManager* getSceneManager(void) const {return mSceneMgr;}Ogre::RenderWindow* getRenderWindow(void) const {return mWindow;}bool go(CRect rt, HWND hWnd);void createRoot(void);void setupResources(void);void setupRenderSystem(void);void createRenderWindow(HWND m_hWnd, int width, int height);int initializeResourceGroups(void);void chooseSceneManager(void);void createCamera(void);void createViewport(void);void createScene(void);void createFrameListener(void);class CMyFrameListener* mListener;private:Ogre::Root* mRoot;Ogre::RenderWindow* mWindow;            Ogre::SceneManager* mSceneMgr;Ogre::Camera* mCamera;Ogre::SceneNode* mCamNode;OgreBites::SdkCameraMan* mCameraMan;     // basic camera controllerOgre::Light* light;};


源文件

#include "StdAfx.h"#include "MyOgreApp.h"CMyOgreApp::CMyOgreApp(void){}CMyOgreApp::~CMyOgreApp(void){}bool CMyOgreApp::go(CRect rt, HWND hWnd){createRoot();setupResources();setupRenderSystem();createRenderWindow(hWnd, rt.Width(), rt.Height());chooseSceneManager();createCamera();createViewport();initializeResourceGroups();createScene();createFrameListener();//创建侦听return true;}void CMyOgreApp::createRoot(void){//mRoot = new Ogre::Root("plugins_d.cfg");//debug模式用//已将plugins_d.cfg文件名改成了plugins.cfg,这样一来,无论是DEBUG还是RELEASE模式,都不用修改代码mRoot = new Ogre::Root("plugins.cfg");//release模式用}void CMyOgreApp::setupResources(void){// Load resource paths from config fileOgre::ConfigFile cf;//cf.load("resources_d.cfg");//debug模式用//已将plugins_d.cfg文件名改成了plugins.cfg,这样一来,无论是DEBUG还是RELEASE模式,都不用修改代码cf.load("resources.cfg");//release模式用// Go through all sections & settings in the fileOgre::ConfigFile::SectionIterator seci = cf.getSectionIterator();Ogre::String secName, typeName, archName;while (seci.hasMoreElements()){secName = seci.peekNextKey();Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();Ogre::ConfigFile::SettingsMultiMap::iterator i;for (i = settings->begin(); i != settings->end(); ++i){typeName = i->first;archName = i->second;Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);}}}void CMyOgreApp::setupRenderSystem(void){//mRoot->showConfigDialog();//mRoot->restoreConfig();//if (!mRoot->restoreConfig() && !mRoot->showConfigDialog())//throw Ogre::Exception(1, "未选择渲染系统","setupRenderSystem()");RenderSystemList* rl = &const_cast<RenderSystemList&>(mRoot->getAvailableRenderers());RenderSystem* rSys = NULL;RenderSystemList::iterator it = rl->begin();while (it!=rl->end()){if (-1 != (*it)->getName().find("OpenGL Rendering Subsystem"))//if (-1 != (*it)->getName().find("Direct3D9 Rendering Subsystem")){rSys = (RenderSystem*)(*it);break;}++it;}rSys->setConfigOption("Full Screen","Yes");rSys->setConfigOption("VSync","No");mRoot->setRenderSystem(rSys);}void CMyOgreApp::createRenderWindow(HWND m_hWnd, int width, int height){mRoot->initialise(false);//禁止ogre创建新的渲染窗口,而使用MFC的窗口NameValuePairList misc;misc["externalWindowHandle"] = StringConverter::toString((int)m_hWnd); mWindow = mRoot->createRenderWindow("OgreRenderWindow", width, height, false, &misc);}int CMyOgreApp::initializeResourceGroups(void){TextureManager::getSingleton().setDefaultNumMipmaps(5);ResourceGroupManager::getSingleton().initialiseAllResourceGroups();return 0;}void CMyOgreApp::chooseSceneManager(void){mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE);}void CMyOgreApp::createCamera(void){// Create the cameramCamera = mSceneMgr->createCamera("PlayerCam");// Position it at 500 in Z directionmCamera->setPosition(Ogre::Vector3(0,0,80));// Look back along -ZmCamera->lookAt(Ogre::Vector3(0,0,-300));mCamera->setNearClipDistance(5);mCameraMan = new OgreBites::SdkCameraMan(mCamera);   // create a default camera controller}void CMyOgreApp::createViewport(void){// Create one viewport, entire windowViewport* vp = mWindow->addViewport(mCamera);vp->setBackgroundColour(ColourValue(0,0,0));// Alter the camera aspect ratio to match the viewportmCamera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));}void CMyOgreApp::createScene(void){//添加背景mSceneMgr->setSkyDome(true, "Examples/CloudySky",6, 8);Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();headNode->attachObject(ogreHead);// Set ambient lightmSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));// Create a lightOgre::Light* l = mSceneMgr->createLight("MainLight");l->setPosition(20,80,50);}//创建帧监听void CMyOgreApp::createFrameListener(void){mListener= new CMyFrameListener(mWindow, mCamera, mSceneMgr, light);mRoot->addFrameListener(mListener);}


2. 在View类的头文件中包含CMyOgreApp 的头文件

#include "MyOgreApp.h"


并声明两个变量

public:// ogre主类CMyOgreApp m_ogreApp;// 初次渲染bool m_firstDraw;


3. 在View类的构造函数中将m_firstDraw 初始化为  true。

4. 在View类的OnDraw函数中添加下如下代码

void COgreTest2View::OnDraw(CDC* /*pDC*/){COgreTest2Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码//Ogre渲染try {if(m_firstDraw){m_firstDraw = false;CRect   rect;GetClientRect(&rect);m_ogreApp.go(rect,m_hWnd);//传入MFC主窗口句柄SetTimer(1,20,0);}m_ogreApp.getRoot()->renderOneFrame();} catch( Ogre::Exception& e ) {#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32MessageBox(  e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);#elsestd::cerr << "An exception has occured: " <<e.getFullDescription().c_str() << std::endl;#endif}}


5. 添加WM_TIMER和WM_ERASEBKGND消息处理函数,代码分别如下 :

void COgreTest2View::OnTimer(UINT_PTR nIDEvent){// TODO: 在此添加消息处理程序代码和/或调用默认值if (1 == nIDEvent){m_ogreApp.getRoot()->renderOneFrame();}CView::OnTimer(nIDEvent);}

BOOL COgreTest2View::OnEraseBkgnd(CDC* pDC){// TODO: 在此添加消息处理程序代码和/或调用默认值return TRUE;}


五、添加事件处理方法,实现人机交互


1. 添加一个帧监听类: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 controllerbool 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;}



2. 为了实现监听与响应,需要修改CMyOgreApp类,而这些工作在上面贴出的代码中已经完成了,这里再简单说明一下:

在CMyOgreApp类的头文件中包含监听类

#include "MyFrameListener.h"

声明一个CMyFrameListener类的变量

class CMyFrameListener* mListener; 

声明一个函数,函数的实现已在上面的代码中贴出来了

void createFrameListener(void); 

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


3. 需要特别指出的是setupRenderSystem()函数的修改,本项目默认以OpenGL进行渲染,所以省略了渲染选择对话框

代码如下:

void CMyOgreApp::setupRenderSystem(void){RenderSystemList* rl = &const_cast<RenderSystemList&>(mRoot->getAvailableRenderers());RenderSystem* rSys = NULL;RenderSystemList::iterator it = rl->begin();while (it!=rl->end()){if (-1 != (*it)->getName().find("OpenGL Rendering Subsystem"))//if (-1 != (*it)->getName().find("Direct3D9 Rendering Subsystem")){rSys = (RenderSystem*)(*it);break;}++it;}rSys->setConfigOption("Full Screen","Yes");rSys->setConfigOption("VSync","No");mRoot->setRenderSystem(rSys);}

如果想要弹出渲染选择对话框,则代码可以修改为如下:

void CMyOgreApp::setupRenderSystem(void){mRoot->showConfigDialog();}

4. 为了保证在DEBUG和RELEASE模式下,程序都可以正确运行,本人将D:\OgreSDK_vc10_v1-8-1\bin\debug文件夹中的两个文件的名称改了:

plugins_d.cfg 改成了 plugins.cfg

resources_d.cfg 改成了 resources.cfg


至此,全部工作就完成了,生成并运行。














       







0 0
原创粉丝点击