简介:本资源是面向GIS开发、三维仿真及地理空间应用开发者的一站式编译成果包,专为解决OpenSceneGraph 3.7与OSGEarth 3.4在VS2019 x64平台下的集成编译难题而设计,覆盖osgQt图形界面桥接、SQLite轻量级空间数据存储、GDAL 3.0.4栅格/矢量数据驱动等核心依赖。压缩包共2000个文件,以1122个hpp(模板与接口声明)和878个h(C/C++头文件)为主,涵盖OpenGL扩展(glext.h)、GDAL/OGR几何定义(ogr_geometry.h)、音视频编解码(avcodec.h)、字体渲染(freetype.h)及PNG/SQlite等关键组件头文件,结构完整、层级清晰,可直接用于项目引用或二次开发。资源包大小727.48MB,已为122位开发者提供开箱即用的Release构建环境。用户下载后可立即获得x64 Release版全部预编译头文件、跨模块依赖关系说明及典型GIS三维场景集成范例支撑,显著降低环境配置门槛与版本兼容风险。 如果你做三维GIS或者数字孪生相关的桌面端开发,大概率绕不开这套经典组合:OpenSceneGraph做渲染引擎,osgEarth在上面构建地球地形和影像调度,GDAL负责解析各种遥感影像和高程数据,SQLite存缓存索引,最后再用Qt把整个三维场景嵌到自己的界面里。标题里这套“VS2019 + x64 + OSG 3.7 + osgEarth 3.4 + osgQt + sqlite3 + GDAL 3.0.4”的编译环境,就是我在实际项目中反复搭过好多次的标配。
这篇文章我会把这些库从源码到最终能用的全过程,包括CMake选项怎么勾、依赖路径怎么填、编译顺序怎么排、踩过哪些坑,原原本本写清楚。适合正在搭建三维GIS开发环境的人,无论你是第一次接触还是已经编译到怀疑人生,都能从这里找到对应的解决方案。
1. 这套组合到底是什么,为什么要自己编译
先说清楚这套技术栈的定位。OpenSceneGraph(简称OSG)是一个基于OpenGL的跨平台三维渲染引擎,负责把三维模型、地形、天空盒这些东西画出来。osgEarth则是运行在OSG之上的三维地球SDK,提供瓦片金字塔调度、地形投影、影像叠加这些GIS能力。它们两个的关系,你可以理解成OSG是发动机,osgEarth是变速箱加导航系统,后者让前者具备了GIS数据处理能力。
GDAL在这套组合里的角色更底层。它是个栅格与矢量数据解析库,osgEarth加载GeoTIFF、IMG、DEM这类格式时,底层都是通过GDAL插件去读的。SQLite则主要用来做瓦片缓存和索引存储,osgEarth可以把下载或生成的地形瓦片缓存到本地SQLite数据库里,下次打开就不需要重新计算。osgQt是把OSG渲染窗口嵌入Qt Widgets界面的桥梁,没有它,你只能在独立的窗口里看三维地球,做不了完整的桌面应用。
为什么非要自己编译而不是直接下载现成的?这个问题我一开始也犯过懒。OSG官方只提供部分测试版安装包,osgEarth官方基本不提供Windows预编译二进制,GDAL虽然有各种预编译包,但版本和编译器不一定和你手上的VS2019匹配。最麻烦的是,这套库之间存在严格的对齐关系:osgEarth 3.4要求OSG至少是3.6.5及以上,GDAL 2.x和3.x在API上又有破坏性改动,SQLite版本太老会导致osgEarth运行时崩。自己从头编译一遍,虽然耗时,但所有库都在同一个编译器和同一个运行库(Runtime Library)体系下生成,性能和稳定性都是最可控的。
还有个现实原因:你拿到的预编译包往往是用不同版本MSVC编译的,混合使用的时候经常出现内存分配冲突、Debug/Release混用崩溃、链接失败等问题。与其排查这些剪不断理还乱的错误,不如一次性把整条链路的编译环境统一起来。
2. 编译前的依赖树与版本匹配思路
这套环境的依赖关系比大多数人想象中复杂,不能上来就一把梭地编译。先把依赖树理清楚,后面每一步都会省心很多。
2.1 库之间的依赖关系
osgEarth 3.4的直接依赖包括OSG、GDAL、SQLite、CURL(可选,用于网络瓦片)、Qt5(配合osgQt)。OSG 3.7的依赖则包括zlib、libpng、libjpeg、libtiff、freetype、curl、sqlite3、Qt5以及可选的GDAL插件。GDAL 3.0.4自己又依赖了proj、sqlite3、libtiff、libpng、libjpeg、curl等一堆底层库。
如果把这条链拆开,编译顺序基本是固定的:
- 先处理最底层的第三方库:zlib、libpng、libjpeg、libtiff、freetype、curl、sqlite3
- 再编译GDAL 3.0.4(如果选预编译包则跳过)
- 编译OSG 3.7,开启需要的插件和Qt支持
- 编译osgQt(OSG 3.7已经把osgQt从主仓库独立出去了,需要单独拉取编译)
- 最后编译osgEarth 3.4
这个顺序背后的逻辑很直接:上层库在CMake配置阶段要查找下层库的头文件和库文件,顺序不对就得反复回头补东西。尤其OSG,它的插件系统会在配置阶段检测每个可选依赖是否存在,没找到的部分会被自动禁用,如果编译完osgEarth才发现OSG没有编译GDAL插件,你就要回头重新编译整个OSG,非常浪费时间。
2.2 版本选择的一个关键决策
关于GDAL,我推荐直接用GISInternals提供的预编译包,也就是标题里那个 release-1911-x64-gdal-3-0-4-ma 包。这名字拆开看:1911表示包内部构建版本,x64表示64位,gdal-3-0-4是GDAL版本号,ma代表用VS2019(MSVC v142)编译的。GISInternals的包把GDAL本身和它依赖的proj、sqlite3、curl、tiff这些库都打包好了,省去自己编译整个GDAL依赖树的痛苦。你只需要把它解压到固定目录,配置环境变量,然后在编译OSG和osgEarth时让它找到头文件和库文件就行。
自编译GDAL 3.0.4在Windows上是很痛苦的,它要的底层库太多,尤其是proj库的版本匹配,稍不注意就是一堆编译错误。所以我的原则是:能用预编译包就用预编译包,自己编译GDAL纯粹是重复造轮子。但sqlite3这个库很轻量,而且osgEarth的CMake配置里对sqlite3的查找逻辑比较固定,自己编译反而更好控制版本。
3. 准备VS2019编译环境与第三方库
工欲善其事必先利其器。在正式拉代码之前,建议把编译环境一次性准备好,避免后面编译到一半才发现缺东西。
3.1 VS2019安装组件
安装VS2019时,下面几个组件是必须的:
- 使用C++的桌面开发(Workloads里直接勾选)
- 针对最新v142生成工具的C++工具集
- Windows 10 SDK(建议勾选最新版本,10.0.18362或更高)
这里强调的是,不要精简安装。OSG和osgEarth编译过程中会用到C++的MFC/ATL可选依赖吗?一般不需要,但CMake的MSVC生成器会检测Windows SDK版本,版本太旧可能导致某些头文件找不到。我建议把Windows 10 SDK和C++ CMake tools for Windows两个选项都勾上,CMake工具虽然我们一般用GUI版,但VS附带版本有时候能救急。
安装路径方面,VS2019本身建议默认路径,但项目代码和第三方库的目录尽量不要有空格和中文。比如第三方的库统一放到D:\3rdParty\下面,源码放D:\src\,编译输出目录也放在独立目录。这一步很多人忽略,后面CMake配置时路径里有中文会引发一堆怪问题,尤其是osgEarth的插件加载路径,空格会导致运行时找不到DLL。
3.2 CMake版本与Qt版本
CMake建议直接装最新稳定版,不要用VS2019自带的那个老版本cmake。我当时用的是3.20以上版本,OSG和osgEarth的CMakeLists已经要求CMake最低版本3.10以上,但高版本的CMake对MSVC生成器和Qt模块的识别更友好,能少踩很多坑。安装时选择把cmake加入系统PATH,方便以后在命令行用。
Qt版本建议用Qt 5.15.2,这是一个非常重要的版本节点。Qt 5.15.2是最后一个支持Win7的版本,也是vs2019匹配度非常好的版本,社区验证充分。安装Qt时选择MSVC 2019 64位组件,如果你不想被Qt的在线安装器折腾,也可以用离线包,但不管哪种方式,msvc2019_64这个编译套件目录一定要记得勾上。osgQt编译时只认这个目录下的qmake。
3.3 第三方库目录规划
我自己的目录规划是固定的,这样重新搭建环境时有章可循:
D:\3rdParty\ ├─ gisinternals\ # GDAL预编译包,解压到release-1911-x64-gdal-3-0-4-ma ├─ sqlite3\ # sqlite3 源码加编译产物 ├─ Qt\5.15.2\ # Qt默认安装目录 └─ install\ # OSG和osgEarth的统一安装目录这个目录结构有个好处:编译OSG时,所有的第三方依赖头文件都在D:\3rdParty\下面,cmake的搜索逻辑路径非常清晰,配置阶段不会漏东西。另外,GDAL预编译包的路径不要改包名,CMake有时候会通过路径上的特征字符串去判断版本,改乱了容易触发奇怪的错误。
4. sqlite3与GDAL:底层库的编译和配置
底层库这部分有一个核心原则:头文件、库文件、运行DLL三者的架构必须一致,必须是x64 Release。如果你编译的是Debug版本,那所有库都用Debug链接;Release版本就全程Release。混用Debug和Release的库是Windows C++程序最常见的崩溃来源,这个坑在后续链接阶段会反复咬你。
4.1 从源码编译sqlite3
sqlite3源码只有一个c文件和一个h文件,编译起来非常轻量。从官网下载sqlite-amalgamation压缩包(源码合并版),解压后你会看到sqlite3.c、sqlite3.h、sqlite3ext.h三个文件。
用VS2019的开发者命令行工具(x64 Native Tools Command Prompt for VS2019)编译,命令很简单:
cl /c /O2 /MD sqlite3.c link /DLL /OUT:sqlite3.dll sqlite3.obj第一行命令生成sqlite3.obj目标文件,/O2做速度优化,/MD表示动态链接到多线程DLL运行时(对应MDd则是Debug运行时)。第二行把obj文件链接成sqlite3.dll。如果想生成sqlite3.lib导入库,link命令会自动生成。
如果你需要sqlite3.exe命令行工具,可以再用:
cl /c /O2 /MD sqlite3.c shell.c link /OUT:sqlite3.exe sqlite3.obj shell.obj编译完把sqlite3.h放到D:\3rdParty\sqlite3\include,sqlite3.lib放到D:\3rdParty\sqlite3\lib,sqlite3.dll放到D:\3rdParty\sqlite3\bin。这样目录结构就跟其他库保持一致了,后面osgEarth配置时填三个路径就行。
4.2 GISInternals的GDAL包配置
GISInternals包解压后,bin目录下是一堆DLL和exe,include目录下是头文件,lib目录下是导入库。这个包比较有特点的地方在于,它的include目录里已经带了proj的升级头文件,lib里也有对应的proj库。所以如果你用这个包,不需要再单独编译proj。
需要做的事情是三步:
- 把
bin目录加入系统PATH环境变量。因为GDAL目录下的DLL之间相互依赖,osgEarth的osgdb_gdal插件在加载时如果找不到gdal.dll、proj.dll这些运行库,会直接报插件加载失败。 - 在CMake配置OSG和osgEarth时,把GDAL的include路径指到
release-1911-x64-gdal-3-0-4-ma\include,库路径指到release-1911-x64-gdal-3-0-4-ma\lib。 - 设置GDAL_DATA环境变量,路径指向
release-1911-x64-gdal-3-0-4-ma\bin\gdal-data。这个变量告诉GDAL去哪里找坐标投影参数、椭球定义等数据文件,不设置的话,加载某些投影的地形文件时会报找不到坐标系统。
这里有个检测GDAL环境是否正常的技巧:开一个命令行,输入gdalinfo --version,如果能正确输出GDAL 3.0.4的版本信息,说明bin目录和DLL配置没问题。如果输出找不到DLL的错误,说明PATH没生效或者bin下的东西不全。
4.3 关于GDAL的Debug和Release版本问题
GISInternals包默认只提供Release版本库。如果你用VS2019的Debug模式编译osgEarth,链接阶段可能会报RuntimeLibrary不匹配的错误。解决办法有两个:一是osgEarth等上层库全部用Release模式编译,这是最推荐的做法;二是如果你必须用Debug模式,需要把GDAL换成别的来源,比如vcpkg编译的debug版GDAL,但这要引入vcpkg整套工具链,工程量大不少。
我自己实际项目里,OSG和osgEarth都是从Release编译的,调试三维渲染逻辑时用日志输出或者断点靠插件内部打印。OSG和osgEarth的Release包在大多数场景下够用了。
5. OpenSceneGraph 3.7的完整编译过程
OSG是整个链路的核心,它的编译质量直接决定后面osgEarth能不能正常工作。标题里写的是3.7,实际对应的是OpenSceneGraph主仓库主线版本,因为官方在3.6.5之后的版本号已经推进到3.7.x。osgEarth 3.4对OSG版本要求是3.6.5以上,所以3.7主线配合3.4是没问题的。
5.1 拉取源码与CMake配置
从GitHub拉取OpenSceneGraph仓库代码后,建议不要直接切到master最新提交,因为主线偶尔会有破坏性改动。我一般选择master上近期内有多个稳定tag的提交,或者直接使用OpenSceneGraph-3.6.5再往后的某个发布候选分支。你如果没特殊需求,git checkout到最新的稳定提交即可。
拉完代码后新建两个目录:build(编译中间目录)和install(最终安装目录)。然后打开CMake GUI,源目录选择源码根目录,build目录选择新建的build目录。
CMake配置时,有几个选项是必须注意的:
- 点击“Configure”时,generator选择 “Visual Studio 16 2019”,Platform选择x64。这两个选择决定后面所有编译产物都是64位,如果选成了Win32,后面GDAL和SQLite的64位库都会链接不上。
CMAKE_INSTALL_PREFIX设置为D:\3rdParty\install,这个是后续osgEarth查找OSG的默认路径。BUILD_OSG_EXAMPLES设置为OFF。示例代码会拖慢编译速度,而且对我们来说没有实际用处,在配置阶段就关掉。DYNAMIC_OPENSCENEGRAPH和DYNAMIC_OPENTHREADS保持ON,用动态库方式生成,这样插件机制才能正常工作。OSG_WINDOWING_SYSTEM设置为WIN32。OSG_USE_QT设置为ON。这是OSG 3.7编译时启用Qt支持的开关,如果这里没开,后面osgQt编译出来也没办法和OSG配合使用。CMAKE_PREFIX_PATH填D:\3rdParty,这样CMake会在D:\3rdParty\sqlite3、D:\3rdParty\gisinternals等子目录中自动搜索依赖库。
OSG的可选插件里,有几个建议打开:
GDAL插件必须打开。这个插件让OSG能直接读取影像数据,虽然osgEarth自己也带着GDAL支持,但OSG这边的插件机制会在某些场景下被调用。sqlite3插件可开可不开,取决于你要不要用OSG直接读取sqlite缓存。curl插件建议打开,用于读取网络资源。freetype插件建议打开,用于文字叠加显示。Zlib、libpng、libjpeg、libtiff这些基础图片格式插件必须打开,它们决定OSG能不能加载各种纹理图片格式。
配置过程中如果某个依赖包找不到,CMake会红色高亮显示。这时候不要盲目重试,要去看具体哪个变量没找到。最常见的是找不到ZIP路径(zlib),解决办法是把ZLIB_INCLUDE_DIR和ZLIB_LIBRARY变量手动填写成具体路径。zlib这个库在你编译GDAL包里面其实已经带了一份,GISInternals包的include和lib目录里就有zlib.h和zlib.lib,直接指向那边即可。
5.2 编译安装和插件校验
在CMake GUI里调整完所有选项后,点击Generate生成VS2019解决方案。然后打开生成的OpenSceneGraph.sln,在解决方案管理器里把解决方案配置从Debug切换到Release,然后生成ALL_BUILD项目。OSG的完整编译在8核CPU上大概需要15到25分钟,如果开了很多示例和插件,时间会更长。
编译过程中如果报错,优先看是不是某个第三方库路径配置错了,这些错误通常会显示成“无法打开包含文件”或“无法解析的外部符号”。前者是头文件路径问题,后者是库文件链接问题。解决思路是回头检查CMake里对应的变量是否指向了正确的目录,改完变量后重新Configure和Generate,然后再编译。
编译通过后,在VS里右键INSTALL项目,选择生成,把OSG相关文件安装到D:\3rdParty\install目录下。安装完成后,install/include下应该有openscenegraph头文件目录,install/bin下有osg.exe、osgviewer.exe以及大量osgdb_*.dll插件,install/lib下有各种库文件。这时候可以打开命令行,运行osgviewer cow.osg,如果能弹出一个牛的三维模型,说明OSG主程序基本没问题。
5.3 osg编译容易犯的几个低级错误
第一个是平台选错。很多人Configure的时候看都不看,默认生成了Win32,然后用x64的GDAL库链接,编译时报LNK1112,模块计算机类型“x86”与目标计算机类型“x64”冲突。解决方法是重新Configure,把Generator Platform改成x64。
第二个是Release和Debug混用。比如你用Debug模式编译OSG,但链接时指向了Release版本的sqlite3.lib,会报LNK2038 RuntimeLibrary不匹配。这种问题很隐蔽,因为VS的错误输出可能只是说“检测到RuntimeLibrary的不匹配项”,不仔细看根本想不到是混用了。
第三个是install路径里的空格问题。如果你把OSG装到了C:\Program Files\OpenSceneGraph这种路径,CMake的查找逻辑通常也能处理,但osgEarth编译时某些自定义脚本可能会因为路径里有空格而炸掉。所以我一直坚持所有依赖放在D:\3rdParty\这种无空格路径下,省得后面排查。
6. osgQt独立编译:桥接Qt5与OSG
在OSG 3.7之前,osgQt是集成在OSG主仓库里的,但从3.7开始,官方把osgQt单独拆成了一个独立仓库。这意味着你编译完OSG主仓库,并不会自动得到osgQt相关的东西,必须单独拉取并编译。
6.1 编译osgQt需要满足的条件
编译osgQt之前,三个东西必须已经就绪:
- OSG 3.7已经编译安装到D:\3rdParty\install(osgQt的CMake会通过OSG_DIR查找OSG的config文件)
- Qt 5.15.2已经安装,并且安装组件中包含msvc2019_64(osgQt查找Qt5Widgets和Qt5OpenGL模块)
- VS2019的x64生成工具已经配置好
这三个条件缺一不可。缺第一个,osgQt的CMake在查找OSG_INCLUDE_DIR时就会红一片;缺第二个,osgQt编译时会报找不到Qt5Config.cmake;缺第三个,整个编译过程都无法开始。
6.2 编译步骤与CMake配置
拉取osgQt仓库代码后,在仓库根目录新建build目录。CMake GUI的Source目录指向osgQt源码根目录,Build目录指向新建的build目录。Configure时同样选择Visual Studio 16 2019和x64。
osgQt的CMake配置相对简单,主要变量有:
OSG_DIR填D:\3rdParty\install,让CMake找到OSGConfig.cmakeQt5_DIR填D:\3rdParty\Qt\5.15.2\msvc2019_64\lib\cmake\Qt5,这是Qt5的CMake包查找路径CMAKE_PREFIX_PATH填D:\3rdParty\install;D:\3rdParty\Qt\5.15.2\msvc2019_64,简化两个库的搜索
如果CMake找不到Qt5,最常见的原因是安装Qt时没有安装到默认路径,或者环境变量没配置。解决方法是手动设置Qt5_DIR变量,指到实际的msvc2019_64\lib\cmake\Qt5目录。
Configure通过后,Generate生成解决方案,打开sln,选择Release配置,生成ALL_BUILD。编译完成后生成osgQt库文件,如果你看到osgQt5.dll和osgQt5.lib之类的产物,说明编译成功。之后右键INSTALL项目安装到D:\3rdParty\install目录,这样osgEarth编译时就能通过OSG目录找到osgQt。
6.3 osgQt编译后的验证
编译完osgQt后,最好做一个快速验证。写一个最简单的Qt+OSG程序太费时间,我一般是检查install/lib目录下有没有osgQt5相关的库,以及install/bin目录下有没有osgQt5.dll。如果有,再用Dependencies工具(或者DEPENDS)看下osgQt5.dll的导入表,确认它只依赖了OSG和Qt相关库,没有引入其它dll,基本就OK了。
注意,osgEarth 3.4本身并不强制依赖osgQt,它只是在你需要在osgEarth里面嵌入Qt界面时才需要。如果你的项目不需要Qt界面,可以跳过这一节。但如果标题里明确写了osgQt,说明最终产品是要嵌入Qt的,最好还是按完整链路走一遍。
7. osgEarth 3.4的编译配置
终于到了重头戏。osgEarth 3.4的编译是整个环境搭建中最容易出现配置问题的环节,因为它要同时跟OSG、GDAL、SQLite、Qt四个体系打交道,任何一个路径配错都会导致最终的插件缺失或者链接失败。
7.1 拉取源码与分支选择
从GitHub拉取osgEarth仓库代码后,默认分支可能已经是master,版本可能比3.4更高。标题里指定的是3.4,所以要切到对应的分支或者tag。推荐使用git checkout 3.4或者某个3.4.x的tag,比如3.4.0或3.4.1。3.4系列的代码相对稳定,而且跟GDAL 3.0.x和SQLite3的兼容性经过大量验证。
如果你的OSG是3.7开发主线,需要确保osgEarth代码版本不要早于2021年初的某个提交,因为OSG 3.7对某些API做了调整,旧版osgEarth可能编译不过。用最新的3.4分支头即可。
7.2 CMake关键配置逐项说明
osgEarth的CMake GUI配置里,下面这些选项是你一定会碰到的:
CMAKE_INSTALL_PREFIX填D:\3rdParty\install,让osgEarth安装到和OSG同一个目录,方便后续统一管理。CMAKE_PREFIX_PATH填D:\3rdParty\install;D:\3rdParty\Qt\5.15.2\msvc2019_64;D:\3rdParty\gisinternals\release-1911-x64-gdal-3-0-4-ma;D:\3rdParty\sqlite3,这是最关键的一步,CMake会在这个路径列表下自动查找所有依赖。OSGEARTH_BUILD_TESTS设为OFF,测试代码要编译很多额外的东西,没必要。OSGEARTH_BUILD_SAMPLES设为ON,示例工程是验证编译结果最好的工具,尤其osgearth_viewer这个示例,编译出来可以直接加载earth文件验证环境。OSGEARTH_BUILD_OSGEARTH_QT设为ON,这是osgEarth自带的一套Qt封装,如果你打算用Qt做界面,这个选项可以辅助确认osgQt配置没问题。
GDAL相关变量如果CMake没有自动找到,需要手动设置:
GDAL_INCLUDE_DIR填D:\3rdParty\gisinternals\release-1911-x64-gdal-3-0-4-ma\includeGDAL_LIBRARY填D:\3rdParty\gisinternals\release-1911-x64-gdal-3-0-4-ma\lib\gdal_i.lib
sqlite3相关变量同理:
SQLITE3_INCLUDE_DIR填D:\3rdParty\sqlite3\includeSQLITE3_LIBRARY填D:\3rdParty\sqlite3\lib\sqlite3.lib
如果你看到GDAL_FOUND或者SQLITE3_FOUND为FALSE,不要盲目Generate,先回过头检查路径。很多时候是找不到gdal.h头文件或者gdal_i.lib库文件,这种问题在CMake的红色高亮里一目了然。
7.3 编译过程与产物检查
generate之后打开osgEarth.sln,同样把解决方案配置切成Release,然后右键ALL_BUILD编译。osgEarth的编译量比OSG小很多,约5到10分钟就能完成。编译过程中最常见的报错有两类:
一类是找不到OSG的头文件,比如osg/Node或osgEarth/Version找不到。这通常是CMAKE_PREFIX_PATH没包含OSG安装目录,或者Cmake缓存里残留了旧的OSG路径。解决方法是把CMakeCache.txt删掉重新Configure,让CMake重新搜索。
另一类是链接时提示无法解析的外部符号,符号名里包含osgEarth或osg字样。这种情况多半是因为OSG和osgEarth的编译版本不一致,比如osgEarth链接到了系统里另一个旧版OSG库,或者Release库和Debug库混用。解决方法是确保OSG_DIR只指向你编译安装的那个OSG目录,并且把其它所有可能干扰的路径从CMAKE_PREFIX_PATH中移除。
编译完成后,用VS生成INSTALL项目,把osgEarth的dll、头文件、cmake配置装到D:\3rdParty\install目录下。现在install/bin目录里应该能同时看到osgdb_osgearth_*.dll这些osgEarth插件。这几个插件是osgEarth的核心,包括osgdb_osgearth_feature、osgdb_osgearth_image、osgdb_osgearth_elevation、osgdb_osgearth_terrain等。如果这些插件不在,说明osgEarth编译没成功或者安装没执行。
7.4 osgEarth插件架构的理解
osgEarth的插件机制设计得很有意思。严格来说,osgEarth本身不是一个独立的可执行程序,而是作为一组OSG插件运行在OSG的框架里。比如你用osgviewer去打开一个earth文件,OSG会根据文件后缀找到osgdb_osgearth_terrain插件,然后这个插件再根据earth文件里的XML配置去实例化osgEarth的各种功能。
这就意味着,就算osgEarth编译成功了,如果你的OSG插件搜索路径不对,它照样跑不起来。OSG默认会在exe所在目录和OSG_FILE_PATH指定的路径下搜索插件。所以我后面会强调,运行任何osgEarth程序之前,必须把D:\3rdParty\install\bin加到PATH或者设置OSG_FILE_PATH环境变量。
8. 部署环境与运行验证
整个编译链路完成后,先别急着自己写代码,先把运行环境验证打通。这一步能帮你把所有路径问题、DLL缺失问题提前暴露出来,等真正开发时能省很多排查时间。
8.1 环境变量设置
需要配置的环境变量有这么几个,我按优先级说明:
OSG_FILE_PATH:设成D:\3rdParty\install\bin。这是OSG搜索插件和资源文件的路径,不设置的话,osgEarth运行时可能找不到osgdb_osgearth_terrain等插件。GDAL_DATA:设成D:\3rdParty\gisinternals\release-1911-x64-gdal-3-0-4-ma\bin\gdal-data。确保GDAL能读取坐标系统描述数据。PATH:把D:\3rdParty\install\bin、D:\3rdParty\gisinternals\release-1911-x64-gdal-3-0-4-ma\bin、D:\3rdParty\Qt\5.15.2\msvc2019_64\bin都加进去。
这三个路径缺一不可。PATH里的顺序也会影响程序运行,我习惯把OSG的bin放最前面,这样确保优先加载自己编译的OSG相关DLL,而不是被系统里其它旧版DLL干扰。
8.2 验证测试
先验证OSG环境。命令行输入:
osgviewer cow.osg这个命令会加载OSG自带的牛模型。如果黑屏或者报错,优先检查PATH里有没有osgviewer.exe所在目录,以及显卡驱动是否正常。
再验证osgEarth环境。在osgEarth的示例工程里找到osgearth_viewer示例,运行时传入一个简单的earth文件。如果你手头没有earth文件,可以用osgEarth源码包里的samples目录下的简单示例,比如simple.earth。命令大概是:
osgearth_viewer simple.earth如果能看到一个三维地球,而且可以用鼠标拖拽旋转、滚轮缩放,说明整条链路已经通了。如果报osgdb_osgearth_terrain插件找不到或者earth文件无法解析,大概率是OSG_FILE_PATH没设置好,或者osgEarth插件没安装到install/bin目录下。
验证时还可以用一个小技巧:设置环境变量OSG_NOTIFY_LEVEL为INFO,OSG会打印出插件加载和文件解析的详细日志。如果你设置成DEBUG,日志量会非常大,但能看清每一步加载了什么库、哪个插件注册失败。对于排除环境问题是神器。
8.3 项目工程里如何引用这些库
编译好的静态链接路径和动态运行路径要分开理解。程序编译时,VS工程需要在“附加包含目录”中配置OSG和osgEarth的头文件路径,在“附加库目录”中配置lib路径,并在“附加依赖项”中列出需要链接的lib文件。而程序运行时,则依赖PATH路径下的DLL文件。
如果你在VS里写了代码但运行时提示找不到osgEarth相关dll,解决办法很简单:把install/bin目录加到系统PATH,或者把生成的DLL复制到exe同目录。我推荐后者,因为发布程序时本来就要把所有DLL放到exe旁边。但开发调试时用PATH最方便。
9. 编译踩坑问题排查速查表
把这几年编译这个组合踩过的坑整理成一张表,按症状、原因、解决方式来对照排查,比自己对着日志猜效率高很多。
| 症状 | 常见原因 | 解决方式 |
|---|---|---|
| CMake Configure时GDAL_FOUND为FALSE | GDAL_INCLUDE_DIR和GDAL_LIBRARY没填或者填错 | 手动指定到gisinternals的include和gdal_i.lib |
| 编译OSG时报无法打开gdal_priv.h | GDAL头文件路径没配置 | 确认OSG的CMake里GDAL_INCLUDE_DIR填了gisinternals的include目录 |
| 链接时报LNK1112 x86/x64冲突 | CMake的Platform选了Win32而非x64 | 重新Configure,Platform选择x64 |
| 链接时报LNK2038 RuntimeLibrary不匹配 | Debug/Release库混用 | 统一使用Release构建所有库 |
| osgviewer打开earth文件提示plugin not found | osgEarth插件没安装,或OSG_FILE_PATH找不到 | 确认osgdb_osgearth_terrain.dll存在并设置OSG_FILE_PATH |
| 运行时提示找不到osgQt5.dll | PATH没包含install/bin目录 | 把install/bin加到PATH,或复制到exe目录 |
| 加载影像时显示空白,无报错 | GDAL_DATA未设置或设置错误 | 设置GDAL_DATA指向gisinternals的gdal-data目录 |
| osgearth_viewer启动后闪退 | Qt版本和osgQt版本不匹配 | 确认osgQt和osgEarth都使用Qt5.15.2编译 |
| 编译osgEarth时找不到osgEarth::Version头文件 | OSG版本太旧或OSG_DIR指向错误 | 确认OSG为3.7及以上,OSG_DIR指向install目录 |
| earth文件解析失败,日志提示srs错误 | GDAL的proj版本或数据文件问题 | 更新gisinternals包里的proj,检查GDAL_DATA |
| Debug模式下链接报一堆缺符号 | GISInternals只有Release库 | 全部改成Release编译;除非换vcpkg版Debug GDAL |
这张表不能覆盖所有问题,但覆盖了绝大多数新手会遇到的。如果还没解决,建议把CMake的页面截图、编译日志的末尾20行、环境变量列表整理好再提问,信息越全越容易定位。
10. 最后分享几点经验
这套环境我反复搭过很多次,最后分享几个实际操作中总结的小技巧。
第一,整个编译过程至少预留一个小时,期间不要做其它紧急的事。OSG的ALL_BUILD编译时间最长,如果编译到一半中断再重来,很考验耐心。我习惯把编译顺序固定成脚本,从命令行依次调用cmake --build,这样就算出问题也能快速定位到是哪一步。
第二,每次改完CMake变量后,清缓存比单纯重新Configure更可靠。CMakeCache.txt会记住上一次的模块搜索路径,当你移动了某个库的位置后,光点Configure可能还是找不到,因为它读的是缓存里的旧路径。删掉build目录下的CMakeCache.txt重新Configure,几乎能根治所有“我明明改了路径为什么还是错”的问题。
第三,不要贪新。当时我试过OSG 3.7新版和osgEarth 3.4最新master的组合,大部分情况是好的,但偶尔会因为某个API调整导致编译失败。如果你要交付项目,锁死版本比追新版本更重要。建议在文档里记下每个仓库的commit号,以后重建环境才能保证完全一致。
第四,如果是团队协作,建议把D:\3rdParty整个目录做一个压缩包或者镜像,传到团队内部共享。新同事入职时直接解压,设置好环境变量就能开始开发,不用每个人重复编译一遍。如果你用的是版本管理工具,这些依赖不要提交到代码仓库里,用独立的依赖包管理方式更清晰。
这套编译工作做完,其实只是一个开始。接下来你可以用osgEarth的API加载真实地形数据,把遥感影像切片、矢量数据导入、地形夸张显示、视点控制这些能力一个个加进去。编译环境的打磨决定了后续开发的上限,前期花时间把地基打牢,后面才能专注在业务逻辑上。
本文还有配套的精品资源,点击获取