osgQOpenGL是OSG嵌入到QT的一种新的实现方法。OSG使用OpenGL进行三维模型的渲染,恰好Qt5也提供了对OpenGL的支持。因此,OSG提供了osgQOpenGL来实现对Qt的支持。 在以前的版本中,osg嵌入到Qt是使用osgQt插件中的GraphicsWindow或者GraphicsWidget,新版本提供osgQOpenGL插件来实现osg内嵌Qt。
关于OSG的下载和编译,读者可查看笔者的上一篇博客。这里不再赘述。
由于osgQOpenGL是OSG的一个插件,因此读者需要自行下载该插件的源码并编译。以下提供osgQOpenGL的下载链接,如果嫌弃下载速度慢,也可以使用笔者提供的源码包。
下载地址1(Github):下载地址 下载地址2():下载地址
源码包是osgQt,但是编译后只生成两个lib库。如下图: 具体的编译方法和笔者的上一篇博客中介绍的编译方法一样,这里不再赘述,但需要强调一点,就是 需要在osgQt的源码包中的Cmakelists.txt中加入如下几段代码
SET(DESIRED_QT_VERSION "5.14.2" CACHE STRING "") SET(CMAKE_PREFIX_PATH "C:/Qt/Qt5.14.2/5.14.2/msvc2017_64" CACHE PATH "")添加位置如下图: 然后修改一下此处的数据(如下图): 然后就是使用cmake进行生成,然后使用VS2017编译,在然后生成lib库。上一篇博客中讲的很详细,不会的读者朋友请移步:osg编译教程。
Qt的下载和安装都很简单,下载地址在笔者的上一篇博客中,有需要的朋友可以去看看。
以下是osgQOpenGL/osgQOpenGLWidget的源码,不是很多,但可以看出一些东西。
#ifndef OSGQOPENGLWIDGET_H #define OSGQOPENGLWIDGET_H #ifdef __APPLE__ # define __glext_h_ # include <QtGui/qopengl.h> # undef __glext_h_ # include <QtGui/qopenglext.h> #endif #include <osgQOpenGL/Export> #include <OpenThreads/ReadWriteMutex> #ifdef WIN32 //#define __gl_h_ #include <osg/GL> #endif #include <osg/ArgumentParser> #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QReadWriteLock> class OSGRenderer; namespace osgViewer { class Viewer; } class OSGQOPENGL_EXPORT osgQOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT protected: OSGRenderer* m_renderer {nullptr}; bool _osgWantsToRenderFrame{true}; OpenThreads::ReadWriteMutex _osgMutex; osg::ArgumentParser* _arguments {nullptr}; bool _isFirstFrame {true}; friend class OSGRenderer; public: osgQOpenGLWidget(QWidget* parent = nullptr); osgQOpenGLWidget(osg::ArgumentParser* arguments, QWidget* parent = nullptr); virtual ~osgQOpenGLWidget(); /** Get osgViewer View */ virtual osgViewer::Viewer* getOsgViewer(); //! get mutex virtual OpenThreads::ReadWriteMutex* mutex(); signals: void initialized(); protected: //! call createRender. If overloaded, this method must send initialized signal at end void initializeGL() override; void resizeGL(int w, int h) override; //! lock scene graph and call osgViewer::frame() void paintGL() override; //! called before creating renderer virtual void setDefaultDisplaySettings(); void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; void mouseDoubleClickEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void wheelEvent(QWheelEvent* event) override; void createRenderer(); private: }; #endif // OSGQOPENGLWIDGET_H从源码中可以看出,osgQOpenGLWidget继承自QOpenGLWidget,类中定义了两个接口和一个信号(划重点)。 公开接口只有以下两个:
virtual osgViewer::Viewer* getOsgViewer(); virtual OpenThreads::ReadWriteMutex* mutex();信号函数也只有一个:
void initialized();因此在使用的时候调用其公共接口就行。具体如何使用请看下文。
源码中定义了一个信号,那么很自然地就想到在自己的窗口类中定义一个槽函数。 如下:
protected slots: void initOsgModel();然后在窗口类的构造函数中进行信号和槽的绑定。
connect(osgQOpenGLWidget*, SIGNAL(initialized()), this, SLOT(initosgModel()));将信号和槽绑定之后就可以在窗口上显示osg的三维模型。
头文件代码如下:
#ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include <osgQOpenGL/osgQOpenGLWidget> #include <string> using namespace std; QT_BEGIN_NAMESPACE namespace Ui { class MyWidget; } QT_END_NAMESPACE class MyWidget : public QWidget { Q_OBJECT public: MyWidget(QWidget *parent = nullptr); ~MyWidget(); void setFile(string sFilename); protected slots: void initWindow(); protected: osgQOpenGLWidget* _pOsgQOpenGLWidget; string _sFilename; private: Ui::MyWidget *ui; }; #endif // MYWIDGET_H头文件中定义了一个槽函数initWindow(),该函数将会在MyWidget的构造函数中与 osgQOpenGLWidget的对象指针的initialized()信号进行绑定。
源文件代码如下:
#include "mywidget.h" #include "ui_mywidget.h" #include <osgViewer/Viewer> #include <osg/Node> #include <osgDB/ReadFile> #include <osgGA/TrackballManipulator> MyWidget::MyWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::MyWidget) { ui->setupUi(this); _pOsgQOpenGLWidget = new osgQOpenGLWidget(this); _pOsgQOpenGLWidget->setGeometry(this->geometry()); connect(_pOsgQOpenGLWidget, SIGNAL(initialized()), this, SLOT(initWindow())); } MyWidget::~MyWidget() { delete ui; if(_pOsgQOpenGLWidget != NULL) delete _pOsgQOpenGLWidget; } void MyWidget::setFile(string sFilename) { _sFilename = sFilename; } void MyWidget::initWindow() { osgViewer::Viewer* pViewer = _pOsgQOpenGLWidget->getOsgViewer(); pViewer->setCameraManipulator(new osgGA::TrackballManipulator); osg::Node* node = osgDB::readNodeFile(_sFilename); pViewer->setSceneData(node); }注意,initWindow()函数中,唯一需要着重提一下的是这条语句:
pViewer->setCameraManipulator(new osgGA::TrackballManipulator);这条语句如果去掉,将无法加载osg的三维模型,只会显示osgViewer的蓝色背景。具体原因笔者尚在探索中,如果某位读者知道原因,敬请留言告知笔者。
程序运行效果如下图所示: 更改设置geometry函数的参数,可以得到如下效果:
由于osgQOpenGLWidget继承自QWidget,因此很多QWidget的功能osgQOpenGLWidget都能直接使用,如:添加按钮,设置背景等。具体的实现过程可以由读者自行尝试。 最后加一句: 别白嫖了,点赞+关注啊!二连啊!打字不累的嘛! 别白嫖了,点赞+关注啊!二连啊!打字不累的嘛! 别白嫖了,点赞+关注啊!二连啊!打字不累的嘛! 别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
