OGRE 渲染 到 MFC

网上睇到一个OGRE——MFC的代码

就是在mfc 单文挡架构下 cview 里面 onpait 这个消息函数加个settimer 刷新UI 然后 嗯 无了

我在这个之上 将CView继成 用个MFC 多线程UI的东东 这样 旁边再加个停靠窗口 用CJ60Lib

CVIEW插入一个 ogreappliction 不过 这个监听器呢 用OIS OIS 一定要绑定主窗口句柄的 即CMainWND 而渲染那个窗口就要绑定在具体要画在的窗口上 即CVIEW
无了 看图:OGRE 渲染 到 MFC_第1张图片
工程要加比较多开源东西
本来想做个3D编辑器的

停靠窗口 再脚本控制 写些逻辑 场景其他特交 什么器都放里面 而 一放开mfc 外壳窗口 可以比较快得到一个ogre窗口
不过近来无时间搞 算了 反正无什么技术含量 至少好多具体东东未做 架了一点点不管了

代码在这里 工程依的东西比较多 绝对有问题 编译 有心只看看图 跟CVIEW里面的就可以的了
http://www.cppblog.com/Files/jimsmorong/ogre_mfc_edit.rar

OGRE MFC

代码:

http://www.pudn.com/downloads82/sourcecode/windows/bitmap/detail318146.html

 

最近在搞这个在MFC框架上显示OGRE渲染, 开发环境是VS2005.

如何嵌入呢,其实不难. 主要是要把MFC主窗口的句柄传给OGRE的渲染系统RenderSystem,并且程序结束时要清理渲染窗口.

1)因为不在使用OGRE默认的配置窗口来初始化RenderSystem,现在这一步必须自己来做。首先设置配置文件路径,然后轮询可用的RenderSystem。这里默认使用Direct3D9 Render System。
   // 和原来一样设置插件、资源路径,设置过后就可以轮讯可用的RenderSystem了
   setupResources(); 
  
   // 指定使用Direct3D9 Render System渲染子系统。
   RenderSystemList *rl = Root::getSingleton().getAvailableRenderers();
   RenderSystemList::iterator it = rl->begin(); 
   D3D9RenderSystem *mRSys = NULL;
   while( it != rl->end() )
   { 
       if( -1 != ( *it )->getName().find( "3D9" )   )
       {
          mRSys = ( D3D9RenderSystem* )( *it );
          break;
       }
       it++;
    }

    // 配置框中的选项需要手动设置。
    mRSys->initConfigOptions(); 
    mRSys->setConfigOption( "Anti aliasing", "None" );
    mRSys->setConfigOption( "Floating-point mode", "Fastest" );
    mRSys->setConfigOption( "Full Screen", "No" );
    mRSys->setConfigOption( "Rendering Device", "NVIDIA GeForce2 MX/MX 400" );
    mRSys->setConfigOption( "VSync", "No" );
    mRSys->setConfigOption( "Video Mode", "640 x 480 @ 32-bit colour" );

    // 起用
    mRoot->setRenderSystem( mRSys );

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( 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 new DEBUG_NEW 
     #endif

并用 #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" 
ii) in the C/C++/Preprocessor tab, add _AFXDLL to the preprocessor definitions 
iii) in the Linker/Input tab, add mfc80d.lib anywhere before OgreMain_d.lib

   3.....在实际的编程中,你的view类将会需要重载cwnd类的OnTimer,OnDraw / OnPaint等函数, VS2005里面是没有像VC6.0里面的CLASS WIZZARD,这使得我们在重载的过程中,需要自己手动添加消息映射.

如重载OnTimer类, 这时你的View类里面有该函数
afx_msg void OnTimer(UINT_PTR nIDEvent);

这时你需要在view的cpp里面找到

BEGIN_MESSAGE_MAP(COgreMfcView, CView)
// 标准打印命令
ON_WM_TIMER()

ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
END_MESSAGE_MAP()

并且添加ON_WM_TIMER(), 这时你的定时器函数才会响应,被调用到.

4......ROOT根对象的删除须在你的winapp里面, 如果你在view类的ondestroy()里面删除根对象,或者在析构函数里面删除它, 这对导致你在关闭程序后,弹出错误. 其原因可能是由于删除root的时机不对!

你可能感兴趣的:(timer,command,iterator,mfc,Direct3D,preprocessor)