当前位置: 首页 > article >正文

QT+osg+osgearth显示一个地球(进阶)

        曾经我有一个版本,是用的别人的封装好的dll和lib,但是这样无法满足在liunx系统或者别的国产操作系统比如银河麒麟上跑这个程序。

        于是在网上查了很多资料,终于实现了我的需求,一般在其他系统上运行的osg+osgearth是比较好编译的,但是osgqt在osgearth3.0版本就没有了,在网上找了好久,终于找到了可以运行的源码,直接.h和.cpp的加入到项目中,这样就不影响在liunx系统上运行。

运行结果:

1.配置环境

QT版本:5.15.2   编译器:MSVC2019   64bit

编辑器:QT  Creator  大家也可以用vs2019或者2022一样的。

OSG版本3.6.5  x64   osg-earth3.0

2.库的导入

      我是在qt ceartor中以外部库的形式导入的,目前项目主要还是运行在win10系统上,pro文件

# GDAL 库
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../OSG3.6.5_X64/3rdparty/lib/ -lgdal_i
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../OSG3.6.5_X64/3rdparty/lib/ -lgdal_id
else:unix: LIBS += -L$$PWD/../OSG3.6.5_X64/3rdparty/lib/ -lgdal_i

INCLUDEPATH += $$PWD/../OSG3.6.5_X64/3rdparty/include
DEPENDPATH += $$PWD/../OSG3.6.5_X64/3rdparty/include


# OSG 核心库
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../OSG3.6.5_X64/osg365/lib/ -losg -losgViewer -losgDB -losgGA  -lOpenThreads -losgUtil -losgWidget   -losgAnimation  -losgFX  -losgManipulator  -losgParticle  -losgShadow  -losgSim  -losgTerrain  -losgText
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../OSG3.6.5_X64/osg365/lib/ -losgd -losgViewerd -losgDBd -losgGAd  -lOpenThreadsd  -losgUtild -losgWidgetd  -losgAnimationd  -losgFXd -losgManipulatord -losgParticled -losgShadowd -losgSimd -losgTerraind  -losgTextd
else:unix: LIBS += -L$$PWD/../OSG3.6.5_X64/osg365/lib/ -losg -losgViewer -losgDB -losgGA   -lOpenThreads  -losgUtil -losgWidget  -losgAnimation  -losgFX  -losgManipulator  -losgParticle  -losgShadow -losgSim -losgTerrain  -losgText

INCLUDEPATH += $$PWD/../OSG3.6.5_X64/osg365/include
DEPENDPATH += $$PWD/../OSG3.6.5_X64/osg365/include


# OSG-Earth 核心库
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../OSG3.6.5_X64/osgearth-3.2/lib/ -losgEarth
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../OSG3.6.5_X64/osgearth-3.2/lib/ -losgEarthd
else:unix: LIBS += -L$$PWD/../OSG3.6.5_X64/osgearth-3.2/lib/ -losgEarth

INCLUDEPATH += $$PWD/../OSG3.6.5_X64/osgearth-3.2/include
DEPENDPATH += $$PWD/../OSG3.6.5_X64/osgearth-3.2/include

3、添加三个关于osgqt的h和cpp

关于这三个文件的资源:通过网盘分享的文件:osgqt
链接: https://pan.baidu.com/s/1gvleKqNxgJnVC6uY4u1kDw 提取码: 6658 
--来自百度网盘超级会员v7的分享

找不到这个人写的文章衔接了,只好放自己的百度网盘。

4.界面

拖了一个widget进行栅格布局,这样球就是随着界面大小的变化而变化。

注意:不进行栅格布局会报错。

将osg的球嵌入到qt的一个界面中,跟qchart中的图表有些类似,都是需要一个widget进行装的而且需要进行布局,而不是直接使用的当前的ui界面。

如果继承的界面是QMainWindow,就不一样,QMainWindow有一个函数可以 this->setCentralWidget(osg_widget);

4、代码

.h

#ifndef AMAINWIDGET_H
#define AMAINWIDGET_H

#include <QWidget>
#include "osgqt/GraphicsWindowQt.h"

#include <QTimer>
#include <osgDB/ReadFile>
#include <osg/Group>
#include <osg/Node>
#include <osg/Camera>
#include <osg/PositionAttitudeTransform>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>

#include <osgEarth/MapNode>
#include <osgEarth/SpatialReference>

#include <osgEarth/GeoTransForm>
#include <osgEarth/GeoCommon>
#include <osgEarth/SpatialReference>
#include <osgEarth/EarthManipulator>
#include <osgEarth/Ephemeris>
#include <osgEarth/Sky>

#include <osgUtil/Tessellator>
#include <osgEarth/GLUtils>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/TexGen>

#include <QApplication>
#include <QDir>
#include <QString>

