您的位置:首页 > 其它

Ogre嵌入MFC傻瓜完全教程(二)

2014-05-16 17:42 288 查看
在上一篇博文中我们已经配置好OGRE的项目的属性了,本篇将讲解如何将场景渲染到MFC的窗口中。

一、Ogre Demo 的结构

为了能够顺利的将Ogre场景渲染至MFC窗口中,我们需要了解OGRE的大致执行过程(如果对这块很熟悉可以直接跳过)。首先打开我们刚开始创建的Demo: OgreApp。在类视图中我们可以看到里面里面只有两个类:BaseApplication 和OgreApp2。
我们先研究一下OgreApp2这个类。打开头文件我们发现这个类的父类是BaseApplication,里面除了构造和析构函数外只有一个虚函数 createScene(),打开它的定义我们看到里面只有五六行代码,每一句代码具体的含义我就不再讲了,这个函数的功能就是创建一个场景里面加载了一个 ogrehead.mesh文件,也就是Ogre的logo,还创建了一个光源。再往下看我们发现了我们特别熟悉的main函数。main函数中仅仅做了两件事,一是声明一个自身对象
app,而是调用go()函数。至于那个try...catch 就没什么好说的了。现在我们就明白了Ogre渲染的起始点就是这个go()函数,下面我们就看看这个go()函数到底做了什么。
打开BaseApplication 的头文件,我们看到BaseApplication 继承了一大堆的类,我们暂时先不管它们。在研究go()之前我们先看一下这个类中几个比较重要的变量。Ogre::Root *mRoot; Ogre::Camera* mCamera; Ogre::SceneManager* mSceneMgr; Ogre::RenderWindow* mWindow;从名字上我们就知道这几个变量的含义分别是根、主摄像头、场景管理器、渲染窗口,它们的功能我们也能猜出一二。这四个变量对一个Ogre应用程序来说是必不可少的。下面找到go()转到定义我们发现它也只是做了三件事而已(前面的那个#ifdef
_DEBUG的意思你懂的)一是调用setup();二是调用startRendering();三是 destroyScene();

我们再找到setup()的定义看到里面做的事情就比较多了。
1、new了一个 root 对象 mRoot ,这个mRoot非常重要,它贯穿整个Ogre应用的始终。
2、调用 setupResources() 通过它的源码我们知道它主要完成的是配置资源的功能。
3、调用 cofigure() 显示配置窗口,手动配置渲染系统的属性。
4、调用 chooseSceneManager() 选择场景管理器
5、调用 createCamera() 创建摄像机
6、调用 createViewports() 创建视口

7、调用 setDefaultNumMipmaps() Set default mipmap level

8、调用 createResourceListener() 资源侦听
9、调用 loadResources() 加载资源
10、调用 createScene() 创建场景
11、调用 createFrameListener() 创建帧监听
这个setup()函数中的这些工作基本上就是Ogre的全部工作了,由于我们现在的任务是如何渲染场景至MFC窗口,所以我就不再对各个函数进行详细解释了,等后面用到再详细介绍。

二、渲染场景至MFC窗口

终于到正题了,经过前面的讲解我想大部分人都知道下面该怎么做了吧。但我的题目是傻瓜教程,目的就是使用最简单的语言,尽可能的让更多人明白如何做,我希望我们能把更多精力放在如何做好一个App,而不是放在这些繁琐的耗费时间的准备工作上。
在上一篇博文中我们已经创建并配置好了一个MFC单文档项目。现在就在此基础上开始往下做。
1、首先我们需要新建一个和Demo里的BaseApplication类似的类详细步骤就不写了直接贴上代码:
头文件
#pragma once
#include "ogre.h"
#include "OgreConfigFile.h"
#include "OgreFrameListener.h"
#include "OgreStringConverter.h"
#include "OIS.h"

#include <SdkTrays.h>
#include <SdkCameraMan.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);

private:
Ogre::Root* mRoot;
Ogre::RenderWindow* mWindow;
Ogre::SceneManager* mSceneMgr;
Ogre::Camera* mCamera;
Ogre::SceneNode* mCamNode;
OgreBites::SdkCameraMan* mCameraMan;     // basic camera controller
//	class CAOgreFrameListener* mListener;
Ogre::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");
}

void CMyOgreApp::setupResources(void)
{
// Load resource paths from config file
Ogre::ConfigFile cf;
cf.load("resources_d.cfg");

// Go through all sections & settings in the file
Ogre::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();
//if (!mRoot->restoreConfig() && !mRoot->showConfigDialog())
//	throw Ogre::Exception(1, "未选择渲染系统","setupRenderSystem()");
}

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 camera
mCamera = mSceneMgr->createCamera("PlayerCam");

// Position it at 500 in Z direction
mCamera->setPosition(Ogre::Vector3(0,0,80));
// Look back along -Z
mCamera->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 window
Viewport* vp = mWindow->addViewport(mCamera);
vp->setBackgroundColour(ColourValue(0,0,0));
// Alter the camera aspect ratio to match the viewport
mCamera->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 light
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));

// Create a light
Ogre::Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
}

//创建帧监听
void CMyOgreApp::createFrameListener(void)
{
//	mListener= new CAOgreFrameListener(mWindow, mCamera, mSceneMgr, light,/*headNode,*/ m_a_senode);
//	mRoot->addFrameListener(mListener);
}
2、这个类创建好之后在View类的头文件中包含CMyOgreApp的头文件
#include "MyOgreApp.h"

声明两个变量
public:
CMyOgreApp m_ogreApp;//ogre 主类
bool m_firstDraw;//初次渲染

3、在View类的构造函数中将m_firstDraw 初始化为ture;

在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_WIN32
MessageBox(  e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
}
4、在类向导中为View类添加WM_TIMER 消息处理函数

void COgreTest2View::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (1 == nIDEvent)
{
m_ogreApp.getRoot()->renderOneFrame();
}
CView::OnTimer(nIDEvent);
}
5、在类向导中为View类添加WM_ERASEBKGND消息处理函数
BOOL COgreTest2View::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
return TRUE;
//return CView::OnEraseBkgnd(pDC);
}

6、将D:\OgreSDK_vc10_v1-8-1中的bin和media文件夹复制到项目的根目录下,也就是和源文件同一级的目录下



此时生成,运行会得到下面的运行结果



选择渲染系统,配置参数后点OK,Ogre的脑袋就华丽丽的出现了~



至此整个OGRE渲染至MFC窗口的工作就完成了,但仅仅这样是不够的,下一篇博文我将介绍基于此框架的事件处理的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: