本文目录
1 简介
osgQOpenGL是OSG嵌入到QT的一种新的实现方法。OSG使用OpenGL进行三维模型的渲染,恰好Qt5也提供了对OpenGL的支持。因此,OSG提供了osgQOpenGL来实现对Qt的支持。
在以前的版本中,osg嵌入到Qt是使用osgQt插件中的GraphicsWindow或者GraphicsWidget,新版本提供osgQOpenGL插件来实现osg内嵌Qt。
2 环境准备
2.1 OSG
关于OSG的下载和编译,读者可查看笔者的上一篇博客。这里不再赘述。
2.2 osgQOpenGL
由于osgQOpenGL是OSG的一个插件,因此读者需要自行下载该插件的源码并编译。以下提供osgQOpenGL的下载链接,如果嫌弃下载速度慢,也可以使用笔者提供的源码包。
2.2.1 osgQOpenGL下载
下载地址1(Github):下载地址
下载地址2(优快云):下载地址
2.2.2 osgQOpenGL编译
源码包是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编译教程。
2.3 Qt
Qt的下载和安装都很简单,下载地址在笔者的上一篇博客中,有需要的朋友可以去看看。
3 osgQOpenGL的简单使用
3.1 osgQOpenGL源码
以下是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();
因此在使用的时候调用其公共接口就行。具体如何使用请看下文。
3.2 osgQOpenGLWidget的使用。
源码中定义了一个信号,那么很自然地就想到在自己的窗口类中定义一个槽函数。
如下:
protected slots:
void initOsgModel();
然后在窗口类的构造函数中进行信号和槽的绑定。
connect(osgQOpenGLWidget*, SIGNAL(initialized()), this, SLOT(initosgModel()));
将信号和槽绑定之后就可以在窗口上显示osg的三维模型。
3.2.1 MyWidget.h头文件
头文件代码如下:
#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()信号进行绑定。
3.2.2 MyWidget.cpp源文件
源文件代码如下:
#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的蓝色背景。具体原因笔者尚在探索中,如果某位读者知道原因,敬请留言告知笔者。
3.2.3 程序效果
程序运行效果如下图所示:
更改设置geometry函数的参数,可以得到如下效果:
4 总结
由于osgQOpenGLWidget继承自QWidget,因此很多QWidget的功能osgQOpenGLWidget都能直接使用,如:添加按钮,设置背景等。具体的实现过程可以由读者自行尝试。
最后加一句:
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!