按照经典的Qt程序结构,应该有一个从QMainWindow继承而来的MainWindow,让它做为主窗口,然后子类化一个QWidget,它做为主窗口的"中心挂件",能过封装Ogre的部分功能,实现用Ogre对该窗体的绘制。首先,如何把Ogre这个引擎发动,不断驱动其进行工作。Qt也需要告诉Ogre如何把渲染的内容画到指定的窗口中去,以及用哪种方式更新窗口中的内容。

         当键盘或鼠标消息来的时候,如何通知Ogre进行响应。从Ogre这边来看,就是如何把Ogre的功能,分布到Qt的各个部分。而且与一般的ogre程序不同,不是进入到连续的循环中(一般的ogre程序中,通过执行mRoot->startRendering();语句进入一个不停渲染循环,通过预先安插好的帧侦听器来对消息进行响应,对程序逻辑进行处理)而可以是“必要时”对窗口进行更新。而且与一般ogre程序不同,由于Qt自身可以检测输入设备消息,因此,OIS不再需要。
         把Ogre中的内容嵌入到Qt,从形式来看可以许多种,也就是说可以把相关Ogre的部分拆成不同部分,按照作者的需要封装在Qt中的不同部分。比如,Ogre中描述抽象的“引擎”概念的部分(Root等),因为我们想一但应用程序启动,就应该让Ogre引擎启动了,那么这些部分可以用QApplication封装,而且RenderWindow,与Qt中的QWidget概念上是关联的,所以就用QWidget来封装。出于简单的原因,我把Ogre都封装从QWidget继承而来的OgreView中了。很显然,主要考虑OgreView就可以了。
