news 2026/10/12 21:50:54

VS2019 x64 编译 OpenSceneGraph 3.7 + osgEarth 3.4 工具链实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
VS2019 x64 编译 OpenSceneGraph 3.7 + osgEarth 3.4 工具链实战

简介:本资源为基于VS2019编译的x64 OpenSceneGraph 3.7、osgEarth 3.4、osgQt、SQLite3及GDAL 3.0.4的完整开发环境包,面向从事三维地理空间应用、虚拟仿真与GIS开发的C++工程师。它解决了多开源组件在64位Windows平台下的集成与兼容问题,省去从源码逐一编译配置的繁琐过程。压缩包共约2000个文件,以1122个hpp与878个h头文件为主,涵盖OSG、osgEarth、osgQt、SQLite、GDAL及FFmpeg等模块的接口声明,便于二次开发时直接引用与调试。包体约727.48MB,内容完整。目前已有123人学习下载。借助该资源,读者可快速获得一套可用的三维渲染与地理数据处理基础环境,理解各组件间的依赖关系与头文件组织方式,为地图集成显示、空间数据读写及Qt界面交互开发提供直接支撑,适合需要搭建OSG+osgEarth技术栈的中高级开发者参考使用。

1. 从 VS2019 编译 x64 OpenSceneGraph3.7 说起:一套能跑起来的 osgEarth 3.4 工具链长什么样

如果你手上有一个 VS2019 的 x64 工程,需要把 OpenSceneGraph 3.7、osgEarth 3.4、osgQt 和 sqlite3 串成一条能出 Release 的链路,同时还要接上 GDAL 3.0.4 读地理数据,那你大概率已经体会过这套组合的“玄学”之处:单独编 OSG 能过,单独编 osgEarth 能过,一旦把 osgQt 和 sqlite3 塞进去,链接期就开始报一堆找不到符号。这篇笔记不讲空泛概念,只讲我在 VS2019 下把这条 x64 工具链从零编到 Release 可用的完整路径,包括依赖顺序、CMake 参数、第三方库版本对齐,以及几个让我返工两次的坑。适合已经会写 C++、但第一次碰 OSG 全家桶的图形/GIS 方向从业者,也适合被 1603 安装错误和运行库缺失折腾过、想一次性把环境理顺的人。

2. 依赖顺序与版本对齐:为什么 OSG 3.7 必须排在 osgEarth 3.4 前面

2.1 四个库的依赖关系不是线性的

很多人以为 OpenSceneGraph、osgEarth、osgQt、sqlite3 是四个平级库,随便什么顺序编都行。实际依赖是分层的:OSG 3.7 是根,它提供 osg、osgDB、osgViewer、osgUtil 这些核心模块;osgQt 是 OSG 的可选扩展,把 osgViewer 嵌进 Qt 的 QWidget;osgEarth 3.4 同时依赖 OSG 和 GDAL,用来做地理坐标投影和瓦片调度;sqlite3 则是 osgEarth 内部缓存和部分数据源要用的嵌入式数据库。所以正确顺序是:先 sqlite3(静态库即可),再 OSG 3.7,再 osgQt,最后 osgEarth 3.4。顺序错了,CMake 的 find_package 会找不到 OSG 的 config 文件,osgEarth 直接配置失败。

2.2 版本对齐比版本新更重要

标题里写的是 OpenSceneGraph3.7、osgEarth-3.4、GDAL 3.0.4,这三个版本是能对上的。我试过用 OSG 3.6.5 配 osgEarth 3.4,编译能过,但运行到 osgEarth 的 TileSource 初始化时会崩,原因是 osgEarth 3.4 内部用了 OSG 3.7 才稳定的某个 osgDB 回调接口。GDAL 3.0.4 对应的是 release-1911-x64 这个预编译包,它和 osgEarth 3.4 的 GDAL 驱动层是匹配的。如果你手头是 GDAL 3.4 或更高,osgEarth 3.4 的 gdal 插件在读取某些坐标系时会返回空指针,这个后面避坑章节会细说。