namespace Ui {
class amainWidget;
}

class amainWidget : public QWidget
{
    Q_OBJECT

public:
    explicit amainWidget(QWidget *parent = nullptr);
    ~amainWidget();

private:
    Ui::amainWidget *ui;

private:
    QTimer* _timer;		// 计时器,每5ms触发一次事件
    osgViewer::Viewer* viewer;
    osg::ref_ptr<osg::Group> root;
    osg::ref_ptr<osg::Camera> camera;
    osg::ref_ptr<osg::Node> earthNode;
    osg::ref_ptr<osgEarth::MapNode> mapNode;
    osg::ref_ptr <osg::MatrixTransform> earthForm;
    osg::ref_ptr<osgEarth::EarthManipulator> em;
    tm* t_tm;
    osgEarth::SkyNode* m_pSkyNode;
    time_t now_time;

private:
    void InitOSG();// 初始化设置osg
    void InitUI();//界面初始化
    void InitTimer();//屏幕刷新初始化
    void InitOsgearth();//初始化osgearth
    void InitSky();//天空初始化
private slots:
    // 定时更新帧的槽函数
    void updateFrame();

};

#endif // AMAINWIDGET_H

.cpp

#include "amainwidget.h"
#include "ui_amainwidget.h"

amainWidget::amainWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::amainWidget)
{
    ui->setupUi(this);
    InitOSG();
    InitOsgearth();
    InitUI();
    InitTimer();

}

amainWidget::~amainWidget()
{
    delete ui;
}

void amainWidget::InitOSG()// 初始化设置osg
{
    viewer = new osgViewer::Viewer;
    // 设置模型
    root = new osg::Group;


    QString exeDir = QCoreApplication::applicationDirPath();
    QDir::setCurrent(exeDir);
    // 显示 .earth 文件中的地球模型

        // 使用相对于exe的相对路径来构建.earth文件的完整路径

    earthNode = new osg::Node;

    QString relativeEarthFilePath = "Maps/ocean.earth";  // 请替换为你实际的.earth文件相对路径
    QString earthFilePath = exeDir + "/" + relativeEarthFilePath;
   // QString earthFilePath ="./simple.earth";
    earthNode = osgDB::readNodeFile(earthFilePath.toStdString());

    //获取屏幕分辨率 长宽
    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
    if (!wsi)
        return;
    unsigned int width, height;
    wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);
    //设置图形环境特性
    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
    traits->windowDecoration = false;//声明是否显示窗口的描述
    traits->x = 0;
    traits->y = 0;
    traits->width = width;
    traits->height = height;
    traits->doubleBuffer = true;//创建图形窗口是否使用双缓存

    //设置照相机
    camera = new osg::Camera;
    camera->setGraphicsContext(new osgQt::GraphicsWindowQt(traits.get()));
    camera->setClearColor(osg::Vec4(0.2, 0.2, 0.6, 1.0));
    camera->setViewport(new osg::Viewport(0, 0, width, height));
    camera->setProjectionMatrixAsPerspective(30.0f, (double(traits->width)) / (double(traits->height)), 1.0f, 10000.0f);

    //设置渲染器
    viewer->setCamera(camera);
    viewer->setSceneData(root);
    viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);//创建为单线程
    viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
}
void amainWidget::InitOsgearth()
{
    //mapnode初始化
    mapNode = osgEarth::MapNode::findMapNode(earthNode .get());
    earthForm = new osg::MatrixTransform;
    //osgearth操作器
    em = new osgEarth::Util::EarthManipulator;
    if (mapNode.valid())
    {
        em->setNode(mapNode);
    }

    em->getSettings()->setArcViewpointTransitions(true);
    viewer->setCameraManipulator(em);

//    //获取地球半径 设置视点
 //   double earth_R = mapNode->getMap()->getSRS()->getEllipsoid()->getRadiusEquator();
   // const char* viewPointName = QString::fromLocal8Bit("北京").toStdString().c_str();
   //                                 em->setViewpoint(osgEarth::Viewpoint(viewPointName, 112.44, 33.75, 0.0, 0.0, -90.0, 5 * earth_R), 5);
   // 初始化天空
    InitSky();
}
void amainWidget::InitSky()
{
    //获取当前时间 初始化天空
    now_time = time(0);
    t_tm = localtime(&now_time);
    osgEarth::DateTime cur_date_time(now_time);
    osgEarth::Ephemeris* ephemeris = new osgEarth::Ephemeris;

    //设置黑夜明暗程度
    osgEarth::Util::SkyOptions skyOptions;
    skyOptions.ambient() = 0.3;

    m_pSkyNode = osgEarth::SkyNode::create(skyOptions);
    m_pSkyNode->setName("SkyNode");
    m_pSkyNode->setEphemeris(ephemeris);
    m_pSkyNode->setDateTime(cur_date_time);
    viewer->setLightingMode(osg::View::SKY_LIGHT);
    m_pSkyNode->attach(viewer, 0);
    m_pSkyNode->setLighting(true);

    m_pSkyNode->addChild(mapNode);
    root->addChild(m_pSkyNode);

}
void amainWidget::InitUI()//界面初始化
{
//    // ui布局
//    osgQt::GraphicsWindowQt* gw = dynamic_cast<osgQt::GraphicsWindowQt*>(camera->getGraphicsContext());
//    QWidget* osg_widget = (QWidget*)(gw->getGLWidget());
//    this->setCentralWidget(osg_widget);
//    //窗口最大化
//    this->setWindowState(Qt::WindowMaximized);
//    this->setWindowTitle(QString::fromLocal8Bit("数字地球"));

    // 获取 OSG 的 QWidget
    osgQt::GraphicsWindowQt* gw = dynamic_cast<osgQt::GraphicsWindowQt*>(camera->getGraphicsContext());
    QWidget* osg_widget = (QWidget*)(gw->getGLWidget());

    // 创建一个布局管理器
    QVBoxLayout* layout = new QVBoxLayout(this->ui->widget);  // 使用当前窗口作为父对象
    layout->setContentsMargins(0, 0, 0, 0);       // 设置边距为 0
    layout->addWidget(osg_widget);                // 将 osg_widget 添加到布局中

    // 应用布局到当前窗口
    this->setLayout(layout);

    // 设置窗口标题和状态
    this->setWindowState(Qt::WindowMaximized);
    this->setWindowTitle(QString::fromLocal8Bit("数字地球"));
}
void amainWidget::InitTimer()//屏幕刷新初始化
{
    _timer = new QTimer;
    QObject::connect(_timer, SIGNAL(timeout()), this, SLOT(updateFrame()));
    _timer->start(10);

}
void amainWidget::updateFrame()
{

    viewer->frame();
}

