OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/98730328

目录

前言

地球控件

运行效果

运行Demo下载地址

QGLWidget与QOpenGLWidget详解

QOpenGLWidget放置半透明控件

关键代码

OsgViewerWidget.h

OsgViewerWidget.cpp

入坑

入坑一:进去就当机

入坑二:渲染窗口出现问题不对和球体横截面的问题

工程模板:对应版本号1.20.0


 

OSG三维开发专栏

OSG开发笔记(一):OSG介绍、编译

OSG开发笔记(二):OSG帮助文档编译

OSG开发笔记(三):OSG使用osgQt嵌入Qt应用程序

OSG开发笔记(四):OSG不使用osgQt重写类嵌入Qt应用程序》:

OSG开发笔记(五):OSG场景理解与基础类概述

OSG开发笔记(六):OSG内存管理

OSG开发笔记(七):OSG复现OpenGL入门示例和OSG坐标系

OSG开发笔记(八):OSG模型文件存储与读取

OSG开发笔记(九):OSG模型的基本操作之添加/删除、显示/隐藏、开关节点开/》:

OSG开发笔记(十):OSG模型的变换之平移、旋转和缩放

OSG开发笔记(十一):OSG渲染状态与2D纹理映射

OSG开发笔记(十二):OSG基本几何图形、内置几何类型

OSG开发笔记(十三):OSG三维纹理映射(体渲染)

OSG开发笔记(十四):OSG交互

OSG开发笔记(十五):OSG光照

OSG开发笔记(十六):OSG视口、相机和视点

OSG开发笔记(十七):OSG中的相机移动

OSG开发笔记(十八):OSG鼠标拾取pick、拽托球体以及多光源

OSG开发笔记(十九):OSG文字显示

OSG开发笔记(二十):OSG使用HUD显示文字

OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式

OSG开发笔记(二十二):OSG场景背景

OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG地球仪

OSG开发笔记(二十四):OSG漫游之平移、转向和低抬头

OSG开发笔记(二十五):OSG漫游之CS移动、碰撞检测与跳跃

OSG开发笔记(二十六):OSG漫游之上下楼梯

《OSG开发笔记(二十七):OSG路径漫游之录制播放固定路径动画

《OSG开发笔记(二十八):OSG模型固定路径动画

  持续补充中…

 

  OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪

 

前言

       在之前工程中,osgQt和移植osgQt过来都是通过QGLWidget渲染,Qt在5.5及以后推荐使用QOpenGLWidget窗口替代QGLWidget,在应用层最大的区别就是在QGLWidget上放置控件是无法半透明的,而在QOpenGLWidget上放置控件是可以透明的。

 

地球控件

运行效果

        该项目是在Qt中渲染OSG实现效果的:

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第1张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第2张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第3张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第4张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第5张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第6张图片

运行Demo下载地址

       https://download.csdn.net/download/qq21497936/11489564

 

QGLWidget与QOpenGLWidget详解

       请参考《Qt开发笔记:QGLWidget、QOpenGLWidget详解及区别》

 

QOpenGLWidget放置半透明控件

       请参考《关于 QGLWidget和QOpengGLWidget透明相关问题 的问题》

       OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第7张图片

 

关键代码

OsgViewerWidget.h

#ifndef OSGVIEWERWIDGET_H
#define OSGVIEWERWIDGET_H

#include 
#include 

class QInputEvent;

class OsgViewerWidget : public QOpenGLWidget, public osgViewer::Viewer
{
    Q_OBJECT

public:
    OsgViewerWidget(QWidget *parent = 0);
    ~OsgViewerWidget();

signals:
    void signal_clearWidget();

protected:
    bool event(QEvent* event);

    void setKeyboardModifiers(QInputEvent* event);
    void keyPressEvent(QKeyEvent* event);
    void keyReleaseEvent(QKeyEvent* event);
    void mousePressEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void mouseDoubleClickEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void wheelEvent(QWheelEvent* event);
    void resizeEvent(QResizeEvent *event);
    void moveEvent(QMoveEvent* event);
    void timerEvent(QTimerEvent *);

