简介:针对OSG3.6.5与OSGEarth 2.10在Visual Studio 2019环境下的编译需求,这套预编译的3rdParty.zip直接提供64位三方库,省去手动搜集与编译依赖的繁琐过程。资源面向使用VS2019、需要快速搭建OpenSceneGraph与OSGEarth开发环境的C++开发者,尤其适合刚入门或希望减少环境配置成本的学习者。压缩包共2000个文件、约137.76MB,主体为1351个头文件、56个lib导入库、32个cmake配置模块以及少量dll运行库等,涵盖编译链接所需的头文件、导入库与CMake查找脚本,并附带时区数据等支撑文件;目录结构清晰,便于按依赖类型集成到现有工程。目前已有623人学习下载,说明该包在同类需求中具备实用参考价值。拿到后可直接配合OSG与OSGEarth源码进行链接配置,有效缩短编译链搭建周期,把更多精力留给场景渲染与地形调度等业务开发。
1. 被三方库卡住的第一天:OSG 3.6.5 与 OSGEarth 的预编译依赖包
在 Windows 上用 VS2019 编译 OSG 3.6.5 和 OSGEarth,最磨人的不是源码本身,而是那二十几个第三方依赖库。每个人第一次编 OSG 几乎都在同一个地方翻车——报错指向一个 curl/openssl/gdal 的头文件找不到,但你根本不知道这头文件该从哪来。网上要么让你用 vcpkg 一个个装,要么让你去每个库的官网手动编译,拖拖拉拉两三天就没了。这个预编译好的 3rdParty.zip 就是把 zlib、libpng、libjpeg、tiff、freetype、curl、openssl、gdal、geos、sqlite3 等一堆库在 VS2019 工具集下编译好、打包好的现成货。适合那些目标明确、只想把 OSG 跟 OSGEarth 跑起来的人——解压、配置、CMake 认到路径,然后就直奔编译正题。
2. 为什么需要预编译三方库:依赖关系梳理与选型理由
2.1 从源码编译整个生态的连锁依赖
OSG 3.6.5 不是孤立的渲染引擎,它的插件体系覆盖了图片、模型、视频、网络数据等各类输入输出资源。加载一张 JPEG 图片要 libjpeg,加载 PNG 要 libpng,读取高程和影像数据要 GDAL,做几何运算要 GEOS,通过网络拉取远程瓦片要 curl,而 curl 自己又依赖 openssl。这些库互相之间还有版本耦合,比如 curl 要链接 openssl 的 libssl 和 libcrypto,GDAL 要链接 tiff、jpeg、png、sqlite3,GEOS 又要和 GDAL 配合工作。你从零开始逐一编译,最先解决的是顺序问题——先编 zlib,再编 libpng,因为 libpng 依赖 zlib;先编 openssl,再编 curl,因为 curl 依赖 openssl。这个顺序只要错一步,链接阶段就会报一堆 unresolved external symbol。
自己编译三方库的第二个成本是工具集对齐。OSG 的 CMake 在查找第三方库时,会校验库的运行时库设置是 /MD(Release)还是 /MDd(Debug),以及库是在 Debug 还是 Release 配置下生成。你用不同版本的 VS 或者不同版本的 CMake 编出来的 .lib 文件,可能因为 ABI 不兼容导致 OSG 在链接期直接失败。这也是为什么预编译包必须标明“VS2019”的原因——它对应的是 MSVC v142 工具集、x64 架构、以及 /MD 与 /MDd 两套运行时配置。包的发布者已经把这个问题压平了,你拿到手后要做的就是解压、把路径填给 CMake、然后祈祷自己没选错架构。
2.2 3rdParty.zip 里的库清单与用途对照
这份预编译包大致覆盖了 OSG 和 OSGEarth 在 Windows 编译时最常用的一批库。我在本地解压后看到目录结构一般长这样:
3rdParty/ |-- bin/ # DLL 文件,运行时需要拷到 exe 旁边或加入 PATH |-- include/ # 头文件,CMake 查找时用 |-- lib/ # 静态库与导入库,链接器用 |-- share/ # CMake 配置文件,部分库可通过 find_package 找到bin 目录里通常会包含 zlib.dll、libpng.dll、libjpeg.dll、tiff.dll、curl.dll、libssl.dll、libcrypto.dll、geos.dll、gdal.dll、sqlite3.dll、freetype.dll 这些运行时组件。include 目录里对应的是各个库的头文件。lib 目录下每个库至少提供 xx.lib(Release 导入库)和 xxd.lib(Debug 导入库)两组文件,有些库命名习惯不同,比如 libcurl.lib 对应 Release,libcurld.lib 对应 Debug。
各库在 OSG/OSGEarth 链路里的角色如下:
| 库 | 在编译链路中的角色 | 默认被哪个模块使用 |
|---|---|---|
| zlib | 解压与压缩基础库,PNG/TIFF 的间接依赖 | osgdb_png、osgdb_tiff |
| libpng / libjpeg | 图片插件解码 | osgdb_png、osgdb_jpeg |
| tiff | 多波段影像读写 | osgdb_tiff、GDAL |
| freetype | 字体渲染与文字贴图 | osgdb_freetype、osgText |
| curl / openssl | 网络数据源与 HTTPS 支持 | osgdb_curl、OSGEarth 网络瓦片 |
| gdal | 栅格与矢量数据读写,OSGEarth 的核心数据源 | OSGEarth 的 GDAL 驱动 |
| geos | 空间几何操作,与 GDAL 搭配 | OSGEarth 矢量要素处理 |
| sqlite3 | 本地缓存与地理数据库读取 | OSGEarth 的缓存机制 |
需要特别注意的是 GDAL。OSGEarth 对 GDAL 的版本很敏感,如果你的 3rdParty 包里 GDAL 是 3.4.x,而代码里调用了 GDAL 3.6 才有的 API,就会在编译期报“找不到函数定义”。反过来,如果运行时加载的 gdal.dll 版本和编译时不一致,OSGEarth 在读取 GeoTIFF 时会直接崩掉。所以拿到预编译包后,第一步就去看 gdal 的版本号,确认它和你 OSGEarth 源码分支的预期一致。
2.3 为什么不用 vcpkg 或 Conan 等方案
不是 vcpkg 不好,是对于固定 VS2019 + OSG 3.6.5 的场景,预编译包比包管理方案更省心。vcpkg 在安装依赖时默认使用当前最新的库版本,比如 curl 8.x、openssl 3.x。但 OSG 3.6.5 的 CMake 脚本是按它发布时代的库行为设计的,某些新版本库改了头文件结构或函数签名,可能会导致 OSG 的插件代码编译失败。你当然可以在 vcpkg 里指定版本,但那意味着你得先确认每个依赖库哪个版本能过编译——这套验证工作早有人替你做过了,才产出了这份预编译包。
另外 vcpkg 安装的是静态库或动态库取决于你设置的 triplet,而 OSG 的第三方库查找脚本往往默认找动态库(有对应 DLL)。如果 vcpkg 装了静态库,OSG 的 CMake 会找到但链接阶段一堆“无法解析的外部符号”,原因是静态库还需要额外定义一些宏,比如 CURL_STATICLIB。这个坑很容易让人怀疑人生。预编译包直接给你动态库版本,绕开了宏定义和链接顺序的问题。
3. 编译前环境准备:VS2019 工程配置与路径布局
3.1 安装 VS2019 并确认工具集版本
预编译三方库是基于 VS2019 的 MSVC v142 工具集生成的,因此你在编译 OSG 之前先得确认本地 VS2019 是完整安装的。打开 Visual Studio Installer,查看已安装的组件列表中是否包含“MSVC v142 - VS 2019 C++ x64/x86 生成工具”和“Windows 10 SDK”。这两个缺一个,CMake 生成工程时会报找不到 C 编译器或找不到 Windows SDK。
安装完成后,打开“开发者命令提示符”或者直接在“开始”菜单里找到“x64 Native Tools Command Prompt for VS 2019”,运行 cl 命令验证编译环境:
cl如果你看到类似“Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x64”的输出,说明工具链已经就绪。注意必须是 x64 版本的命令行提示符,因为 3rdParty 包里的库是 64 位版本。如果误用了 x86 环境,之后 VS 打开工程时虽然也能编译,但链接器找不到与 x64 匹配的导入库,报错会相当迷惑。
3.2 解压 3rdParty 并规划目录
解压 3rdParty.zip 时不要解压到带中文和空格的路径下,比如“D:\我的 3rdParty”这种。CMake 的 find_package 机制对路径中的空格处理在不同版本里表现不一致,OSG 3.6.5 用的 CMake 配置脚本对空格路径有时会解析失败,表现就是“找不到库”但路径明明是对的。我的习惯是统一放到 D 盘根目录下的纯英文目录:
D:\dev\3rdParty\x64把 zip 里的内容全部解压到 x64 目录下。解压后确认 x64 目录里直接是 bin、include、lib、share 四个子目录,而不是多了一层嵌套目录。嵌套目录会让 CMake 的搜索路径失效——你指定依赖搜索路径为 D:\dev\3rdParty\x64,而实际头文件在 D:\dev\3rdParty\x64\3rdParty\include 里,那就什么都找不到。
3.3 建立环境变量与 PATH 配置
为了让 CMake 以及后续编译出来的 OSG 程序在运行时能直接找到 DLL,我一般会在系统环境变量里增加一个 OSG_3RDPARTY_DIR,把它指向解压目录:
setx OSG_3RDPARTY_DIR "D:\dev\3rdParty\x64"然后把 bin 目录追加到 PATH:
setx PATH "%PATH%;D:\dev\3rdParty\x64\bin"setx 会把变量写到用户环境变量里,新开的命令行窗口才生效,当前窗口不会立即更新。所以配置完要重新打开一个命令行窗口,用 echo 验证:
echo %OSG_3RDPARTY_DIR%这一步看似多余,但在 CMake 配置阶段很省时间——你不需要每次都手动填路径,CMake 变量可以直接引用这个环境变量。另外 PATH 里加上 bin 目录还有个好处:OSG 编译安装完成后,运行 osgviewer 时系统会自动找到 gdal.dll、curl.dll 这些依赖,不需要手动把 DLL 一个个复制到 exe 目录。
4. CMake 配置与编译:关键开关与参数说明
4.1 用 CMake GUI 生成 VS2019 工程
OSG 和 OSGEarth 的编译走标准 CMake 流程。打开 CMake GUI,把源代码路径和构建路径分别填好——构建路径我习惯用源码目录外的一个独立目录,比如源码在 D:\dev\openscenegraph-3.6.5,构建目录就建 D:\dev\build\osg-3.6.5,这样不会把 CMake 生成的中间文件和源码混在一起,后续想重新配置只需要删掉构建目录,源码保持干净。点 Configure,在弹窗里选择 Visual Studio 16 2019,平台选 x64,其他的保持默认:
源代码目录: D:/dev/openscenegraph-3.6.5 构建目录: D:/dev/build/osg-3.6.5 生成器: Visual Studio 16 2019 平台: x64第一次 Configure 会花一点时间,因为 CMake 需要探测编译器和 Windows SDK。探测完成后,CMake 界面里会列出大量红色选项行——红底白字表示该变量是第一次配置时新增的,粉色的 ACTUAL_3RDPARTY_DIR 等变量则是 CMake 在查找依赖时自动找到的路径。这一步不要急着点 Generate,先把几个关键变量确认好。
4.2 OSG 3.6.5 的关键 CMake 变量
OSG 的 CMake 脚本通过 ACTUAL_3RDPARTY_DIR 变量来定位整个三方库目录。在 CMake GUI 里搜索“3RDPARTY”,找到 ACTUAL_3RDPARTY_DIR,把它填为你的三方库路径。填完后点 Configure 再查一下 CMAKE_PREFIX_PATH,通常 CMake 会自动把它设成与 ACTUAL_3RDPARTY_DIR 相同的值,如果没自动设置,就手动加一行:
CMAKE_PREFIX_PATH = D:/dev/3rdParty/x64这个变量是所有 find_package 和 find_library 命令的基础搜索路径。OSG 的插件模块很多,但并不是所有模块你都需要编。在 CMake 里把不需要的插件关掉可以显著缩短编译时间,也减少依赖错误的风险。我的建议是至少要保留这几个:osgdb_png、osgdb_jpeg、osgdb_tiff、osgdb_curl、osgdb_freetype、osgdb_gdal——前两个支持基础图片格式,后几个是三维地形和网络数据加载的刚需。
相关的 CMake 变量开关如下:
BUILD_OSG_PLUGINS_BY_DEFAULT: ON BUILD_OSG_PLUGIN_PNG: ON BUILD_OSG_PLUGIN_JPEG: ON BUILD_OSG_PLUGIN_TIFF: ON BUILD_OSG_PLUGIN_CURL: ON BUILD_OSG_PLUGIN_FREETYPE: ON BUILD_OSG_PLUGIN_GDAL: ON BUILD_OSG_DEPRECATED_SERIALIZERS: OFFBUILD_OSG_DEPRECATED_SERIALIZERS 是历史遗留选项,OSG 3.6.5 里默认是关闭的,如果你在地形加载时不需要读取旧版 .osg 序列化格式,保持关闭即可。打开它会让编译器多处理一批旧代码,而且这些代码和现代 OSG 架构有冲突,经常在编译期报错,属于典型的“不关就翻车”的开关。
4.3 编译 OSG 并确认插件生成
Configure 通过后点 Generate,CMake 会在构建目录里生成 OSG.sln。用 VS2019 打开这个解决方案文件,在“生成”菜单中选择“批生成”,勾选 ALL_BUILD 的 Release 和 Debug 两个配置。全部编译大概要 15 到 30 分钟,取决于机器性能。编译完成后最重要的验证动作是看插件 DLL 是否在构建目录的 bin 下生成,尤其是 osgdb_gdal.dll 这个文件——OSGEarth 的数据读取全靠它,编不出来后面全是白做。
用命令行编译也可以,好处是输出日志可以全文搜索,方便定位错误位置:
cmake --build D:/dev/build/osg-3.6.5 --config Release --target INSTALL加 INSTALL 目标会把 OSG 的头文件、库文件和插件统一安装到 CMAKE_INSTALL_PREFIX 指定的目录。这一步建议做,因为后面编 OSGEarth 时需要引用 OSG 的安装路径,而不是引用构建目录里的散乱文件。
4.4 OSGEarth 的配置差异
OSGEarth 的 CMake 变量里有两个和 OSG 不一样的关键点。第一是 OSG 查找方式——OSGEarth 通过 find_package(OpenSceneGraph REQUIRED) 来定位 OSG 安装,所以必须保证 CMAKE_PREFIX_PATH 里包含 OSG 的安装目录。第二是依赖库的查找——OSGEarth 直接查找 GDAL、GEOS、CURL、SQLite3 这四个库,对应的 CMake 变量是:
GDAL_INCLUDE_DIR = D:/dev/3rdParty/x64/include GDAL_LIBRARY = D:/dev/3rdParty/x64/lib/gdal.lib GEOS_INCLUDE_DIR = D:/dev/3rdParty/x64/include GEOS_LIBRARY = D:/dev/3rdParty/x64/lib/geos.lib CURL_INCLUDE_DIR = D:/dev/3rdParty/x64/include CURL_LIBRARY = D:/dev/3rdParty/x64/lib/libcurl.lib SQLITE3_INCLUDE_DIR = D:/dev/3rdParty/x64/include SQLITE3_LIBRARY = D:/dev/3rdParty/x64/lib/sqlite3.lib这些变量在第一次 Configure 之后可能显示为 NOTFOUND,需要手动逐项填入。填完后再点 Configure,CMake 会把它们标红并显示找到的文件路径。如果某一行仍然显示 NOTFOUND,多数情况是库文件命名和 CMake 脚本预期不一致,比如 CMake 在找 libcurl.lib,而 3rdParty 包里只有 curl.lib。解决办法是手动把变量改为实际文件名。
5. 避坑与排查:编译 OSG 和 OSGEarth 的常见问题
5.1 现象一:CMake 报错 “Could NOT find GDAL”
配置 OSGEarth 时 CMake 输出红色警告,说找不到 GDAL 库,然后整个 Configure 失败。检查 GDAL_INCLUDE_DIR 和 GDAL_LIBRARY 两个变量,发现它们各自指向了不同的目录——include 指向了 3rdParty 的 include 目录,而 lib 指向了另一个项目里的 gdal.lib。原因是我之前配置过另一个地学项目,系统环境变量里残留了一个 GDAL_ROOT 变量,把 CMake 的查找引偏了。
解决方法是把 CMake 变量强制写死,直接在 CMake GUI 里把 GDAL_LIBRARY 改成 3rdParty 包里的完整路径,同时清掉用户环境变量里的 GDAL_ROOT。从那以后我配置任何带地理依赖的项目,都先在命令行里用 set 检查一遍 GDAL、GEOS、CURL 相关环境变量,确保没有残留干扰项再打开 CMake。
5.2 现象二:Debug 配置下 OSG 编译报 “无法打开文件 zlibd.lib”
编译 OSG 的 Debug 版本时,链接器报错说找不到 zlibd.lib,但 Release 版本一切正常。原因很典型——3rdParty 包里的 zlib 只有 Release 版的 zlib.lib,没有 Debug 版的 zlibd.lib。OSG 的 CMake 脚本在 Debug 配置下会把库名自动追加一个 d 后缀,找不到就失败,但它不会因为找不到而回退到 Release 库名。
解决方式有两种。第一种是在 CMake 配置里找到 ZLIB_LIBRARY_DEBUG 变量,手动指定为 zlib.lib 而不是 zlibd.lib,让 Debug 链接时复用 Release 库。第二种是在 CMake 变量里把 ZLIB_LIBRARY_RELEASE 和 ZLIB_LIBRARY_DEBUG 都填成同一个 lib 文件的路径。类似的情况在 libpng 和 libjpeg 上也可能出现,最省事的做法是先把 3rdParty 包的 lib 目录列一遍,确认所有 xxxd.lib 是否存在,若缺就按这个思路处理。
5.3 现象三:运行时提示 “无法定位程序输入点于 gdal.dll”
OSG 和 OSGEarth 编译安装都成功了,但运行 osgviewer 加载一个 .earth 文件时,Windows 弹窗说 gdal.dll 里找不到某个程序输入点。出现这种错误,几乎可以肯定是操作系统加载了另一个版本的 gdal.dll——PATH 环境变量里同时存在别人的 GIS 软件目录,把那个目录下版本更老的 gdal.dll 优先加载了。比如 QGIS 或 ArcGIS 自带的老版本 GDAL,它们位于系统 PATH 的前面。
排查过程是先看当前进程实际加载了哪个 gdal.dll,用微软的 Process Explorer 或命令行工具。确认后把 3rdParty 的 bin 目录在 PATH 里的位置往前挪,或者干脆把 OSG 运行目录里的相关 DLL 复制一份到 exe 同目录下,Windows 默认优先加载 exe 所在目录的 DLL。“OSG 程序在当前目录找不到 DLL”比“找错 DLL”更好修。
5.4 现象四:OSGEarth 加载地形时 GDAL 数据读取失败
编译全部通过,运行 osgviewer 加载一个本地 GeoTIFF 影像文件,程序没有崩溃但画面上什么都不显示,控制台输出一串 GDAL 相关的 error 日志。检查后发现 3rdParty 包里的 GDAL 版本是 3.4.4,而 OSGEarth 源码里用的 GDAL 版本预期是 3.6.x——API 兼容但某些驱动行为不同,尤其是 GeoTIFF 的空间参考解析上,3.4 和 3.6 的 WKT 处理逻辑有差异。
处理方案是锁定版本链:先确认 OSGEarth 分支发布时搭配的 GDAL 版本区间,再决定是降级 3rdParty 里的 GDAL 还是升级 OSGEarth 源码。遇到这种问题就别在 CMake 层面死磕了,那是编译配置的问题不是版本策略问题。我一般会优先保持 3rdParty 包整体不动,调整 OSGEarth 源码分支版本去适配它,因为整个 3rdParty 里的库彼此有耦合,单独换 GDAL 可能连带需要换 GEOS。
6. 把编译成果跑起来:验证 OSG 与 OSGEarth 安装有效
安装和配置都结束之后,验证是最重要的一步,直接决定你有没有白折腾。先在命令行打开 osgviewer,加载 OSG 自带的示例模型:
osgviewer cow.osg如果窗口弹出并且出现一头牛,说明 OSG 核心和基础插件都是好的。这一步很多人会跳过,直接进入 OSGEarth 环节,然后一旦出问题就分不清到底是 OSG 不行还是 OSGEarth 不行。建议把这个验证动作当作习惯,每次换构建环境都强制走一遍。
接着验证 GDAL 插件链路是否正常:
osgviewer --image 某个本地影像.tif能正常显示影像说明 osgdb_gdal 插件确实在运行。再进一步,写一个最简的 earth 文件来验证 OSGEarth 的整个数据加载链路。新建一个 test.earth,内容如下:
<map> <image name="local" driver="gdal"> <url>某个本地影像.tif</url> </image> </map>用 osgviewer 加载它:
osgviewer test.earth如果能看到影像叠加在地球模型上,那 OSGEarth 的 GDAL 驱动、地形生成逻辑、缓存机制基本都在正常工作。这之后再去碰 http 瓦片源、矢量数据、高程叠加这些高级功能,每一步都用这个最简 earth 文件作为回归基线。
整个编译链路里最让我头疼的不是代码问题,而是环境变量残留和库版本错配——它们不报编译错误,只在你运行时悄无声息地搞破坏。从那以后,我每次新建一套三维渲染开发环境,都强制走一遍完整验证流程,先 osgviewer 跑 cow,再跑 GDAL 影像,最后跑 earth 文件。这套流程虽然只花五分钟,但能挡住后面好几天的排错时间。希望帮到你。
本文还有配套的精品资源,点击获取