osgQOpenGL的简单使用——在一个窗口中显示三维模型

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(CSDN):下载地址

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都能直接使用,如:添加按钮,设置背景等。具体的实现过程可以由读者自行尝试。
最后加一句:
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!
别白嫖了,点赞+关注啊!二连啊!打字不累的嘛!

猜你喜欢

转载自blog.csdn.net/GeomasterYi/article/details/107132140