    osgViewer::Viewer* getOSGViewer() { return this; }
    osg::Group* getRoot(){ return root; }

protected:
    virtual void paintGL();

private:
    void init3D();
    osg::ref_ptr createCamera(int x, int y, int w, int h);

private:
    osg::ref_ptr root;
    osgViewer::GraphicsWindow* window;
};

#endif // OSGVIEWERWIDGET_H

OsgViewerWidget.cpp

#include "OsgViewerWidget.h"

#include "OsgViewerWidget.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "eventHandler/MyUserPickEventHandler.h"

OsgViewerWidget::OsgViewerWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    init3D();
    setMouseTracking(true);
    setFocusPolicy(Qt::StrongFocus);
}

OsgViewerWidget::~OsgViewerWidget()
{
}

bool OsgViewerWidget::event(QEvent *event)
{
    switch (event->type()) {
    case QEvent::TouchBegin:
    case QEvent::TouchEnd:
    case QEvent::TouchUpdate: {
        QList touchPoints = static_cast(event)->touchPoints();
        unsigned int id = 0;
        unsigned int tapCount = touchPoints.size();

        osg::ref_ptr osgEvent(NULL);
        osgGA::GUIEventAdapter::TouchPhase phase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN;
        foreach (const QTouchEvent::TouchPoint& touchPoint, touchPoints) {
            if (!osgEvent) {
                if (event->type() == QEvent::TouchBegin) {
                    phase = osgGA::GUIEventAdapter::TOUCH_BEGAN;
                    osgEvent = window->getEventQueue()->touchBegan(id, osgGA::GUIEventAdapter::TOUCH_BEGAN, touchPoint.pos().x(), touchPoint.pos().y());
                } else if (event->type() == QEvent::TouchEnd) {
                    phase = osgGA::GUIEventAdapter::TOUCH_ENDED;
                    osgEvent = window->getEventQueue()->touchEnded(id, osgGA::GUIEventAdapter::TOUCH_ENDED, touchPoint.pos().x(), touchPoint.pos().y(), tapCount);
                } else if (event->type() == QEvent::TouchUpdate) {
                    phase = osgGA::GUIEventAdapter::TOUCH_MOVED;
                    osgEvent = window->getEventQueue()->touchMoved(id, osgGA::GUIEventAdapter::TOUCH_MOVED, touchPoint.pos().x(), touchPoint.pos().y());
                }
            } else {
                osgEvent->addTouchPoint(id, osgGA::GUIEventAdapter::TOUCH_ENDED, touchPoint.pos().x(), touchPoint.pos().y());
                osgEvent->addTouchPoint(id, phase, touchPoint.pos().x(), touchPoint.pos().y());
            }
            id++;
        }
        break;
    }
    default:
        break;
    }
    return QOpenGLWidget::event(event);
}

void OsgViewerWidget::setKeyboardModifiers(QInputEvent *event)
{
    int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier);
    unsigned int mask = 0;
    if (modkey & Qt::ShiftModifier) {
        mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
    }
    if (modkey & Qt::ControlModifier) {
        mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
    }
    if (modkey & Qt::AltModifier) {
        mask |= osgGA::GUIEventAdapter::MODKEY_ALT;
    }

    window->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
    update();
}

void OsgViewerWidget::keyPressEvent(QKeyEvent *event)
{
    setKeyboardModifiers(event);
    window->getEventQueue()->keyPress(event->key());
    QOpenGLWidget::keyPressEvent(event);
    update();
}

void OsgViewerWidget::keyReleaseEvent(QKeyEvent *event)
{
    setKeyboardModifiers(event);
    window->getEventQueue()->keyRelease(event->key());
    QOpenGLWidget::keyReleaseEvent(event);
    update();
}

void OsgViewerWidget::mousePressEvent(QMouseEvent *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;
    case Qt::NoButton: button = 0; break;
    default: button = 0; break;
    }
    setKeyboardModifiers(event);
    window->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
    update();
    emit signal_clearWidget();
}

