查看: 3985|回复: 3

OSG嵌入Qt中的QOpenGLWidget

[复制链接]

该用户从未签到

发表于 2019-9-27 11:12:26 | 显示全部楼层 |阅读模式
在网上找了很久,有些是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:tOSGWidget(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:eftButton:
                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:rawable* 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();
}

OSGForQOpenGLWidget.zip

4.54 MB, 下载次数: 284, 下载积分: 威望 1

OSG嵌入QOpenGLWidget例子

该用户从未签到

发表于 2020-4-4 18:17:18 | 显示全部楼层
感谢了,我是初学者。参考一下。

该用户从未签到

发表于 2021-11-6 09:37:58 | 显示全部楼层
感谢分享,初学:handshake
  • TA的每日心情
    擦汗
    2022-1-12 10:00
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2022-1-11 16:13:13 | 显示全部楼层
    我需要在多个从相机在不同的widget中显示,用QOpenGLWidget能做到吗?
    osg新手--当前可以弹出 win32和QGLWidget窗口来显示从相机。QOpenGLWidget直接一片黑


    1. #pragma once
    2. #include "Common.h"

    3. class GraphicsWindowEmbeddedQt : public osgViewer::GraphicsWindowEmbedded
    4. {
    5. public:
    6.         bool _valid = true;
    7.         bool _realized = false;
    8.         QOpenGLWidget *_widget = nullptr;
    9.        
    10.         GraphicsWindowEmbeddedQt(int x, int y, int width, int height, QWidget *widget)
    11.                 : osgViewer::GraphicsWindowEmbedded(x, y, width, height)
    12.         {
    13.                 _widget = static_cast<QOpenGLWidget *>(widget);
    14.         }
    15.         virtual bool realizeImplementation()
    16.         {
    17.                 qDebug() << __FUNCTION__ << __LINE__;
    18.                 const QGLContext *savedContext = QGLContext::currentContext();


    19.                 _widget->context();

    20.                 if (!valid())
    21.                 {
    22. //                        _widget->glInit();
    23.                 }

    24.                 _realized = true;
    25.                 bool result = makeCurrent();
    26.                 _realized = false;

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

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

    34.                 _realized = true;

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

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

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

    42.                 return true;
    43.         }

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

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

    51.         bool isRealizedImplementation() const
    52.         {
    53.                 qDebug() << __FUNCTION__ << __LINE__;

    54.                 return _realized;
    55.         }

    56.         void closeImplementation()
    57.         {
    58.                 qDebug() << __FUNCTION__ << __LINE__;
    59.                 if (_widget)
    60.                         _widget->close();
    61.                 _realized = false;
    62.                 _widget = nullptr;
    63.         }

    64.         bool makeCurrentImplementation()
    65.         {
    66.                 const QGLContext *savedContext = QGLContext::currentContext();
    67.                 if (savedContext)
    68.                         const_cast<QGLContext*>(savedContext)->makeCurrent();
    69.                 _widget->makeCurrent();
    70.                 return true;
    71.         }

    72.         bool releaseContextImplementation()
    73.         {
    74.                 _widget->doneCurrent();
    75.                 return true;
    76.         }

    77.         void swapBuffersImplementation()
    78.         {
    79.                 const QGLContext *savedContext = QGLContext::currentContext();
    80.                 if (savedContext)
    81.                         const_cast<QGLContext*>(savedContext)->makeCurrent();
    82.                 _widget->makeCurrent();

    83.         }

    84.         //virtual bool makeCurrentImplementation() { qDebug() << __FUNCTION__ << __LINE__; return true; }
    85.         //virtual bool releaseContextImplementation() { qDebug() << __FUNCTION__ << __LINE__; return true; }
    86.         //virtual void swapBuffersImplementation() { qDebug() << __FUNCTION__ << __LINE__; }
    87.         virtual void grabFocus() { qDebug() << __FUNCTION__ << __LINE__; }
    88.         virtual void grabFocusIfPointerInWindow() { qDebug() << __FUNCTION__ << __LINE__; }
    89.         virtual void raiseWindow() { qDebug() << __FUNCTION__ << __LINE__; }
    90. };

    复制代码
    微信图片_20220111161211.png
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    OSG中国官方论坛-有您OSG在中国才更好

    网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

    联系我们

    • 工作时间:09:00--18:00
    • 反馈邮箱:1315785073@qq.com
    快速回复 返回顶部 返回列表