QT中创建OSG项目运行实例

前记
一般osg在vs2019编译器运行,只要配置相应的环境就能正常运行,但是如果要在qt中运行需要自己手动配置类才能正常运行,以下是qt中运行osg的一个示例

1、创建QT项目

首先正常创建QT项目(这里用的是MSVC2019),然后进入mainwindow.ui界面设计页面,将OpenGlWidaet拖入页面:
在这里插入图片描述

2、配置OSG环境

请现在自己的电脑配置好osg的环境,并控制台确定osg可用,然后在.pro文件中引入os9,加入如下内容:

FORMS    += mainwindow.ui
INCLUDEPATH  += $${ROOT}\include
LIBS += $${ROOT}\lib\OpenThreadsd.lib
LIBS += $${ROOT}\lib\osgd.lib
LIBS += $${ROOT}\lib\osgDBd.lib
LIBS += $${ROOT}\lib\osgGAd.lib
LIBS += $${ROOT}\lib\osgQt5d.lib
LIBS += $${ROOT}\lib\osgTextd.lib
LIBS += $${ROOT}\lib\osgUtild.lib
LIBS += $${ROOT}\lib\osgViewerd.lib
QT += opengl

注意:ROOT = D:\SWEnvironment\OSG为自己电脑OSG所在位置,这个路径一定要对应上。

3、创建OSG类

也可以说是这个openGLWidget窗口的类,要想在这个窗口显示内容,需要为其创建一个单独的类,然后将这个窗口提升为这个类,即可,步骤如下:

1)创建openGLWidget类(名称可以自己随意设置,这里设置为openGLWidget)


在这里插入图片描述
在这里插入图片描述

然后一直下一步,直到创建完成;

2)创建完成后,设置"openglwidget.h"和"openglwidget.cpp"的内容

(1)openglwidget.h

#ifndef OSGVIEW_H
#define OSGVIEW_H
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgDB/ReadFile>
#include <QString>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QOpenGLWidget>
#include <QMainWindow>
#include <iostream>
class AdapterWidget : public QOpenGLWidget//QOpenGLWidget类是用于呈现OpenGL图形的小部件
{
public:
    AdapterWidget(QWidget *parent = 0, const char* name = 0, const QOpenGLWidget* shareWidget = 0,Qt::WindowFlags f = Qt::Widget);

    virtual ~AdapterWidget(){}

    osgViewer::GraphicsWindow* getGraphicsWindow()//应该是用于输出图像的
    {
        return mGw.get();
    }

    const osgViewer::GraphicsWindow* getGraphicsWidow()const//应该是多余的,没有调用到
    {
        return mGw.get();
    }
protected:
    virtual void resizeGL(int width, int height);//设置OpenGL视区、投影等,每当部件调整大小时,将会被调用
    virtual void keyPressEvent(QKeyEvent* event);//键盘按键事件
    virtual void keyReleaseEvent(QKeyEvent* event);//键盘释放事件
    virtual void mousePressEvent(QMouseEvent* event);//鼠标按键事件
    virtual void mouseReleaseEvent(QMouseEvent* event);//鼠标释放事件
    virtual void mouseMoveEvent(QMouseEvent* event);//鼠标移动事件
    virtual void wheelEvent(QWheelEvent* event);//滚轮事件

    //osg图形设备
    osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> mGw;//GraphicsWindowEmbedded提供了用于操作窗口设备的方法,同时拥有了处理事件的能力,当有事件发生时,可接收事件进行响应处理
};

class OpenGLWidget : public osgViewer::Viewer, public AdapterWidget
{
public:
    OpenGLWidget(QWidget * parent = 0, const char *name = 0, const QOpenGLWidget * shareWidget = 0, Qt::WindowFlags f = Qt::Widget);

    ~OpenGLWidget(){}

    virtual void paintGL();//渲染OpenGL场景,需要更新Widget时就会调用

protected:
    osg::Timer mTimer;//定义一个定时器,用来计算读取一个模型的时间(就是本项目运行后在控制台输出的那个时间)
    double mStrTime;
    double mEndTime;

    double mSleepTime;

    int num;
};

#endif // OSGVIEW_H

(2)openglwidget.cpp

#include "openglwidget.h"
#include <QDebug>



AdapterWidget::AdapterWidget(QWidget *parent, const char *name, const QOpenGLWidget *shareWidget, Qt::WindowFlags f)
{
    mGw = new osgViewer::GraphicsWindowEmbedded(this->x(), this->y(), width(), height());

    setFocusPolicy(Qt::ClickFocus);
}

//设置OpenGL视口,投影等。每当调整Widget的大小时(第一次显示窗口Widget时会调用它,因为所有新创建Widget都会自动获得调整大小的事件)
void AdapterWidget::resizeGL(int width, int height)
{
    mGw->getEventQueue()->windowResize(0, 0, width, height);
    mGw->resized(0, 0, width, height);

}

