OGRE嵌入到MFC
OGRE 2007-12-10 09:53:59 阅读392 评论0 字号:大中小 订阅
最近在搞这个在MFC框架上显示OGRE渲染, 开发环境是VS2005. 如何嵌入呢,其实不难. 主要是要把MFC主窗口的句柄传给OGRE的渲染系统RenderSystem,并且程序结束时要清理渲染窗口. 1)不再使用OGRE默认的配置窗口来初始化RenderSystem,自己来进行初始化。首先设置配置文件路径,然后轮询可用的RenderSystem。这里使用OpenGL Render System,当然你也可以使用Direct3D9 Render System。 // 和原来一样设置插件、资源路径,对资源进行加载. //设置过后就可以轮讯可用的RenderSystem了 setupResources(); // 指定使用OpenGL Render System渲染子系统 Ogre::RenderSystemList::iterator pRend = mRoot->getAvailableRenderers()->begin(); Ogre::RenderSystem *rsys = *pRend;
// 配置框中的选项需要手动设置。 rsys->setConfigOption("Colour Depth", "32" );
// 起用 mRoot->setRenderSystem( rsys ); 2)剩下的初始化过程和ExampleApplication基本一致,只不过现在不需要由OGRE自动创建窗体,应该将MFC视图的句柄传过去初始化。 // 初始化,传入false表示不需要OGRE自动创建窗口 mRoot->initialise( false );
// 手动创建渲染窗口,在这里我们将MFC视图的句柄传入 NamevaluePairList miscParams; miscParams["externalWindowHandle"] = StringConverter::toString( ( size_t )mWnd ); mWindow = mRoot->createRenderWindow( "View", 640, 480, false, &miscParams ); 到次初始化过程已经完毕,这时候运行程序就得到一个漆黑的MFC窗口。 3)因为现在使用是视图的WndProc,我们必须自己处理更新和触发FrameStart事件. // 触发FrameStart, FrameEnd事件 void update( void ) { mRoot->_fireFrameStarted(); mWindow->update(); mRoot->_fireFrameEnded(); } //在视图的OnDraw时间里,调用update void CMFCRenderView::OnDraw(CDC* /*pDC*/) { CMFCRenderDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: 在此处为本机数据添加绘制代码 update(); }
这样还不够,WM_PAINT事件并不由我们控制,当窗体静静的趟在那的时候是不会触发的,因此我们通过设置一个timer来模拟没帧的更新, // 20ms触发一次, SetTimer()可以放在OnCreate()或者OnDraw()里面, 只需初始化一次就可以了 SetTimer( 100, 20, 0 );
void CMFCRenderView::OnTimer(UINT nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 update(); __super::OnTimer(nIDEvent); } *******须注意的地方: 1......初始化可以在OnDraw(CDC* pDC)的第一次执行时候进行,而不能在PreCreateWindow(CREATESTRUCT& cs) 或者COgreMFCView( )或者OnCreate()这个CView的子类初始化的时候进行因为这个时候,View对应的HWND实际上还没初始化出来呢... 2......Ogre嵌入到MFC里面, 将会导致NEW等操作符的重载冲突, 你必须选择让Ogre或者MFC进行内存管理. (1) 使用Ogre自己的MemoryManager,并且禁止调用MFC的DEBUG_NEW,这需要先 找到cpp中的以下行 #ifdef _DEBUG 并用 #define OGRE_DEBUG_MEMORY_MANAGER 1代替 这样Ogre中会使用自己的new/delete,而不是调用vccrt中的_heap_alloc_debug . (2) 使用MFC. 可以参考http://www.blogjava.net/wangle/ 具体设置如下: i) in the General tab, switch "Use MFC in a shared DLL" to "Use Standard Windows Libraries" 3.....在实际的编程中,你的view类将会需要重载cwnd类的OnTimer,OnDraw / OnPaint等函数, VS2005里面是没有像VC6.0里面的CLASS WIZZARD,这使得我们在重载的过程中,需要自己手动添加消息映射. 如重载OnTimer类, 这时你的View类里面有该函数 这时你需要在view的cpp里面找到 BEGIN_MESSAGE_MAP(COgreMfcView, CView) ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint) 并且添加ON_WM_TIMER(), 这时你的定时器函数才会响应,被调用到. 4......ROOT根对象的删除须在你的winapp里面, 如果你在view类的ondestroy()里面删除根对象,或者在析构函数里面删除它, 这对导致你在关闭程序后,弹出错误. 其原因可能是由于删除root的时机不对!
就说这么多了, 想到再补充! (上面内容是通过本人总结以及网上牛人的文章而写的) |