5.遇到的问题

我准备在6版本编译osgqt的文件,发现编译不通过。

我询问了chatgpt

6.5.3版本,#include <QtOpenGL/QGLWidget>为什么找不到这个资源

chatgpt给的回答是:

在 Qt 6.5.3 中,<QtOpenGL/QGLWidget> 不再可用,因为 Qt 已经对 OpenGL 的支持进行了重构。QGLWidget 属于 Qt 4 和 Qt 5 的 OpenGL 支持模块,而在 Qt 6 中,该模块被移除,推荐使用更现代的 OpenGL 支持类,例如 QOpenGLWidgetQOpenGLWindow

估计有什么头文件或者调用的opengl什么的需要修改一下。


http://www.kler.cn/a/404856.html

相关文章:

  • [Realtek sdk-3.4.14b] RTL8197FH-VG新增jffs2分区操作说明
  • Elasticsearch面试内容整理-实践与应用场景
  • Java-05 深入浅出 MyBatis - 配置深入 动态 SQL 参数、循环、片段
  • 【每日 C/C++ 问题】
  • 如何理解Lua 使用虚拟堆栈
  • AI一键生成原创花卉印花图案——创新与效率的结合
  • 《Java核心技术 卷I》链表
  • 多目标优化算法:多目标吸血水蛭优化算法(MOBSLO)求解DTLZ1-DTLZ9,提供完整MATLAB代码
  • 集合卡尔曼滤波(Ensemble Kalman Filter),用于二维滤波(模拟平面上的目标跟踪),MATLAB代码
  • 机器学习——数据隐私与安全学习
  • 排序算法:直接插入排序,希尔排序,选择排序,快速排序,堆排序,归并排序
  • 【IEEE独立出版 |往届均已成功检索】第八届大数据与应用统计国际学术研讨会(ISBDAS 2025)
  • C#核心(10)拓展方法
  • 机器学习:智能技术的未来
  • Vue_Router权限控制:不同角色显示不同路由
  • MySQL基础大全(看这一篇足够!!!)
  • 解决.DS_Store 在项目一致无法排除,.gitignore里也不生效
  • C++ 网络编程:打造多线程 TCP 服务器,同时服务多个客户机!
  • Qt-常用的按钮控件 QPushButton QRadioButton QCheckBox
  • Kadane 算法 二维 详解
  • 如何创建一个网站?初学者的分步指南
  • 【Apache Paimon】-- 5 -- Flink 向 Paimon 表写入数据
  • 网络编程day2.2~day3——TCP并发服务器
  • TCP Listen 队列详解与优化指南
  • springboot基于大数据技术的电影推荐系统的设计与实现
  • 区块链预言机;预言机的部署、与智能合约的关系以及是否分布式;基于Fabric联盟链与链外世界的数据交互