
简介本资源为基于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界面交互开发提供直接支撑适合需要搭建OSGosgEarth技术栈的中高级开发者参考使用。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 的 QWidgetosgEarth 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_TYPERelease ^ -DCMAKE_INSTALL_PREFIXD:/dev/osg-3.7-install ^ -DBUILD_OSG_APPLICATIONSOFF ^ -DOSG_USE_UTF8_FILENAMEON ^ -DACTUAL_3RDPARTY_DIRD:/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_APPLICATIONSOFF关掉示例程序省一半编译时间。ACTUAL_3RDPARTY_DIR指向第三方库根目录里面要有 zlib、libpng、libjpeg、curl 这些 OSG 依赖x64 版本必须和 VS2019 的 MSVC 运行时一致。参数怎么改如果你要调试把CMAKE_BUILD_TYPE换成Debug但注意 Debug 和 Release 的第三方库不能混用MSVC 的_ITERATOR_DEBUG_LEVEL不一致会在链接期报错。OSG_USE_UTF8_FILENAMEON建议保持中文路径下读模型不容易乱码。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 6osgQt 大概率编不过因为 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_TYPERelease ^ -DCMAKE_INSTALL_PREFIXD:/dev/osgqt-install ^ -DOSG_DIRD:/dev/osg-3.7-install ^ -DQT_QMAKE_EXECUTABLED:/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 nameMyMap typegeocentric options cache typesqlite3 pathD:/osgearth_cache cache_policy usageread_write/ /cache /options /map逻辑说明cache typesqlite3告诉 osgEarth 用 sqlite3 做缓存后端path是缓存目录cache_policy usageread_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_DIRD:/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_LIBRARYMultiThreadedDLL和 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并且缓存目录按配置分开。这个习惯帮我省了至少两次通宵排查。希望帮到你。本文还有配套的精品资源点击获取