void AdapterWidget::keyPressEvent(QKeyEvent *event)
{
    mGw->getEventQueue()->keyPress((osgGA::GUIEventAdapter::KeySymbol) *(event->text().toUtf8().data()));
}

void AdapterWidget::keyReleaseEvent(QKeyEvent *event)
{
    mGw->getEventQueue()->keyRelease((osgGA::GUIEventAdapter::KeySymbol) *(event->text().toUtf8().data()));
}

void AdapterWidget::mousePressEvent(QMouseEvent *event)
{
    int button = 0;
    switch (event->button()) {
    case (Qt::LeftButton):
        button = 1;
        break;
    case (Qt::MiddleButton):
        button = 2;
        break;
    case (Qt::RightButton):
        button = 3;
        break;
    case (Qt::NoButton):
        button = 4;
        break;
    default:
        button = 0;
        break;
    }

    mGw->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
}

void AdapterWidget::mouseReleaseEvent(QMouseEvent *event)
{
    int button = 0;
    switch (event->button()) {
    case (Qt::LeftButton):
        button = 1;
        break;
    case (Qt::MiddleButton):
        button = 2;
        break;
    case (Qt::RightButton):
        button = 3;
        break;
    case (Qt::NoButton):
        button = 4;
        break;
    default:
        button = 0;
        break;
    }

    mGw->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);
}

void AdapterWidget::mouseMoveEvent(QMouseEvent *event)
{
    mGw->getEventQueue()->mouseMotion(event->x(), event->y());
}

void AdapterWidget::wheelEvent(QWheelEvent *event)
{
    mGw->getEventQueue()->mouseScroll(event->angleDelta().y() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN);
}



OpenGLWidget::OpenGLWidget(QWidget *parent, const char *name, const QOpenGLWidget *shareWidget, Qt::WindowFlags f) : AdapterWidget(parent, name, shareWidget, f)
{
    this->setMouseTracking(true);
    getCamera()->setViewport(new osg::Viewport(0, 0, width(), height()));
    getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(width()) / static_cast<double>(height()), 1.0f, 10000.0f);
    getCamera()->setGraphicsContext(getGraphicsWindow());
    setThreadingModel(osgViewer::Viewer::SingleThreaded);

    mStrTime = 0.0;
    mEndTime = 0.0;
    mSleepTime = 0.0;

    num = 0;
}

//渲染OpenGL场景,需要更新Widget时就会调用
void OpenGLWidget::paintGL()
{
    mStrTime = mTimer.tick();
    frame();
    num++;
    mEndTime = mTimer.tick();

    //计算睡眠所需时间
    mSleepTime = 1.0 / 60.0 - mTimer.delta_s(mStrTime, mEndTime);

    if(mSleepTime < 0){
        mSleepTime = 0.0;
    }

    //睡眠
    OpenThreads::Thread::microSleep(mSleepTime * 1000000);  //微秒
    Sleep(mSleepTime * 1000);                               //毫秒

    double mTime = mTimer.tick();

    //递归调用
    update();
}

3)OpenGLWidget窗口组件提升类

上面的类是定义一些基本操作,这样才能使OpenGLWidget这个窗口可用,类创建完成后,设置窗口,如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、初始化mainwindow

在一切就绪后,需要在主窗口初始化一下,这样才能让可视化的内容在OpenGLWidget窗口显示

1)在mainwindow.h中添加两个变量,如下

osg::ref_ptr<osg::Group> group;
osg::ref_ptr<osg::Geometry> geometry;//几何体对象,

注意:记得引入osg相关头文件包

2)mainwindow.cpp初始化

将主窗口与OpenGLWidget窗口双向绑定,在构造方法中加入一下内容:

 	QMainWindow * mw = new QMainWindow(this);
    mw->setWindowFlags(Qt::Widget);//设置窗口属性,如果继承QDialog,那窗口就只有关闭按钮,如果继承QWidget,那么就有关闭,最大化,最小化三个按钮

    geometry = NULL;

    group = new osg::Group;
    osg::StateSet *set = group->getOrCreateStateSet();
    set->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
    set->setAttributeAndModes(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);

    osgGA::TrackballManipulator *t;
    t = new osgGA::TrackballManipulator();
    t->setAllowThrow(false);//禁止持续动

    ui->openGLWidget = new OpenGLWidget(mw);
    ui->openGLWidget->setCameraManipulator(t);
    ui->openGLWidget->addEventHandler(new osgViewer::WindowSizeHandler);
    ui->openGLWidget->addEventHandler(new osgViewer::StatsHandler);

    ui->openGLWidget->setSceneData(group);
    mw->setCentralWidget(ui->openGLWidget);
    this->setCentralWidget(mw);

如下图:

这样大功告成了,只需要往group中添加节点就行,就可以正常显示了

5、测试

简单创建一个按钮进行测试,创建后转到槽


槽函数编写内容:加入一个飞机模型,然后运行

结果:

大功告成,可以正常按osg的思路编写代码了,如果需要更改键盘鼠标事件,可以再OpenGLWidget类中修改即可。

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值