applefly 发表于 2019-9-27 11:12:26

OSG嵌入Qt中的QOpenGLWidget

在网上找了很久,有些是OSGQt插件单该插件是QGLWidget类的,这个类在新版本中废弃了建议用QOpenGLWidget
自己写了个测试类,附件中有Qt例子,使用是注意修改OSG编译后include,lib,bin目录
//头文件
#pragma once
#include <QOpenGLWidget>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QKeyEvent>
#include <QEvent>

#include <osgViewer/Viewer>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/GUIEventHandler>
class QtOSGWidget : public QOpenGLWidget
{
        Q_OBJECT

public:
        QtOSGWidget(QWidget *parent = nullptr);
        ~QtOSGWidget();
protected:
        void initializeGL()override;
        void paintGL()override;
        void resizeGL(int w, int h)override;
        //将osgGA::EventQueue事件与Qt鼠标事件相关联
        void mouseDoubleClickEvent(QMouseEvent *event)override;
        void mouseMoveEvent(QMouseEvent *event)override;
        void mousePressEvent(QMouseEvent *event)override;
        void mouseReleaseEvent(QMouseEvent *event)override;
        void wheelEvent(QWheelEvent *event)override;
        void keyPressEvent(QKeyEvent *event)override;
        void keyReleaseEvent(QKeyEvent *event)override;

        bool event(QEvent *event) override;
private:
        osgGA::EventQueue* getEventQueue()const;
        void setKeyboardModifiers(QInputEvent* event);
        osg::ref_ptr<osg::Node> createOSGGlider();
private:
        osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> _mGraphicsWindow;
        osg::ref_ptr<osgViewer::Viewer> _mViewer;
};
//源文件
#pragma execution_character_set("utf-8")
#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgViewerd.lib")
#pragma comment(lib,"osgGAd.lib")
#pragma comment(lib,"osgDBd.lib")
#else
#pragma comment(lib,"osg.lib")
#pragma comment(lib,"osgViewer.lib")
#pragma comment(lib,"osgGA.lib")
#pragma comment(lib,"osgDB.lib")
#endif

#include "QtOSGWidget.h"
/**
1、创建图形上下文和图形窗口
2、将图形上下文附加到相机
3、将相机设置为主视图
*/
QtOSGWidget::QtOSGWidget(QWidget *parent)
        : QOpenGLWidget(parent),
        _mViewer(new osgViewer::Viewer),
        _mGraphicsWindow(new osgViewer::GraphicsWindowEmbedded(this->x(),this->y(),this->width(),this->height()))
{
        setFocusPolicy(Qt::StrongFocus);
        this->setMinimumSize(100, 100);
}