class  OgreView  :  public  QWidget
{    Q_OBJECT    public:    OgreView(QWidget*  parent  );    ~OgreView();    //QSize  minimumSizeHint()  const;    //QSize  sizeHint()  const;
protected:    void  setupView()//创建Ogre使用的内容,场景内容;    void  update();//通过它,手动更新场景内容    void  setupResources();//    void  createScene();    void  createLight();    void  resizeEvent(QResizeEvent*  evt);//窗口可能缩放    void  timerEvent(QTimerEvent*  evt);//可以设一时钟来更新窗口    void  paintEvent(QPaintEvent*  evt);//呵,当然得处理了    //消息响应    void  keyPressEvent(QKeyEvent*  evt);    void  keyReleaseEvent(QKeyEvent*  evt);    void  mousePressEvent(QMouseEvent*  evt);    void  mouseReleaseEvent(QMouseEvent*  evt);    void  mouseMoveEvent(QMouseEvent*  evt);    void  wheelEvent(QWheelEvent*  evt);    //有关Ogre    Ogre::RenderWindow*  mRenderWindow;    Ogre::SceneManager*  mSceneMgr;    Ogre::Camera*  mCamera;    Ogre::Viewport*  mVp;    Ogre::Root*  mRoot;    Ogre::Light*  mainLight;    Ogre::Entity*  mainEnt;    Ogre::SceneNode*  mainNode;    //一些控制变量,没有完全列出    Ogre::Vector3  mDirection;    Ogre::Real  mRotate;    };
//cpp文件中的内容(部分)
OgreView::OgreView(QWidget*  parent) : QWidget(parent,Qt::WFlags(Qt::MSWindowsOwnDC))
{    mRenderWindow  =  NULL;    mSceneMgr  =  NULL;    mVp  =  NULL;    mainEnt  =  NULL;    mainNode  =  NULL;    //....还有一些控制变量的初始化    setupResources();
}
OgreView::~OgreView()
{    //  destroy  Viewport  and  RenderWindow    if(  mVp  )    {    mRenderWindow->removeViewport(mVp->getZOrder());    mVp  =  0;    }    Ogre::Root::getSingleton().detachRenderTarget(mRenderWindow);    mRenderWindow  =  0;    if(mRoot  !=  NULL){    delete  mRoot;    mRoot  =  0;    }
}
void  OgreView::setupResources()
{    mRoot  =  new  Ogre::Root();    Ogre::ConfigFile  cf;    cf.load("resources.cfg");    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);    }    }    if(!mRoot->restoreConfig())    {    mRoot->showConfigDialog();    }    mRoot->initialise(false);    //以上都是从Ogre普通程序照搬
}
//没啥说的,代码比注释更明白
void  OgreView::createScene()
{    mainEnt  =  mSceneMgr->createEntity("Head",  "ogrehead.mesh");    mainNode  =  mSceneMgr->getRootSceneNode()->createChildSceneNode();    mainNode->attachObject(mainEnt);
}
void  OgreView::createLight()
{    mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5,  0.5,  0.5));    mainLight  =  mSceneMgr->createLight("MainLight");    mainLight->setPosition(20,80,50);
}
void  OgreView::setupView()
{    if(mRenderWindow)    return;    //createRenderWindow,当然必须得自己手工建窗口了,把窗口句柄扒出来....    Ogre::NameValuePairList  params;    params["externalWindowHandle"]  =  Ogre::StringConverter::toString((size_t)(HWND)winId());    mRenderWindow  =  mRoot->createRenderWindow("View",  width(), height(),  false,  params);    //SceneManager    mSceneMgr  =  mRoot->createSceneManager(Ogre::ST_GENERIC);    //setup  camera  &  viewport      mCamera  =  mSceneMgr->createCamera("PlayerCam");    mCamera->setPosition(Ogre::Vector3(0,0,80));    mCamera->lookAt(Ogre::Vector3(0,0,-300));    mCamera->setNearClipDistance(5);    mVp  =  mRenderWindow->addViewport(mCamera);    mVp->setBackgroundColour(Ogre::ColourValue(0,  0.0,  0.0,  1));    mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth())  /  Ogre::Real(mVp->getActualHeight()));    //resource    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();    createScene();    createLight();    startTimer(2);
}
void  OgreView::paintEvent(QPaintEvent  *evt)
{    Q_UNUSED(evt);    if(mRenderWindow  ==  NULL)    setupView();    update();
}
void  OgreView::timerEvent(QTimerEvent*  evt)
{    Q_UNUSED(evt);    update();    }
void  OgreView::update()
{    //手工更新场景内容,而不是进入到连续的循环中    if(mRenderWindow  !=  NULL){    mRoot->_fireFrameStarted();    mRenderWindow->update();    mCamera->moveRelative(mDirection);    mCamera->yaw(Ogre::Radian(angleX));    mCamera->pitch(Ogre::Radian(angleY));    mRoot->_fireFrameEnded();    }
}
void  OgreView::resizeEvent(QResizeEvent  *evt)
{    Q_UNUSED(evt);    if  (mRenderWindow  !=  NULL){    mRenderWindow->windowMovedOrResized();    mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth())  /  Ogre::Real(mVp->getActualHeight()));    }
}
void  OgreView::keyPressEvent(QKeyEvent*  evt)
{    if(mainEnt  !=  NULL  &&  mainNode  !=  NULL){    switch(evt->key()){    case  Qt::Key_W:    case  Qt::Key_Up:    rotX  =  -0.1;    mainNode->pitch(Ogre::Radian(rotX));    break;    case  Qt::Key_S:    case  Qt::Key_Down:    rotX  =  0.1;    mainNode->pitch(Ogre::Radian(rotX));    break;    case  Qt::Key_A:    case  Qt::Key_Left:    rotY  =  -0.1;    mainNode->yaw(Ogre::Radian(rotY));    break;    case  Qt::Key_D:    case  Qt::Key_Right:    rotY  =  0.1;    mainNode->yaw(Ogre::Radian(rotY));    break;    }    }
}
void  OgreView::mousePressEvent(QMouseEvent*  evt)
{    if(evt->button()  ==  Qt::LeftButton)    mouseLeftPressed  =  true;    if(evt->button()  ==  Qt::RightButton){    mouseRightPressed  =  true;    mousePos  =  Ogre::Vector2(evt->x(),  evt->y());    }    if(evt->button()  ==  Qt::MidButton)    mouseMiddleBtn  =  true;
}
void  OgreView::wheelEvent(QWheelEvent*  evt)
{    mDirection.z  =  -evt->delta()/12;    update();    mDirection.z  =  0;
}    