2.3 用 CMake 生成 VS2019 x64 工程的最小命令

下面这段是我在 Windows 上编 OSG 3.7 时用的 CMake 命令,x64 和 Release 都显式指定,避免默认生成 Win32 工程:

cmake -S . -B build-vs2019-x64 ^ -G "Visual Studio 16 2019" -A x64 ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_INSTALL_PREFIX=D:/dev/osg-3.7-install ^ -DBUILD_OSG_APPLICATIONS=OFF ^ -DOSG_USE_UTF8_FILENAME=ON ^ -DACTUAL_3RDPARTY_DIR=D:/dev/3rdparty-x64

逻辑说明:-G "Visual Studio 16 2019" -A x64是生成 VS2019 的 64 位解决方案,少了-A x64就会变成 Win32,后面链接 GDAL 的 x64 库会直接报模块计算机类型冲突。CMAKE_INSTALL_PREFIX指向一个独立目录,方便 osgEarth 用OSG_DIR找到它。BUILD_OSG_APPLICATIONS=OFF关掉示例程序,省一半编译时间。ACTUAL_3RDPARTY_DIR指向第三方库根目录,里面要有 zlib、libpng、libjpeg、curl 这些 OSG 依赖,x64 版本必须和 VS2019 的 MSVC 运行时一致。

参数怎么改:如果你要调试,把CMAKE_BUILD_TYPE换成Debug,但注意 Debug 和 Release 的第三方库不能混用,MSVC 的_ITERATOR_DEBUG_LEVEL不一致会在链接期报错。OSG_USE_UTF8_FILENAME=ON建议保持,中文路径下读模型不容易乱码。

2.4 编译和安装的收尾动作

CMake 生成后,用 VS2019 打开build-vs2019-x64/OpenSceneGraph.sln,配置选 Release + x64,先编ALL_BUILD,再编INSTALL。INSTALL 会把头文件、lib、dll 拷到CMAKE_INSTALL_PREFIX。这一步别偷懒只编 ALL_BUILD,否则 osgEarth 配置时找不到osg-config.cmake。编完检查D:/dev/osg-3.7-install/lib下有没有osg.lib、osgDB.lib、osgViewer.lib,以及bin下有没有对应的 dll。缺哪个,后面 osgEarth 就会在哪个模块上报错。

3. osgQt 与 sqlite3 的接入:把 QWidget 嵌进 OSG 视图并让 osgEarth 能写缓存

3.1 osgQt 的定位和编译前提

osgQt 不是 OSG 官方核心模块,它是社区维护的 Qt 适配层。VS2019 下编 osgQt 之前,本机必须已经装好 Qt 5.12 或 Qt 5.15 的 x64 MSVC 版本,并且QTDIR环境变量指向 Qt 安装根目录。osgQt 的 CMake 会去找Qt5Widgets、Qt5OpenGL这些组件。如果你用的是 Qt 6,osgQt 大概率编不过,因为 Qt 6 移除了部分 OpenGL 模块的旧接口。我一般用 Qt 5.15.2 + MSVC2019 64bit 这套组合,和 VS2019 的 ABI 一致。

3.2 编译 osgQt 的关键参数

cmake -S . -B build-osgqt-x64 ^ -G "Visual Studio 16 2019" -A x64 ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_INSTALL_PREFIX=D:/dev/osgqt-install ^ -DOSG_DIR=D:/dev/osg-3.7-install ^ -DQT_QMAKE_EXECUTABLE=D:/Qt/5.15.2/msvc2019_64/bin/qmake.exe

逻辑说明:OSG_DIR指向上一步 OSG 的安装目录,osgQt 靠它找 osgViewer 的头和库。QT_QMAKE_EXECUTABLE显式指定 qmake 路径,避免 CMake 找到系统里其他版本的 Qt。编完后osgqt-install下会有osgQt.lib和osgQt.dll,以及QGraphicsViewAdapter这些头文件。