void OsgViewerWidget::mouseReleaseEvent(QMouseEvent *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;
    case Qt::NoButton: button = 0; break;
    default: button = 0; break;
    }
    setKeyboardModifiers(event);
    window->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);

    QOpenGLWidget::mouseReleaseEvent(event);
    update();
}

void OsgViewerWidget::mouseDoubleClickEvent(QMouseEvent *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;
    case Qt::NoButton: button = 0; break;
    default: button = 0; break;
    }
    setKeyboardModifiers(event);
    window->getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(), button);

    QOpenGLWidget::mouseDoubleClickEvent(event);
    update();
}

void OsgViewerWidget::mouseMoveEvent(QMouseEvent *event)
{
    setKeyboardModifiers(event);
    window->getEventQueue()->mouseMotion(event->x(), event->y());
    QOpenGLWidget::mouseMoveEvent(event);
    update();
}

void OsgViewerWidget::wheelEvent(QWheelEvent *event)
{
    setKeyboardModifiers(event);
    window->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);
    update();
}

void OsgViewerWidget::resizeEvent(QResizeEvent *event)
{
    const QSize& size = event->size();
    window->resized(x(), y(), size.width(), size.height());
    window->getEventQueue()->windowResize(x(), y(), size.width(), size.height());
    window->requestRedraw();

    QOpenGLWidget::resizeEvent(event);
}

void OsgViewerWidget::moveEvent(QMoveEvent *event)
{
    const QPoint& pos = event->pos();
    window->resized(pos.x(), pos.y(), width(), height());
    window->getEventQueue()->windowResize(pos.x(), pos.y(), width(), height());

    QOpenGLWidget::moveEvent(event);
}

void OsgViewerWidget::timerEvent(QTimerEvent *)
{
    update();
}

void OsgViewerWidget::paintGL()
{
    if (isVisibleTo(QApplication::activeWindow())) {
        frame();
    }
}

void OsgViewerWidget::init3D()
{
    setCamera(createCamera(0, 0, width(), height()));

    this->setCameraManipulator(new osgGA::TrackballManipulator);
//    this->addEventHandler(new osgViewer::StatsHandler);
//    this->addEventHandler(new osgViewer::ThreadingHandler());
//    this->addEventHandler(new osgViewer::HelpHandler);
//    this->addEventHandler(new osgGA::StateSetManipulator(this->getCamera()->getOrCreateStateSet()));
    this->setThreadingModel(osgViewer::Viewer::SingleThreaded);

    startTimer(10);
}

osg::ref_ptr OsgViewerWidget::createCamera(int x, int y, int w, int h)
{
    window = new osgViewer::GraphicsWindowEmbedded(x, y, w, h);
//    osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
    osg::ref_ptr traits = new osg::GraphicsContext::Traits;
    traits->windowDecoration = true;
    traits->x = x;
    traits->y = y;
    traits->width = w;
    traits->height = h;
    traits->doubleBuffer = true;
    traits->sharedContext = 0;

    osg::ref_ptr camera = new osg::Camera;
    camera->setGraphicsContext(window);
    camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
    camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    camera->setProjectionMatrixAsPerspective(
                30.0f, double(traits->width) / double(traits->height), 1.0f, 10000.0f);
    camera->setClearColor(osg::Vec4(0.3, 0.3, 0.6, 0.1));

    return camera.release();
}

 

入坑

入坑一:进去就当机

        

问题定位:

       定位是消息处理器中的指针问题

解决方法:

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第8张图片

入坑二:渲染窗口出现问题不对和球体横截面的问题

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第9张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第10张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第11张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第12张图片

解决方法:

       添加深度测试。

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第13张图片

        OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪_第14张图片

 

工程模板:对应版本号1.20.0

        对应版本号1.20.0


原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/98730328

你可能感兴趣的:(Qt开发专栏,OSG,OSG三维开发专栏)