登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> 程序员学前班[不再更新,只读] >> 主题: mfc 中使用 ogre     [回主站]     [分站链接]
标题
mfc 中使用 ogre
clq
浏览(1) + 2010-05-21 20:05:33 发表 编辑

关键字:

mfc 中使用 ogre

http://www.cppblog.com/qudeqing0204lyf/archive/2009/03/02/75338.html

Ogre 多窗口显示在MFC下实现

项目中需要小地图效果自然想到了Ogre教程中的画中画显示,但是小地图 把主窗口遮盖的比较严重。索性就再开个窗口单独作为小地图的显示吧
主要的思路就是在高度200处架设一个位置不变的Camera,用这个 Camera显示出的效果作为小地图的输出
有图有真相,看图再继续


在说明实现方法之前,需要理清楚Ogre中的一些关 系:Root,RenderWindow,SceneManager,Camera,ViewPort
第一,Root在程序中是唯一的,是万物之 源
第二,RenderWindow和Root是一对多的关系,而RenderWindow和MFC中的View(或者是Win32中的窗口)是一 对一的关系,这也是Ogre能多窗口显示的基础
第三,SceneManager和Root是一对多关系,但本例中关系不大,我只用了一个SM
第 四,RenderWindow和ViewPort是一对多关系,但一个RenderWindow必须有一个主ViewPort。
第 五,Viewport和Camera是一对一关系,
第六,SceneManager和Camera是一对多关系,但通常一个程序中只显示一个 Camera的内容,除非你在一个RenderWindow中设置了多个ViewPort,每个ViewPort对应不同的Camera(教程中的画中画 就是这么来的)
画个图把关系理清楚些吧
 
这个例子中我的设计思路是这样的:
创建两个RenderWindow,分别对应主 窗口和小地图窗口,他们对应不同的ViewPort,而不同的ViewPort对应不同的Camera(主窗口就是原来的Camera,小地图窗口用的是 新创建高度200的Camera)。
步骤大致如下:
1。用之前生成Curve窗口一样的方法创建一个可用的View类窗口
2。用 与生成主窗口相同的方法来显示Ogre中的内容(SetupOgre。。。若干等等)
关键的是产生RenderWindow(用 MinimapView窗口的句柄),SM采用getSceneManager获得主窗口的SM,再对Camera,ViewPort一一设置就行,总之 就是对MFCView类照葫芦画瓢。

大功告成!

最后温习下Invalidate的知识:
Invalidate(TRUE);// 擦除背景
Invalidate(FALSE);//不擦除背景
程序View类里的OnEraseBkgnd直接返回TRUE,并且定时器 中用Invalidate(TRUE);就能避免窗口闪烁啦

posted on 2009-03-02 18:19 Alex@VCC 阅读(1992) 评 论(5)  编 辑 收 藏 引 用 所属分类: Ogre



clq
2010-5-21 20:06:32 发表 编辑

OGRE渲染输出到MFC


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);
  }

clq
2010-5-21 20:08:10 发表 编辑

最近在搞这个在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();
 while (pRend != mRoot->getAvailableRenderers()->end())
 {
  
        //////if((*pRend)->getName().find("Direct3D9")) break;
  
  Ogre::String rName = (*pRend)->getName();
  if (rName == "OpenGL Rendering Subsystem")
   break;
  pRend++;
 }

Ogre::RenderSystem *rsys = *pRend;

   // 配置框中的选项需要手动设置。

rsys->setConfigOption("Colour Depth", "32" );
       rsys->setConfigOption( "Full Screen", "No" );
       rsys->setConfigOption( "VSync", "No" );
       rsys->setConfigOption( "Video Mode", "800 x 600" );
       rsys->setConfigOption( "Display Frequency", "60" );

   // 起用

   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 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等函数, 如果你找不到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的时机不对!

 

就说这么多了, 想到再补充! (上面内容是通过本人总结以及网上牛人的文章而写的)



总数:2 页次:1/1 首页 尾页  
总数:2 页次:1/1 首页 尾页  


所在合集/目录



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1