参数怎么改:如果你的 Qt 装在 C 盘,把 qmake 路径换掉即可。注意 osgQt 的 Release 库只能配 Release 的 Qt 库,Debug 配 Debug,混用会在运行时报QWidget: Cannot create a QWidget without QApplication之类的假象错误,实际是运行时库冲突。

3.3 sqlite3 的编译与 osgEarth 缓存配置

sqlite3 我一般直接下 sqlite-amalgamation 的源码包,里面就一个sqlite3.c和一个sqlite3.h。在 VS2019 里新建一个静态库工程,把sqlite3.c加进去,预处理器加SQLITE_ENABLE_RTREE和SQLITE_ENABLE_COLUMN_METADATA,编成 x64 Release 的sqlite3.lib。osgEarth 3.4 的缓存机制默认用 sqlite3 存瓦片索引,如果不编这个库,osgEarth 配置时会提示找不到 sqlite3,然后缓存功能被禁用,跑起来每次都要重新请求数据。

// 在 osgEarth 的 earth 文件里显式指定缓存类型 <map name="MyMap" type="geocentric"> <options> <cache type="sqlite3" path="D:/osgearth_cache"> <cache_policy usage="read_write"/> </cache> </options> </map>

逻辑说明:cache type="sqlite3"告诉 osgEarth 用 sqlite3 做缓存后端,path是缓存目录,cache_policy usage="read_write"允许读写。如果 sqlite3 没编好,这里会退化成内存缓存,程序一关数据就没了。参数怎么改:path建议放在 SSD 上,瓦片多的时候 IO 是瓶颈;usage可以改成read_only做只读部署。

3.4 把 osgQt 的 QWidget 嵌进 osgEarth 视图

osgQt 提供osgQOpenGLWidget,可以直接当 Qt 控件用。下面这段是把它和 osgEarth 的 Viewer 接起来的最小代码:

#include <osgQOpenGL/osgQOpenGLWidget> #include <osgEarth/MapNode> #include <osgEarth/EarthManipulator> #include <osgViewer/Viewer> // 创建 osgQt 的 OpenGL 控件 osgQOpenGLWidget* glWidget = new osgQOpenGLWidget(this); QVBoxLayout* layout = new QVBoxLayout(centralWidget); layout->addWidget(glWidget); // 在控件初始化完成后拿到 Viewer connect(glWidget, &osgQOpenGLWidget::initialized, [=]() { osgViewer::Viewer* viewer = glWidget->getOsgViewer(); osg::Node* earthNode = osgDB::readNodeFile("D:/data/earthfile.earth"); viewer->setSceneData(earthNode); viewer->setCameraManipulator(new osgEarth::Util::EarthManipulator); viewer->setCameraManipulator(new osgEarth::Util::EarthManipulator); });

逻辑说明:osgQOpenGLWidget在initialized信号发出后才真正创建 OpenGL 上下文,所以 Viewer 的获取必须放在这个信号回调里,提前拿会得到空指针。readNodeFile读.earth文件,osgEarth 会自动解析里面的影像、高程、矢量图层。EarthManipulator是 osgEarth 专用的相机操作器,比 OSG 默认的 TrackballManipulator 更适合地理场景。参数怎么改:.earth文件路径换成你自己的;如果要做多视图,可以创建多个osgQOpenGLWidget,但每个都要独立 Viewer,共享 SceneData 时注意线程安全。

4. 避坑与排查:VS2019 编译 osgEarth 3.4 时最常见的 5 个翻车点

4.1 现象:CMake 配置 osgEarth 时报 “Could NOT find OSG”

原因:OSG_DIR没设,或者指向的目录里没有osg-config.cmake。很多人编完 OSG 只编了 ALL_BUILD,没编 INSTALL,导致安装目录是空的。解决:回到 OSG 的 build 目录,用 VS2019 编 INSTALL 目标,确认OSG_DIR下有lib/cmake/osg或share/osg这类 config 文件。然后在 osgEarth 的 CMake 命令里显式加-DOSG_DIR=D:/dev/osg-3.7-install。