QtOSGWidget::~QtOSGWidget()
{
}
/**
设置OpenGL资源和状态
*/
void QtOSGWidget::initializeGL() {
        osg::Camera* camera = _mViewer->getCamera();
        camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
        camera->setProjectionMatrixAsPerspective(30, (double)this->width() / this->height(), 1, 1000);
        camera->setViewport(0, 0, this->width(), this->height());
        camera->setGraphicsContext(_mGraphicsWindow.get());

        osg::ref_ptr<osgGA::TrackballManipulator> manipulator = new osgGA::TrackballManipulator();
        manipulator->setAllowThrow(false);
        _mViewer->setCameraManipulator(manipulator.get());
        _mViewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
        _mViewer->addEventHandler((new osgGA::StateSetManipulator(camera->getOrCreateStateSet())));
        //_mViewer->addEventHandler(new osgViewer::WindowSizeHandler);
        _mViewer->addEventHandler(new osgViewer::StatsHandler);
        osg::ref_ptr<osg::Group> root = new osg::Group();

        QByteArray barr = QString("root").toLocal8Bit();
        char* bdata = barr.data();
        root->setName(bdata);
        root->addChild(createOSGGlider().get());
       
        //优化场景数据
        /*osgUtil::Optimizer optimizer;
        optimizer.optimize(root.get());*/
        _mViewer->setSceneData(root);
        _mViewer->realize();
}
/**
在场景更新时渲染OpenGL
*/
void QtOSGWidget::paintGL() {
        _mViewer->frame();
}
/**
设置OpenGL视口,投影等
*/
void QtOSGWidget::resizeGL(int w, int h) {
        this->getEventQueue()->windowResize(this->x(), this->y(), w, h);
        _mGraphicsWindow->resized(this->x(), this->y(), w, h);
        osg::Camera* camera = _mViewer->getCamera();
        camera->setViewport(this->x(), this->y(), w, h);
}
/**
获取OSG事件队列
*/
osgGA::EventQueue* QtOSGWidget::getEventQueue()const {
        return _mGraphicsWindow->getEventQueue();
};
void QtOSGWidget::mouseDoubleClickEvent(QMouseEvent *event) {
        setKeyboardModifiers(event);
        int button = 0;
        switch (event->button())
        {
        case Qt::LeftButton:
                button = 1;
                break;
        case Qt::MidButton:
                button = 2;
                break;
        case Qt::RightButton:
                button = 3;
                break;
        }
        getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(), button);
        QOpenGLWidget::mouseDoubleClickEvent(event);
}
void QtOSGWidget::mouseMoveEvent(QMouseEvent *event) {
        setKeyboardModifiers(event);
        getEventQueue()->mouseMotion(event->x(), event->y());
        QOpenGLWidget::mouseMoveEvent(event);
}
void QtOSGWidget::mousePressEvent(QMouseEvent *event) {
        setKeyboardModifiers(event);
        int button = 0;
        switch (event->button())
        {
        case Qt::LeftButton:
                button = 1;
                break;
        case Qt::MidButton:
                button = 2;
                break;
        case Qt::RightButton:
                button = 3;
                break;
        }
        getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
        QOpenGLWidget::mousePressEvent(event);
}
void QtOSGWidget::mouseReleaseEvent(QMouseEvent *event) {
        setKeyboardModifiers(event);
        int button = 0;
        switch (event->button())
        {
        case Qt::LeftButton:
                button = 1;
                break;
        case Qt::MidButton:
                button = 2;
                break;
        case Qt::RightButton:
                button = 3;
                break;
        }
        getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);
        QOpenGLWidget::mouseReleaseEvent(event);
}
void QtOSGWidget::wheelEvent(QWheelEvent *event) {
        setKeyboardModifiers(event);
        getEventQueue()->mouseScroll(event->orientation() == Qt::Vertical ?
                (event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
                (event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT));
        QOpenGLWidget::wheelEvent(event);
}
bool QtOSGWidget::event(QEvent *event) {
        bool handled = QOpenGLWidget::event(event);
        switch (event->type())
        {
        case QEvent::MouseButtonPress:
        case QEvent::MouseButtonRelease:
        case QEvent::MouseMove:
        case QEvent::Wheel:
        case QEvent::MouseButtonDblClick:
        case QEvent::KeyPress:
        case QEvent::KeyRelease:
                this->update();
                break;
        default:
                break;
        }
        return handled;
}
void QtOSGWidget::setKeyboardModifiers(QInputEvent* event) {
        int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::AltModifier | Qt::ControlModifier);
        unsigned mask = 0;
        if (modkey & Qt::ShiftModifier) {
                mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
        }
        if (modkey & Qt::AltModifier) {
                mask |= osgGA::GUIEventAdapter::MODKEY_ALT;
        }
        if (modkey & Qt::ControlModifier) {
                mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
        }
        getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
}
void QtOSGWidget::keyPressEvent(QKeyEvent *event) {
        setKeyboardModifiers(event);
        //QByteArray KeyData = event->text().toLocal8Bit();
        /*const char* cKey = KeyData.data();
        osgGA::GUIEventAdapter::KeySymbol symbol = osgGA::GUIEventAdapter::KeySymbol(event->key());*/
        //getEventQueue()->keyPress();
        switch (event->key())
        {
        case Qt::Key_F:
        {
                //从观察者获取节点的方式
                osg::Geode* geode = dynamic_cast<osg::Geode*>(_mViewer->getSceneData());
                int count = geode->getNumDrawables();
                for (int i = 0; i < count; ++i) {
                        osg::ShapeDrawable* draw = dynamic_cast<osg::ShapeDrawable*> (geode->getDrawable(i));
                        std::string name = draw->getName();
                        if (name == "zidingyi1") {
                                draw->setColor(osg::Vec4(0.0, 1.0, 0.0, 1.0));
                        }
                }
                getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_F);
        }
                break;
        case Qt::Key_D:
        {
                //从观察者获取节点的方式
                osg::Geode* geode = dynamic_cast<osg::Geode*>(_mViewer->getSceneData());
                int count = geode->getNumDrawables();
                for (int i = 0; i < count; ++i) {
                        osg::Drawable* draw = geode->getDrawable(i);
                        std::string name = draw->getName();
                        if (name == "zidingyi1") {
                                geode->removeDrawable(draw);
                        }
                }
        }
                break;
        case Qt::Key_S:
        {
                getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_S);
        }
        break;
        case Qt::Key_L:
        {
                getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_L);
        }
        break;
        case Qt::Key_W:
        {
                getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_W);
        }
        break;
        default:
                break;
        }
        QOpenGLWidget::keyPressEvent(event);
}
void QtOSGWidget::keyReleaseEvent(QKeyEvent *event) {
        setKeyboardModifiers(event);

        QOpenGLWidget::keyReleaseEvent(event);
}
osg::ref_ptr<osg::Node> QtOSGWidget::createOSGGlider() {
        osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile("glider.osg");
        QByteArray barr = QString("飞机").toLocal8Bit();
        char* bdata = barr.data();
        node->setName(bdata);
        return node.get();
}

