ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Windows下VS2019编译OSG 3.7与osgEarth 3.4 x64实战详解

Windows下VS2019编译OSG 3.7与osgEarth 3.4 x64实战详解 简介这份压缩包围绕VS2019环境下x64平台OpenSceneGraph 3.7、osgearth-3.4、osgQt、SQLite以及GDAL 3.0.4集成编译的开发资源面向需要搭建三维地理空间渲染与GIS数据处理环境的C开发者。包内共含2000个文件其中1122个为hpp、878个为h均为C/C头文件用于声明各库的接口、数据结构与宏定义是二次开发和编译链接时不可或缺的依赖基础压缩包整体约727.48MB便于直接部署或作为离线对照。对希望将OSG三维场景嵌入Qt界面同时处理地形影像、矢量数据并管理空间数据库的开发者这套针对release-1911的编译产物能显著减少组件整合与版本兼容排查的时间尤其适合具有C基础、正在配置OSG与osgearth开发链路的工程人员。这些头文件覆盖了场景图管理、地理数据解析、数据库访问与图像处理等核心模块为后续功能扩展提供了清晰结构。目前已有123人学习下载可在编写自定义节点、扩展GIS渲染功能时代为参考。1. 为什么 VS2019 编译 x64 的 OpenSceneGraph 3.7 osgEarth 3.4 要先搞定版本契约一套 Windows x64 的 OpenSceneGraph 3.7 osgEarth 3.4 渲染栈真正难的不是写代码而是把 Qt5、GDAL 3.0.4、SQLite 这些外部库按“同一个版本契约”拧在一起。OpenSceneGraph 3.7 把 osgQt 集成方式改了osgEarth 3.4 在 CMake 探测阶段又对 GDAL 版本很敏感任何一环选错位数或混用 Debug/Release结果必然是编译期秒过、运行期崩溃。这篇文章按我在 VS2019 下从源码编译这条 64 位链路的完整过程展开覆盖 CMake 参数、安装前缀、PATH 顺序和四类典型排障适合做 GIS 三维可视化和离线地形渲染、又被 Windows 依赖库折腾过的 C 开发者。2. 编译前准备把 Qt5、GDAL 3.0.4、SQLite 的 x64 版本契约先定下来2.1 统一依赖根目录DLL 最终落在哪现在就要决定在 Windows 上编译这种多层依赖栈最忌讳的就是每个库散落在不同盘符、不同命名规则的目录里。CMake 的find_package机制确实能自动搜但一旦搜到错的版本排错成本远高于一开始就统一路径。我一般在一台干净机器上建一个根目录所有第三方库按固定结构放进去避免后续 PATH 和 CMake 变量写成一团乱麻。常见的目录规划是C:\geo\ OSG\ # OSG 3.7 的安装前缀 osgEarth\ # osgEarth 3.4 的安装前缀 thirdparty\ Qt5\ # Qt 5.15.2 msvc2019_64 gdal-3.0.4\ # GDAL 3.0.4 x64 sqlite\ # SQLite release-1911 x64 build\ build-OSG\ build-osgEarth\ src\ OpenSceneGraph\ osgearth\源码和构建目录分开是 CMake 的标配做法。源码目录保持干净build 目录可以随时删掉重来不会污染源文件。安装前缀统一放在C:\geo\下后面 osgEarth 找 OSG、osgearth_qt 找 Qt 插件全都能按相对路径推理出来。PATH 的规划比编译更早一步编译完以后运行 osgearth 的 exe 需要同时找到 OSG、osgEarth、Qt、GDAL、SQLite 五套 DLL。我通常在编译前就把 PATH 写好放到一个env.bat里每次开新终端先执行一遍避免“编译过了但跑不起来”这种最尴尬的场景。set PATHC:\geo\OSG\bin;C:\geo\osgEarth\bin;C:\geo\thirdparty\Qt5\bin;C:\geo\thirdparty\gdal-3.0.4\bin;C:\geo\thirdparty\sqlite;%PATH% set OSG_LIBRARY_PATHC:\geo\OSG\bin\osgPlugins-3.7.0;C:\geo\osgEarth\bin\osgPlugins-3.7.0 set GDAL_DATAC:\geo\thirdparty\gdal-3.0.4\gdal-data这里OSG_LIBRARY_PATH是指向插件目录的关键变量。OpenSceneGraph 的插件机制默认从 exe 所在目录的osgPlugins-3.7.0子目录找插件但当你把 osgEarth 的插件也放在另一个安装前缀里时不显式指路就找不到。GDAL_DATA则是 GDAL 读取 GeoTIFF 等格式时的数据文件目录少了它GDAL 打开文件会报 “xxx driver not registered”。2.2 Qt5 msvc2019_64 与 GDAL/SQLite 的 x64 选型Qt 版本必须和 VS2019 工具集严格对应。VS2019 对应 MSVC v142官方 Qt 二进制包里要选msvc2019_64那一套。如果误用 MinGW 版CMake 能识别 Qt 组件但链接阶段会出现大量无法解析的外部符号因为两者的 C ABI 根本不通。Qt 5.15.2 是最后一个支持 Win7 的 LTS对老项目兼容性好也可以用 5.15.x 系列里更新一点的补丁版。GDAL 这边标题里写死 3.0.4 是有道理的。osgEarth 3.4 发布时主要对 GDAL 2.4 到 3.0 这一代做适配GDAL 3.0 把 C 接口里不少函数签名做了调整osgEarth 3.4 的 CMake 探测逻辑和源码里的#include都是按这一代接口写的。我见过有人直接拿 GDAL 3.6 去配 osgEarth 3.4结果OGRCoordinateTransformation::CreateCoordinateTransformation这类接口在链接时没问题运行时却因为 GDAL 内部的 PROJ 版本升级而崩溃。所以能锁定 3.0.4 就不要升级除非你愿意同步给 osgEarth 打补丁。SQLite 的release-1911-x64是某个固定发布的打包版本标记它对应 SQLite 3.31 时代。对 osgEarth 来说SQLite 只是为了落地它的本地缓存文件和模型数据库对版本不敏感但必须提供三样东西sqlite3.h头文件、sqlite3.lib导入库、sqlite3.dll运行库。这三者必须是同一次编译的产物不能头文件来自 A 包、lib 来自 B 包。预编译包拿回来以后先看一眼sqlite3.dll的位数用dumpbin /headers sqlite3.dll确认是 x64别到最后才发现给 32 位程序灌了 64 位库。2.3 CMake 与 VS2019 生成器避免 Win32 默认值VS2019 的 CMake 生成器名称是Visual Studio 16 2019。命令行里必须加上-A x64否则 CMake 默认生成 Win32 平台后面 OSG、osgEarth 全都会以 32 位编译等你把 64 位 GDAL 的 lib 链接进去时直接报LNK1112: module machine type x86 conflicts with target machine type x64。CMake 版本建议用 3.20 以上。太老的 CMake 对 Qt5 的qt5_use_modules宏和 osgEarth 的osgEarthConfig.cmake支持都不完整会漏掉一些依赖检测。VS2019 社区版足够不需要激活也不需要网上找什么产品密钥安装时勾选“使用 C 的桌面开发”工作负载确保 MSVC v142 工具集和 Windows 10 SDK 都装上就行。这里有个经验不要用 CMake GUI 手动翻选项复杂项目一次要设几十个变量GUI 勾完根本记不住改了什么。把配置命令写成.bat脚本后续换机器、升级依赖照着脚本重跑一遍即可。注意如果你之后换 VS2022理论上可以共用这套源码但 Qt 要换成msvc2019_64或msvc2022_64里对应的一套且全部依赖库要重新编译不能只换编译器。3. 编译 OpenSceneGraph 3.7 x64CMake 关键开关与 osgQt 的绑定3.1 第一次 CMake 配置用命令行锁死生成参数OpenSceneGraph 3.7 是一个主线开发版本号官方稳定线停留在 3.6.x但 3.7 分支的 CMake 结构更接近现在的 Git master并且把 Qt 支持拆分成了独立的组件。配置命令如下cmake -G Visual Studio 16 2019 -A x64 ^ -DCMAKE_CONFIGURATION_TYPESRelease ^ -DCMAKE_PREFIX_PATHC:/geo/thirdparty/Qt5/5.15.2/msvc2019_64 ^ -DCMAKE_INSTALL_PREFIXC:/geo/OSG ^ -DACTIVE_QTON ^ -DOSG_MSVC_VERSIONED_DLLON ^ -DBUILD_OSG_PLUGINSON ^ -DBUILD_OSG_APPLICATIONSON ^ -DOSG_BUILD_VIEWERON ^ C:/geo/src/OpenSceneGraph这段命令的核心是把四个要素一次性定死。-A x64锁定 64 位平台CMAKE_CONFIGURATION_TYPESRelease让 VS 解决方案里只用 Release 配置从根上杜绝 Debug/Release 混用CMAKE_PREFIX_PATH告诉 CMake 去哪找 Qt5 的配置包CMAKE_INSTALL_PREFIX决定编译完成后头文件、lib、DLL 装到哪。ACTIVE_QT这个开关在 3.7 分支里对应 osgQt 和 osgQOpenGL 两个模块的构建。如果你的源码分支里 OPTION 的名称是OSG_USE_QT那就是版本分支差异改成对应的名字即可。OSG_MSVC_VERSIONED_DLLON会让输出的 DLL 带上版本号后缀比如osg71-osgViewer.dll这样做的好处是同一台机器上多个 OSG 版本共存时不会互相覆盖。BUILD_OSG_APPLICATIONSON会编译 osgviewer、osgversion 等命令行工具。osgEarth 虽然不依赖这些工具但 osgviewer 在后期验证模型加载时非常有用。我在第一次配置时总是把它打开后面验证某个模型文件能不能正常加载直接osgviewer model.osgb就测了。3.2 Release 构建与 INSTALL先编 osgQt 再编全量CMake 生成完 VS 解决方案后按依赖顺序编译。我的习惯是先只编 osgQt 这一项确认 Qt 集成链路是通的再跑全量 ALL_BUILD。如果一上来就全量编译等 20 分钟编译完才发现 osgQt 因为 Qt 路径不对而失败时间就白白浪费了。cmake --build C:/geo/build/build-OSG --config Release --target osgQt -j 8 cmake --build C:/geo/build/build-OSG --config Release --target ALL_BUILD -j 8 cmake --build C:/geo/build/build-OSG --config Release --target INSTALL第一条命令里的--target osgQt只编这一个模块-j 8是并行编译的核数按 CPU 实际线程数调整8 核机器上很稳。第二条命令编全部库和插件编译时长取决于机器三四十分钟是常态。第三条INSTALL把产物拷贝到CMAKE_INSTALL_PREFIX指定的C:\geo\OSG目录。Visual Studio 的多配置生成器下--config Release必须写否则 CMake 默认取 Debug 配置。你可能会问前面不是指定了CMAKE_CONFIGURATION_TYPESRelease吗对它限制了解决方案里只有 Release 一项但命令行的--config仍然要明确写出因为 CMake 的构建命令不知道你要哪个配置。INSTALL完成后检查C:\geo\OSG\bin下的内容。只要 osgQt 编译成功bin 目录里应有osgQt.dll或osgQOpenGL.dll取决于源码分支命名。再检查C:\geo\OSG\bin\osgPlugins-3.7.0里是否有osgdb_qt.dll这个插件是为 osgViewer 读取 Qt 相关文件用的没有它osgearth_qt 在运行时可能静默降级。3.3 osgQt 模块的边界它依赖 Qt 的哪几个组件osgQt 不是把整个 Qt 都编进去它只依赖 Qt5 的 Core、Gui、Widgets、OpenGL 这四个模块。CMake 的find_package(Qt5 COMPONENTS Core Gui Widgets OpenGL)会去CMAKE_PREFIX_PATH指定的目录找对应的Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll、Qt5OpenGL.dll。编译通过只代表链接期成功。运行时这四个 DLL 必须出现在 PATH 里且必须与编译时用的是同一套。C:\Qt\5.15.2\msvc2019_64\bin里通常有Qt5Core.dll、Qt5Gui.dll等把这些加到 PATH 末尾即可。如果系统里同时装了多个 Qt 版本PATH 的顺序会直接决定加载哪个 Qt这就是很多“编译没问题、运行打开窗口就崩”的根源。提示检验 DLL 依赖不要靠眼睛用Dependencies工具或 VS 自带的dumpbin /dependents osgQt.dll看它实际引用了哪个 Qt 版本。4. 编译 osgEarth 3.4把 GDAL 与 SQLite 的链接关系锁死4.1 osgEarth 的 CMake 三组变量OSG_DIR、GDAL、SQLiteosgEarth 3.4 的 CMake 配置比 OSG 更挑剔因为它要同时找到三组外部依赖OSG 本身、GDAL、SQLite。这三组变量只要有一组指向错误配置阶段可能不报错编译阶段或者运行阶段才爆雷。cmake -G Visual Studio 16 2019 -A x64 ^ -DCMAKE_CONFIGURATION_TYPESRelease ^ -DOSG_DIRC:/geo/OSG ^ -DCMAKE_PREFIX_PATHC:/geo/thirdparty/Qt5/5.15.2/msvc2019_64 ^ -DGDAL_INCLUDE_DIRC:/geo/thirdparty/gdal-3.0.4/include ^ -DGDAL_LIBRARYC:/geo/thirdparty/gdal-3.0.4/lib/gdal_i.lib ^ -DSQLITE3_INCLUDE_DIRC:/geo/thirdparty/sqlite/include ^ -DSQLITE3_LIBRARYC:/geo/thirdparty/sqlite/lib/sqlite3.lib ^ -DOSGEARTH_USE_QT5ON ^ -DOSGEARTH_BUILD_SAMPLESON ^ -DOSGEARTH_BUILD_TESTSOFF ^ C:/geo/src/osgearthOSG_DIR指向 OSG 的安装前缀CMake 会往里找include/osg/头文件和lib/目录下的导入库。这一步常见错误是把OSG_DIR指到源码目录源码目录只有.cpp和头文件没有安装好的libCMake 会报找不到 osgDB。GDAL_LIBRARY这一项要特别注意GDAL 的导入库文件名在不同版本里不一样。3.0.4 的预编译包里常见的是gdal_i.lib对应运行时gdal304.dll。如果你手头的是gdal.lib那可能是静态库或另一种命名CMake 能接住但链接时会出现符号重复或缺失。所以这里不要想当然去 lib 目录看实际文件名。SQLITE3_LIBRARY同理。SQLite 官方源码默认编出来是静态库sqlite3.libosgEarth 链接静态库也行但你得额外把/MT和/MD运行库选项对齐否则链接器会报LIBCMT.lib 和 MSVCRT.lib 冲突。我偷懒的做法是直接用动态库版本的sqlite3.libsqlite3.dll省去一堆 CRT 冲突问题。4.2 功能开关GDAL、SQLite、Qt5 为什么必须显式打开osgEarth 3.4 的 CMake 对可选依赖采取“找不到就静默关闭”的策略。你如果没提供 GDAL 路径它不会直接报错而是把OSGEARTH_USE_GDAL自动设置为 OFF。编译照常通过但运行时所有 GDAL 驱动都是空的earth 文件里写的image drivergdal会直接失效连个报错都没有只在地形加载时留下一个黑屏。所以配置完成后第一件事是去 CMakeCache.txt 里确认三项开关findstr OSGEARTH_USE_GDAL C:/geo/build/build-osgEarth/CMakeCache.txt findstr OSGEARTH_USE_SQLITE C:/geo/build/build-osgEarth/CMakeCache.txt findstr OSGEARTH_USE_QT5 C:/geo/build/build-osgEarth/CMakeCache.txt三个值都应该是ON。如果 GDAL 或 SQLite 是 OFF回到上一步检查路径变量是否写错。OSGEARTH_USE_QT5ON会额外编译osgEarthQt库同时会让 osgearth_qt 示例参与构建。这个库依赖 Qt5 Widgets 和 OSG 的 osgQt 模块如果你 OSG 编译时没开ACTIVE_QT这里也会有连锁失败。OSGEARTH_BUILD_SAMPLESON生成一整套示例程序包括 osgearth_qt、osgearth_viewer、osgearth_manyfiles 等。这些示例就是你的验证工具集建议开着。OSGEARTH_BUILD_TESTSOFF关掉测试模块能省不少编译时间CTest 那一套对纯编译场景没意义。4.3 构建、安装并检查插件产物cmake --build C:/geo/build/build-osgEarth --config Release --target ALL_BUILD -j 8 cmake --build C:/geo/build/build-osgEarth --config Release --target INSTALLosgEarth 的编译量比 OSG 小正常机器十分钟左右完成。编译过程中如果弹error LNK2019: unresolved external symbol _GDAL...说明 GDAL 链接失败排查方向是GDAL_LIBRARY指向的 lib 与编译时的头文件版本不一致。如果弹error C2039: xxx is not a member of osg::...说明 OSG 版本太新或太旧和 osgEarth 3.4 的接口对不上。INSTALL 完成后检查C:\geo\osgEarth\bin下应有osgEarth.dll、osgEarthQt.dll、osgEarthFeatures.dll、osgEarthUtil.dll等。C:\geo\osgEarth\bin\osgPlugins-3.7.0下应有osgdb_osgearth.dll以及按功能拆分的osgdb_osgearth_*插件。用osgversion在命令行跑一下确认 OSG 版本号是 3.7.0。插件目录这一步特别重要。osgEarth 是通过 OSG 的插件注册表加载的不在插件目录里的驱动永远不会被识别。另外osgEarth 的插件目录和 OSG 的插件目录理论上可以不是一个路径只要你用OSG_LIBRARY_PATH同时指过去就行但我在实践中会把两个目录都塞进OSG_LIBRARY_PATH省得漏掉。注意osgEarth 安装后默认会把插件复制到CMAKE_INSTALL_PREFIX/bin/osgPlugins-xxx。如果你 INSTALL 完没看到插件目录检查是不是 CMake 的BUILD_OSG_PLUGINS没生效或者安装目录权限不足导致 INSTALL 脚本静默跳过。5. 编译栈排障 4 例从“This sample requires”到 x64 DLL 崩溃5.1 示例报 “This sample requires OpenSceneGraph and osgEarth installed”但两个都装了现象编译出的 osgearth_qt.exe 一运行命令行窗口只打印一句This sample requires OpenSceneGraph and osgEarth installed然后程序退出。原因这不是检测你有没有安装库而是 osgEarth 示例在进入渲染循环前动态加载 OSG 和 osgEarth 的 DLL 失败时的兜底提示。Windows 的 DLL 搜索顺序先从 exe 所在目录找再从 PATH 找。如果你的 PATH 里没有C:\geo\OSG\bin和C:\geo\osgEarth\bin加载器就会失败。解决把第 2.1 节的env.bat在运行前执行一遍或者在系统环境变量里永久追加。如果你不想动全局 PATH把 osgearth_qt.exe 复制到C:\geo\osgEarth\bin再运行也能让它找到同一目录下的 DLL但这只适用于单个 exe 验证。5.2 运行时提示缺少 sqlite3.dll 或 gdal304.dll现象编译全部通过osgearth_viewer.exe 启动时 Windows 弹出“找不到 sqlite3.dll”或“找不到 gdal304.dll”。原因osgEarth 的库在链接期通过导入库记录了依赖关系但导入库不会把 DLL 打包到 exe 里。运行期操作系统按 PATH 搜 DLL。GDAL 3.0.4 的预编译包把 DLL 放在bin目录SQLite 的 DLL 放在sqlite目录这两个目录都不在默认 PATH 里。解决最省心的是在env.bat里把这两个 bin 目录加到 PATH 最前面。还有一种做法是把sqlite3.dll、gdal304.dll以及 GDAL 的依赖 DLL如libssl、libcrypto、proj相关 DLL全部拷到 exe 目录但这样会让验证目录非常乱我一般不用。5.3 osgQt 窗口黑屏场景没有渲染现象osgearth_qt 能弹出窗口但窗口内容全黑拖动鼠标也没有反应。原因分三个层次排查。第一层是 osgEarth 插件没加载earth 文件无法解析此时命令行会有Warning: no map data一类输出。第二层是 GDAL 驱动没有注册GeoTIFF 数据打不开窗口里只显示蓝色背景。第三层是 OpenGL 上下文版本太低osgEarth 3.4 的地形着色器要求 OpenGL 3.3而 Windows 默认的 GL 上下文常常只给到 2.1。解决前两层用GDAL_DATA环境变量和OSG_LIBRARY_PATH修正。第三层需要在代码里显式设置上下文版本#include osg/DisplaySettings osg::DisplaySettings::instance()-setGLContextVersion(3.3); osg::DisplaySettings::instance()-setGLContextProfileHint(osg::DisplaySettings::CORE_PROFILE);这段代码要放在创建 viewer 之前执行否则上下文已经在 2.1 上创建了后面改就没用。我遇到过多次黑屏最后排查都是这一行的事。5.4 Release 程序里混入了 Debug DLLQWidget 直接崩溃现象osgearth_qt 启动后窗口一闪而过Windows 事件日志里能看到Qt5Cored.dll相关的错误或者程序直接弹出一个“已停止工作”对话框。原因最常见的路径是osgEarth 示例虽然用 Release 配置编译但系统 PATH 里先搜到了 Debug 版本的 Qt DLL。VS 在编译 Debug 时会把 Qt 库命名为Qt5Cored.dllRelease 是Qt5Core.dll两个库的内部符号表结构不同混用必然崩溃。解决先确认 PATH 里有没有其他 Qt 安装目录排在前面。用where Qt5Core.dll看实际会被加载的是哪个文件如果输出路径不是你期望的msvc2019_64把 PATH 顺序调整一下或者干脆把多余的 Qt 从 PATH 里移除。还有一个隐蔽点CMAKE_PREFIX_PATH可能同时指了多个 Qt 目录CMake 会优先用第一个找到的最终生成的项目文件里链接到的是哪个 Qt要看 osgearth_qt.vcxproj 里.lib的具体路径别只看 CMake 缓存。提示整套编译栈包括 OSG、osgEarth、Qt、GDAL、SQLite必须统一 Release。我见过有人在调试 osgEarth 代码时只改了 osgEarth 本身的配置为 Debug但 OSG 和 Qt 还是 Release结果程序在osg::ref_ptr的引用计数释放处崩掉这种问题查起来非常耗时。6. 验证整套编译栈用 osgearth_qt 跑通一个离线地球编译完成不等于能跑跑道走一遍才算数。我的验证流程永远从最小离线数据开始不联网、不依赖网络瓦片服务只用一张本地 GeoTIFF 和一段最小的 earth 文件。准备一个test.earth放在D:\data\下earth version2/version map nameoffline-test typegeocentric options lightingtrue/lighting /options image drivergdal urlD:/data/world.tif/url /image /map /earth这个 earth 文件让 osgEarth 用 GDAL 驱动加载一个本地 GeoTIFF图层类型是投影到球面上的geocentric。lighting开启后可以看到地形受光照影响更适合判断渲染管线是否正常。然后运行osgearth_qt.exe D:/data/test.earth --rendermode immediate--rendermode immediate是 osgEarth 的调试选项强制同步渲染不用垂直同步和帧调度。如果这个命令能弹出一个可旋转的地球说明整套栈已经从编译走到了可用的状态。按住鼠标左键拖动旋转滚轮缩放观察画面帧率是否稳定。下一步验证 SQLite 缓存链路。osgEarth 可以把瓦片缓存在 SQLite 数据库里命令里加上缓存路径osgearth_qt.exe D:/data/test.earth --cache-path C:/geo/cache --cache-policy usage运行一段时间后关掉程序用 sqlite3 命令行工具查看缓存库sqlite3 C:/geo/cache/osgearth_modelcache.db .tables如果能看到osgearth_modelcache或类似的表结构说明 SQLite 在 osgEarth 内部已经正常工作数据写入和读取闭环没有问题。这一步跑通后面接在线瓦片服务或者加载 3D 模型都有了可靠性依据。我的个人习惯是把 2.1 节的env.bat和这套验证命令存成一个verify.bat每次在新环境部署完编译栈都先跑这个脚本走一遍再开始写业务代码。编译这种事一套固定流程比临时找问题可靠得多版本号记下来也有据可查。希望帮到你。本文还有配套的精品资源点击获取
返回列表