[osg-users] qt5 qml plugin

Roy Arents osgforum at tevs.eu
Sun Nov 15 03:23:45 PST 2015


Hi,

I'm trying to create a qml pluing to display qt5 qtQuick qml files in osg directly.

The code below seems to work and I can see qml being draw and events are processed. However, the qml image does not seem to be updated/redrawn after receiving events. The image seems static.

I'm not sure were the problem lies. Does qt not update the osg image, or does osg does not show a new image. Perhaps someone can help with this?

Thank you!

Cheers,
Roy


Code:


#include "pluginsQML.h"
#include "QMLParameters.h"

#include <osg/MatrixTransform>
#include <osg/TextureRectangle>
#include <osg/Texture2D>
#include <osg/Object>

#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>

#include <osgQt/QWidgetImage>

#include <osgViewer/ViewerEventHandlers>

#include <QQuickWidget>
#include <QVBoxLayout>

class QmlEventHandler : public osgGA::GUIEventHandler
{
public:
    QmlEventHandler(QQuickWidget* widget) : _widget(widget) {}

    virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
    {
        switch(ea.getEventType())
        {
            case(osgGA::GUIEventAdapter::FRAME):
            {
                QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

//                QCoreApplication::postEvent(_widget,new QEvent(QEvent::UpdateRequest));
//                _widget->repaint();
//                _widget->update();
                break;
            }
            default:
	            break;
        }
        return false;
    }
    protected:
        QQuickWidget* _widget;
};

static QmlEventHandler* qmlEventHandler = NULL;

class ReaderWriterQML : public osgDB::ReaderWriter
{
public:

    ReaderWriterQML()
    {
        supportsExtension("qml", "");
        
        //supportsOption("shmem",        "Enable shared memory");
    }

    virtual ~ReaderWriterQML()
    {
    }

    virtual const char * className() const
    {
        return "ReaderWriterQML";
    }

    virtual ReadResult readNode(const std::string & filename, const osgDB::ReaderWriter::Options* options) const
    {
        const std::string ext = osgDB::getLowerCaseFileExtension(filename);
        if (ext=="qml")
        {
            osg::ref_ptr<osgQML::QMLParameters> parameters(new osgQML::QMLParameters);
            parseOptions(parameters.get(), options);

            std::string cmd = filename + " " + parameters->getOptionString();

            bool inScene = true;

            // There should be one QApplication
            if(!QApplication::instance()) 
            {
                char *argv[] = {"app", (char*)filename.c_str(), NULL};
                int argc = sizeof(argv) / sizeof(char*) - 1;
                new QApplication(argc,argv);
            }

            //QWidget* widget = new QWidget;
            //widget->setLayout(new QVBoxLayout);

            QQuickWidget* widget = new QQuickWidget;
            widget->setSource(QUrl::fromLocalFile(filename.c_str()));
            //widget->layout()->addWidget(quickWidget);

            // Size hack
            QSize initSize = widget->initialSize();
            if(initSize.width() != initSize.height()) osg::notify(osg::WARN) << "ReaderWriterQML - qml files with square size seem to work better in osg" << std::endl;
            widget->setGeometry(0, 0, 2*initSize.width(),2*initSize.height());

            osg::ref_ptr<osgQt::QWidgetImage> widgetImage = new osgQt::QWidgetImage(widget);
            //widgetImage->setDataVariance(osg::Object::DYNAMIC);
#if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
            widgetImage->getQWidget()->setAttribute(Qt::WA_TranslucentBackground);
#endif
            widgetImage->getQGraphicsViewAdapter()->setBackgroundColor(QColor(0, 0, 0, 0));
            widgetImage->getQGraphicsViewAdapter()->resize(initSize.width(), initSize.height()); // Size hack
            QGraphicsScene* graphicsScene = widgetImage->getQGraphicsViewAdapter()->getQGraphicsScene();

            osg::Camera* camera = 0;        // Will stay NULL in the inScene case.
            osg::Geometry* quad = osg::createTexturedQuadGeometry(osg::Vec3(0,0,0), osg::Vec3(1,0,0), osg::Vec3(0,1,0), 1, 1);
            osg::Geode* geode = new osg::Geode;
            geode->addDrawable(quad);

            osg::MatrixTransform* mt = new osg::MatrixTransform;

            osg::Texture2D* texture = new osg::Texture2D(widgetImage.get());
            texture->setResizeNonPowerOfTwoHint(false);
            texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
            texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
            texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
            mt->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

            osgViewer::InteractiveImageHandler* handler; 
            if (inScene)
            {
                mt->setMatrix(osg::Matrix::rotate(osg::Vec3(0,1,0), osg::Vec3(0,0,1)));
                mt->addChild(geode);

                handler = new osgViewer::InteractiveImageHandler(widgetImage.get());
            }
            else    // fullscreen
            {
                // The HUD camera's viewport needs to follow the size of the 
                // window. MyInteractiveImageHandler will make sure of this.
                // As for the quad and the camera's projection, setting the 
                // projection resize policy to FIXED takes care of them, so
                // they can stay the same: (0,1,0,1) with a quad that fits.

                // Set the HUD camera's projection and viewport to match the screen.
                camera = new osg::Camera;
                camera->setProjectionResizePolicy(osg::Camera::FIXED);
                camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
                camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                camera->setViewMatrix(osg::Matrix::identity());
                camera->setClearMask(GL_DEPTH_BUFFER_BIT);
                camera->setRenderOrder(osg::Camera::POST_RENDER);
                camera->addChild(geode);
                camera->setViewport(0, 0, 1024, 768);

                mt->addChild(camera);

                handler = new osgViewer::InteractiveImageHandler(widgetImage.get(), texture, camera);
            }

            mt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
            mt->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
            mt->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
            mt->getOrCreateStateSet()->setAttribute(new osg::Program);

            osg::Group* overlay = new osg::Group;
            overlay->addChild(mt);

            //root->addChild(overlay);
            
            quad->setEventCallback(handler);
            quad->setCullCallback(handler);

            if(!qmlEventHandler) // Only add ONE QmlEventHandler to process all qt events
            {
                qmlEventHandler = new QmlEventHandler(widget);
                overlay->setEventCallback(qmlEventHandler);
            }

            return overlay;

        }
        return ReadResult::FILE_NOT_HANDLED;
    }

    
private:
    
    void parseOptions(osgQML::QMLParameters* parameters, const osgDB::ReaderWriter::Options * options) const
    {
        if(!options) return;

        const std::string name = options->getName();
        int numPluginData = options->getNumPluginData();
        int numPluginStringData = options->getNumPluginStringData();
        const std::string optionString = options->getOptionString();
        if (options && options->getNumPluginStringData()>0)
        {
            const FormatDescriptionMap& supportedOptList = supportedOptions();

            for (FormatDescriptionMap::const_iterator itr = supportedOptList.begin();
                 itr != supportedOptList.end(); ++itr)
            {
                // Find the name
                std::string name(itr->first);
                size_t found = name.find("=");
                if(found!=std::string::npos)
                {
                    name = name.substr(0,found);
                }
                name.insert(0,"-");

                const std::string value = options->getPluginStringData(name);

                parameters->parse(name, value);
            }
        }
    }
};



REGISTER_OSGPLUGIN(qml, ReaderWriterQML)





------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=65646#65646








More information about the osg-users mailing list