4.2 现象:链接 osgEarth 时大量 “无法解析的外部符号 __imp_xxx”

原因:GDAL 的库和 osgEarth 的编译选项不匹配。release-1911-x64-gdal-3-0-4 这个包里的 GDAL 是用特定 MSVC 运行时编的,如果你的 osgEarth 用了不同的_ITERATOR_DEBUG_LEVEL或RuntimeLibrary,符号就对不上。解决:在 osgEarth 的 CMake 里加-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL,和 GDAL 预编译包保持一致。同时确认 GDAL 的include和lib路径都加进了CMAKE_PREFIX_PATH。

4.3 现象:运行时报 “microsoft visual c++ 2015-2022 redistributable (x64)” 缺失

原因:VS2019 编出来的 exe 依赖 VC++ 运行时,目标机器没装。解决:在开发机装一遍VC_redist.x64.exe,或者把vcruntime140.dll、msvcp140.dll随程序一起拷。注意 osgEarth 和 GDAL 可能还依赖concrt140.dll,用 Dependency Walker 或dumpbin /dependents查一遍,缺什么补什么。

4.4 现象:osgQt 的 QWidget 显示黑屏,但 OSG 单独跑正常

原因:Qt 的 OpenGL 上下文和 OSG 的渲染线程冲突。osgQOpenGLWidget 默认用自己的渲染线程,如果 Qt 主线程也在操作 OpenGL,就会黑屏。解决:在main函数里设QSurfaceFormat format; format.setVersion(3,3); format.setProfile(QSurfaceFormat::CoreProfile); QSurfaceFormat::setDefaultFormat(format);,并且不要在 Qt 主线程里直接调 OSG 的frame()。让 osgQOpenGLWidget 自己驱动渲染循环。

4.5 现象:osgEarth 读 GDAL 数据时崩溃,报 “GDALDataset::GetProjectionRef” 空指针

原因:GDAL 3.0.4 的某些驱动在读取没有投影信息的 tif 时会返回空,osgEarth 3.4 没做空判断。解决:在.earth文件里给图层显式指定profile,或者用gdal_translate给数据补上投影信息。如果只是测试,可以在 osgEarth 的 GDAL 插件源码里加一行空指针判断,但更稳妥的做法是预处理数据。

5. 进阶技巧:用 CMake 的 find_package 把整条链路固化进工程

5.1 写一个能复用的 CMakeLists.txt

与其每次手动配路径,不如把 OSG、osgEarth、osgQt、sqlite3 的查找逻辑写进工程的CMakeLists.txt,这样换机器只要改CMAKE_PREFIX_PATH就行。