zhdhbut 发表于 2020-4-4 18:17:18

感谢了,我是初学者。参考一下。

yanguoliuhen 发表于 2021-11-6 09:37:58

感谢分享,初学:handshake:handshake

liuyj_vv 发表于 2022-1-11 16:13:13

我需要在多个从相机在不同的widget中显示,用QOpenGLWidget能做到吗?
osg新手--当前可以弹出 win32和QGLWidget窗口来显示从相机。QOpenGLWidget直接一片黑


#pragma once
#include "Common.h"

class GraphicsWindowEmbeddedQt : public osgViewer::GraphicsWindowEmbedded
{
public:
        bool _valid = true;
        bool _realized = false;
        QOpenGLWidget *_widget = nullptr;
       
        GraphicsWindowEmbeddedQt(int x, int y, int width, int height, QWidget *widget)
                : osgViewer::GraphicsWindowEmbedded(x, y, width, height)
        {
                _widget = static_cast<QOpenGLWidget *>(widget);
        }
        virtual bool realizeImplementation()
        {
                qDebug() << __FUNCTION__ << __LINE__;
                const QGLContext *savedContext = QGLContext::currentContext();


                _widget->context();

                if (!valid())
                {
//                        _widget->glInit();
                }

                _realized = true;
                bool result = makeCurrent();
                _realized = false;

                // fail if we do not have current context
                if (!result) {
                        if (savedContext)
                                const_cast<QGLContext*>(savedContext)->makeCurrent();

                        OSG_WARN << "Window realize: Can make context current." << std::endl;
                        return false;
                }

                _realized = true;

                // make sure the event queue has the correct window rectangle size and input range
                getEventQueue()->syncWindowRectangleWithGraphicsContext();

                if (!releaseContext())
                        OSG_WARN << "Window realize: Can not release context." << std::endl;

                // restore previous context
                if (savedContext)
                        const_cast<QGLContext*>(savedContext)->makeCurrent();

                return true;
        }

        virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const GraphicsWindowEmbedded*>(object) != 0; }
        virtual const char* libraryName() const { return "osgViewer"; }
        virtual const char* className() const { return "GraphicsWindowEmbeddedQt"; }

        virtual bool valid() const
        {
                return nullptr != _widget ? _widget->isValid() : false;
        }

        bool isRealizedImplementation() const
        {
                qDebug() << __FUNCTION__ << __LINE__;

                return _realized;
        }

        void closeImplementation()
        {
                qDebug() << __FUNCTION__ << __LINE__;
                if (_widget)
                        _widget->close();
                _realized = false;
                _widget = nullptr;
        }

        bool makeCurrentImplementation()
        {
                const QGLContext *savedContext = QGLContext::currentContext();
                if (savedContext)
                        const_cast<QGLContext*>(savedContext)->makeCurrent();
                _widget->makeCurrent();
                return true;
        }

        bool releaseContextImplementation()
        {
                _widget->doneCurrent();
                return true;
        }

        void swapBuffersImplementation()
        {
                const QGLContext *savedContext = QGLContext::currentContext();
                if (savedContext)
                        const_cast<QGLContext*>(savedContext)->makeCurrent();
                _widget->makeCurrent();

        }

        //virtual bool makeCurrentImplementation() { qDebug() << __FUNCTION__ << __LINE__; return true; }
        //virtual bool releaseContextImplementation() { qDebug() << __FUNCTION__ << __LINE__; return true; }
        //virtual void swapBuffersImplementation() { qDebug() << __FUNCTION__ << __LINE__; }
        virtual void grabFocus() { qDebug() << __FUNCTION__ << __LINE__; }
        virtual void grabFocusIfPointerInWindow() { qDebug() << __FUNCTION__ << __LINE__; }
        virtual void raiseWindow() { qDebug() << __FUNCTION__ << __LINE__; }
};

页: [1]
查看完整版本: OSG嵌入Qt中的QOpenGLWidget