OSG embedded QT concise summary

1. Solution

About OSG have to say is too fragmented, and search a lot about OSG solution in QT, are each have their own versions, some say not very clear, and some have been out of date. Here are solutions to it yourself.
In ancient OSG which should provide support for the QT; however it should be due to the relatively large changes in QT version, now OSG version should have been gone. But on GitHub has a new osgQt project (address: https://github.com/openscenegraph/osgQt ) used to solve this problem.
osgQt is a simple little project, it did not need additional compiler, the core is called GraphicsWindowQt class, just copy GraphicsWindowQt.h and GraphicsWindowQt.cpp to QT project which is ready for use. Meanwhile osgQt gives a sample called osgviewerQt, it is only just a cpp file. Combination of both, a simple example came out.
QT works as follows:

After compiling run as follows:

2. Problems

1) warning

These projects run directly, will appear as "QOpenGLContext :: swapBuffers () called with non-exposed window, behavior is undefined" warning. Access to online information in English, to the effect that because the environment is not initialized OpenGL generated. Binding osgviewerQt in a timer is called every 10ms frame () to draw one, and the timer is started when the constructor call, no waiting for generating the QT OpenGL environment. Here I put part timers to improve a bit, waiting for the completion of the OSG environment initialization timer is started, there is no warning. The code osgviewerQt improved as follows:

#include <QTimer>
#include <QApplication>
#include <QGridLayout>

#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/MultiTouchTrackballManipulator>

#include <osgDB/ReadFile>

#include "GraphicsWindowQt"

#include <iostream>

class ViewerWidget : public QWidget, public osgViewer::CompositeViewer
{
public:
    ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded) : QWidget(parent, f)
    {
        setThreadingModel(threadingModel);

        // disable the default setting of viewer.done() by pressing Escape.
        setKeyEventSetsDone(0);

        QWidget* widget1 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("D:/Work/OSGBuild/OpenSceneGraph-Data/cow.osgt") );
        QWidget* widget2 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("D:/Work/OSGBuild/OpenSceneGraph-Data/glider.osgt") );
        QWidget* widget3 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("D:/Work/OSGBuild/OpenSceneGraph-Data/axes.osgt") );
        QWidget* widget4 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("D:/Work/OSGBuild/OpenSceneGraph-Data/fountain.osgt") );
//        QWidget* popupWidget = addViewWidget( createGraphicsWindow(900,100,320,240,"Popup window",true), osgDB::readRefNodeFile("D:/Work/OSGBuild/OpenSceneGraph-Data/dumptruck.osgt") );
//        popupWidget->show();

        QGridLayout* grid = new QGridLayout;
        grid->addWidget( widget1, 0, 0 );
        grid->addWidget( widget2, 0, 1 );
        grid->addWidget( widget3, 1, 0 );
        grid->addWidget( widget4, 1, 1 );
        setLayout( grid );

        //connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
        //_timer.start( 10 );
    }

    QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::ref_ptr<osg::Node> scene )
    {
        osgViewer::View* view = new osgViewer::View;
        addView( view );

        osg::Camera* camera = view->getCamera();
        camera->setGraphicsContext( gw );

        const osg::GraphicsContext::Traits* traits = gw->getTraits();

        camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
        camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );

        // set the draw and read buffers up for a double buffered window with rendering going to back buffer
        camera->setDrawBuffer(GL_BACK);
        camera->setReadBuffer(GL_BACK);

        camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f );

        view->setSceneData( scene );
        view->addEventHandler( new osgViewer::StatsHandler );
        view->setCameraManipulator( new osgGA::MultiTouchTrackballManipulator );
        gw->setTouchEventsEnabled( true );
        return gw->getGLWidget();
    }

    osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false )
    {
        osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->windowName = name;
        traits->windowDecoration = windowDecoration;
        traits->x = x;
        traits->y = y;
        traits->width = w;
        traits->height = h;
        traits->doubleBuffer = true;
        traits->alpha = ds->getMinimumNumAlphaBits();
        traits->stencil = ds->getMinimumNumStencilBits();
        traits->sampleBuffers = ds->getMultiSamples();
        traits->samples = ds->getNumMultiSamples();

        return new osgQt::GraphicsWindowQt(traits.get());
    }

//    virtual void paintEvent( QPaintEvent* /*event*/ )
//    { frame(); }

    //定时器事件
    void timerEvent(QTimerEvent* )
    {
        frame();
    }

    //启动定时器绘制
    void show()
    {
        QWidget::show();
        _timerID = startTimer(10);
    }


protected:

    //QTimer _timer;
    int _timerID;               //定时器ID
};

int main( int argc, char** argv )
{
    osg::ArgumentParser arguments(&argc, argv);

#if QT_VERSION >= 0x050000
    // Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different thread" when the viewer is run multi-threaded, this is regression from Qt4
    osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::SingleThreaded;
#else
    osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
#endif

    while (arguments.read("--SingleThreaded")) threadingModel = osgViewer::ViewerBase::SingleThreaded;
    while (arguments.read("--CullDrawThreadPerContext")) threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
    while (arguments.read("--DrawThreadPerContext")) threadingModel = osgViewer::ViewerBase::DrawThreadPerContext;
    while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) threadingModel = osgViewer::ViewerBase::CullThreadPerCameraDrawThreadPerContext;

#if QT_VERSION >= 0x040800
    // Required for multithreaded QGLWidget on Linux/X11, see http://blog.qt.io/blog/2011/06/03/threaded-opengl-in-4-8/
    if (threadingModel != osgViewer::ViewerBase::SingleThreaded)
        QApplication::setAttribute(Qt::AA_X11InitThreads);
#endif

    QApplication app(argc, argv);
    ViewerWidget* viewWidget = new ViewerWidget(0, Qt::Widget, threadingModel);
    viewWidget->setGeometry( 100, 100, 800, 600 );
    viewWidget->show();
    return app.exec();
}

2) multi-threading issues

在OSG中提供了诸如CullDrawThreadPerContext等多线程模式,但是在这里是没办法支持这些多线程模式的,只能支持单线程。在网上查阅了一些解决方案,但是最后都不是很完美,有空再把其解决方案写出来。

3) 其他

GraphicsWindowQt最终继承的还是QT中的QGLWidget类,提供OpenGL功能。而在新版本的QT中,这个类已经被废弃了,取而代之的是一个叫做QOpenGLWidget的类。所以这里面问题还是不少的,好在内容相对较少,以后有空可以自己改进。

Guess you like

Origin www.cnblogs.com/charlee44/p/11031757.html