cmake_minimum_required(VERSION 3.15) project(OsgEarthDemo LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") # 把四个库的安装根目录加进搜索路径 list(APPEND CMAKE_PREFIX_PATH "D:/dev/osg-3.7-install" "D:/dev/osgqt-install" "D:/dev/osgearth-3.4-install" "D:/dev/sqlite3-install" ) find_package(OpenSceneGraph 3.7 REQUIRED COMPONENTS osg osgDB osgViewer osgUtil) find_package(osgEarth 3.4 REQUIRED) find_package(osgQt REQUIRED) find_package(SQLite3 REQUIRED) add_executable(OsgEarthDemo main.cpp) target_link_libraries(OsgEarthDemo PRIVATE ${OSG_LIBRARIES} ${OSGEARTH_LIBRARIES} ${OSGQT_LIBRARIES} SQLite::SQLite3 )

逻辑说明:CMAKE_PREFIX_PATH是 CMake 找 config 文件的根目录列表,把四个安装目录都列进去,find_package就能自动定位。COMPONENTS指定要用的 OSG 模块,不写全的话链接期会缺库。CMAKE_MSVC_RUNTIME_LIBRARY统一运行时,避免和 GDAL 预编译包冲突。参数怎么改:路径换成你自己的安装目录;如果 osgEarth 的 config 文件名不是osgEarthConfig.cmake,用find_package(osgEarth CONFIG REQUIRED)显式指定 CONFIG 模式。

5.2 验证整条链路的三个检查点

编完 exe 后,别急着跑复杂场景。先做三个检查:第一,用dumpbin /dependents OsgEarthDemo.exe看依赖的 dll 是否都在PATH或 exe 同目录;第二,跑一个只加载空.earth文件的用例,确认 osgEarth 的插件能初始化;第三,加载一个带影像和高程的.earth,用osgEarth::Util::EarthManipulator转一下视角,看瓦片是否正常调度。这三个过了,再上 osgQt 的界面集成。

5.3 我踩过的一个“后悔药”级教训

早期我图省事,把 OSG、osgEarth、osgQt 全编成 Debug,想着调试方便。结果 Release 发布时重新编了一遍,发现 osgEarth 的缓存路径在 Debug 和 Release 下行为不一致,Debug 下能读的 sqlite3 缓存在 Release 下报 “database is locked”。后来我养成习惯:第三方库统一编 Release,自己的业务代码才分 Debug/Release,并且缓存目录按配置分开。这个习惯帮我省了至少两次通宵排查。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 21:43:43

匹配滤波与线性调频脉冲压缩:雷达信号处理仿真实现

简介&#xff1a;匹配滤波是雷达脉冲压缩和线性调频信号处理中的核心环节&#xff0c;其增益计算与归一化系数的正确设置直接影响系统性能。这份Matlab仿真资源包面向对雷达信号处理感兴趣的工程与研究人员&#xff0c;围绕LFM信号的匹配滤波增益、白噪声增益及归一化系数展开推…

作者头像 李华
网站建设 2026/10/12 21:43:19

BRT智能系统通信接口国标解读:GB/T 31455.5-2025落地实践与联调经验

做BRT项目的人应该都有这种体会&#xff1a;每次做接口对接&#xff0c;最耗精力的不是功能逻辑本身&#xff0c;而是大家对不上话。车载终端厂家说自己的私有协议&#xff0c;站台信息屏又是另一套格式&#xff0c;调度中心再整一个中间库&#xff0c;三方联调全靠开发熬夜改报…

作者头像 李华
网站建设 2026/10/12 21:37:56

灾备选型新标准:核心自研与数据格式控制成破局关键

上个月参与某制造集团的灾备系统集中选型&#xff0c;技术评审第一个问题不是备份速度&#xff0c;也不是费用&#xff0c;而是&#xff1a;你们备份软件的核心引擎&#xff0c;是自己研发的&#xff0c;还是集成了第三方组件&#xff1f;如果这个答案含糊&#xff0c;后面基本…

作者头像 李华
网站建设 2026/10/12 21:36:54

基于Python的电信客户流失预测:从数据清洗到SHAP可解释性分析

简介&#xff1a;这份资源是面向高校学生与数据挖掘初学者的电信客户流失预测与分析完整项目源码&#xff0c;可作为数据挖掘课程期末大作业、课程设计或自学练手使用。项目基于Python实现&#xff0c;围绕电信用户流失这一典型分类场景&#xff0c;涵盖数据预处理、特征降维、…

作者头像 李华
网站建设 2026/10/12 21:35:16

Open Code Review:从公开权限到开放协作的工程实践体系

1. 项目概述&#xff1a;这不是代码审查工具&#xff0c;而是一套可落地的开源协作实践体系“open-code-review”这个名称乍看像某个新发布的开源工具&#xff0c;但实际它代表的是一类正在快速演进的工程实践范式——把代码审查&#xff08;Code Review&#xff09;这件事&…

作者头像 李华
网站建设 2026/10/12 21:34:10

嵌入模型(Embedding)彻底吃透:原理、选型、接入与 RAG 实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华