Ogre3D嵌入Qt框架相关推荐

  1. 将OSG嵌入QT窗口系统中,实现拖拽界面

    将OSG嵌入QT窗口系统中,实现拖拽界面 一.原理 OSG底层使用的是OpenGL图形系统,QT也增加了对OpenGL的支持,因此,可以通过QT的OpenGL模块,实现将OSG窗口嵌入到QT中,这样可 ...

  2. C#的WinForm中嵌入Qt界面库

    C#的WinForm中嵌入Qt界面库 为何会有如此奇葩需求 一处代码,多处运行 C#有两种写界面的框架,winFrom和WPF,这二者写的界面可以相互调用,但C#编写的界面组件在非托管C++虽然理论上 ...

  3. 半小时训练亿级规模知识图谱,亚马逊AI开源知识图谱嵌入表示框架DGL-KE

    出品 | AI科技大本营(ID:rgznai100) 知识图谱 (Knowledge Graph)作为一个重要的技术,在近几年里被广泛运用在了信息检索,自然语言处理,以及推荐系统等各种领域.学习知识图 ...

  4. 半小时训练亿级规模知识图谱,亚马逊AI开源知识图谱嵌入表示框架

    来源:AI 科技大本营 本文约2300字,建议阅读9分钟 亚马逊 AI 团队开源了一款专门针对大规模知识图谱嵌入表示的新训练框架 DGL-KE,能让研究人员和工业界用户方便.快速地在大规模知识图谱数据 ...

  5. HTTP中CORS跨域请求的实现(C++|Qt框架实现)

    目录 背景 关键 演示及源码 背景 HTTP中CORS跨域请求,可以获取其他服务器的数据: 这里用Qt框架实现! 逻辑如下: 浏览器访问127.0.0.1:80端口!80端口请求了127.0.0.1: ...

  6. QT 框架搭建,用最原始的方法实现简单的塔防游戏 | 原力计划

    作者 | 白家名 责编 | 王晓曼 出品 | CSDN博客 本文作者使用 QT 框架写了一个塔防游戏程序,该程序中实现了购买炮塔.炮塔升级.怪物按照设定路径移动.炮塔自动寻找范围内目标.朝目标怪物发射 ...

  7. 基于海思平台与QT框架的高效视频显示

    首先,不涉及视频解码,仅涉及解码之后的视频缩放.颜色空间转换(如YUV转RGB).贴图.本文主要说明的是在QT框架没有使用OpenGl的情况下,如何让解码后的视频更高效的展示出来. 海思底层解码出来的 ...

  8. Qt框架与STL库之间的巅峰对决:差异、优缺点及适用场景

    Qt框架与STL库之间的巅峰对决:差异.优缺点及适用场景 引言 对比的重要性 Qt框架与STL库简介 博客内容概览 Qt框架基础 Qt框架的特点与组成 Qt的信号槽机制 Qt容器类简介 数据结构的对比 ...

  9. Qt框架之情人节玫瑰花案例项目

    Qt框架之情人节玫瑰花案例项目 本项目是源自Qt框架书写的一个项目,Qt版本选择的是Qt 5.3.1 该版本bug较少,出错几率小,适合入门者学习, 源码我放在CSDN资源了和github主页了. C ...

最新文章

  1. vs2008中如何在项目属性中切换“图形形式”和“控制台形式”——即调出或消除黑窗口
  2. 计算机设备安全检查表,信息安全检查表
  3. 为什么大部分程序员看不起PHP这门语言?
  4. MySQL提供了以下三种方法用于获取数据库对象的元数据
  5. 蚂蚁上市P8身价超亿,丢给我这几个牛逼的公众号
  6. 世界粮农组织五大健康食品_粮农组织的完整形式是什么?
  7. AAAI 2020 | 首个使用 NAS 设计的 GCN,达到动作识别SOTA,代码将开源
  8. ZOJ - 2865 A very easy task
  9. java便利店库存管理系统_便利店库存管理系统可以做什么?
  10. 无刷直流电机计算转速
  11. 工作站Linux双显卡BIOS设置,在BIOS Setup里面设置双显卡机型的双显卡模式教程
  12. package 包名; ^ zip END header not found
  13. 【Chapter 1】架构的结构
  14. 微信小程序留言板设计
  15. Android自定义控件开发入门与实战(7)SVG动画,android底层架构
  16. Java基础语法(十三):throw和throws
  17. 网页卡顿是网站服务器,想解决网站卡顿情况就用这几种诀窍,进来看看
  18. Python 基于csv 读取文本文件提示:‘gbk‘ codec can‘t decode byte 0xbf in position 2: illegal multibyte sequence
  19. 移动硬盘,U盘出现USBC病毒乱码恢复的可能性分析
  20. 【学习历程】05 安装大数据集群前的环境准备

热门文章

  1. zigbee协议栈OSAL分析
  2. 矩形脉冲信号合成_矩形脉冲信号的分解和合成
  3. ChatGPT来了,软件测试工程师距离失业还远吗?
  4. python调用java接口
  5. 昆仑通态触摸屏与台达变频器RS485通讯程序,不经过plc直接用昆仑通态触摸屏的串口对台达变频器进行modbus通讯
  6. QGraphicsScene Class
  7. Verilog Tutorial(5)使用always块实现时序逻辑电路
  8. 在华为eNSP上操作配置“静态路由”实验
  9. 【.NET 基础】——CLR、BCL、DLL、Assembly
  10. h3c 路由器虚拟机dhcp服务器,H3C三层交换机DHCP服务器配置实例