简介:面向Windows 10平台的三维图形开发库资源包,基于Visual Studio 2019完成编译,内含OpenSceneGraph 3.6.5与OSGEarth 3.1双版本,均提供Release/Debug构建结果并兼容x64架构。每个版本均具备bin、include、lib三个标准目录,覆盖几何渲染、地形加载、动画控制、标注系统、光照处理、坐标变换等模块,可直接接入三维GIS、仿真可视化、虚拟训练等C++桌面应用项目。压缩包共42个文件,以38个lib库文件为主便于多配置链接,另有demo示例cpp用于快速验证,整体仅3.49MB。目录中可见osgText、osgEarth、osgParticle、osgSim等子模块,以及AnimationPath、AnnotationNode、AlphaFunc等典型类名,可确认关键扩展特性已打开。目前已有37人学习下载,适合需要省去自行编译流程、快速搭建OSG开发环境的开发者使用。
1. 为什么 Win10 上要自己编译 OSG 3.6.5 + OSGEarth 3.1 的 Release/Debug 开发库
接手一个老三维GIS项目时,最怕的不是业务逻辑复杂,而是库本身是个黑匣子:同事U盘里拷来的预编译OSG/OSGEarth只有Release版,Debug下一断点全是汇编,一查依赖还有一半是别的编译器产的。想正经调试,就得有一套在Win10下用VS2019编译的OSG 3.6.5 + OSGEarth 3.1双版本开发库,而且Release/Debug完整目录结构必须分开、纯净、可复现。这套东西不贵,但很花时间,网上搜到的预编译包要么版本对不上,要么目录残缺。如果你和我一样用C++做三维仿真、GIS客户端,这篇就是一次照着走完的完整路径。
2. 编译前置:vs2019 工作负载、第三方依赖与目录规划
2.1 固定版本为什么值得
OSG 3.6.5 是 3.6 系列末期的维护版,对 VS2019 的 v142 工具集支持最稳;OSGEarth 3.1 又恰好是针对 OSG 3.6 API 调整过的版本,两者在接口上是一个相对成熟的搭配。往上走 OSGEarth 3.2 要换一部分 API,往下走 3.0 对 3.6 的兼容补丁不够,卡在这个组合是很多从业者的默认选择。我自己在多个 Win10 版本上验证过,这个组合踩的人多、能搜到的问题也多,适合作为项目基线。
| 组件 | 我选的版本 | 理由 |
|---|---|---|
| 操作系统 | Win10 专业版 / LTSC 2019 | 驱动和显卡兼容面广 |
| 编译器 | VS2019 MSVC v142 | 与 3.6.5 发布时间匹配 |
| 构建工具 | CMake 3.16+ | 支持 VS2019 生成器和--install |
| 三维引擎 | OSG 3.6.5 | 3.6 系列稳定版 |
| 地形引擎 | OSGEarth 3.1 | 匹配 OSG 3.6 API |
| 运行库配置 | Release / Debug 分开 | 避免 DLL 互相污染 |
版本不是越新越好,尤其老项目里用到的 OSG 节点回调、OSGEarth 图层 API 在高版本里改过签名,一旦锁死版本,后续所有坑都在可控范围内。
2.2 别急着搜 vs2019安装教程:先勾对工作负载
很多人第一步就翻车:VS2019 装了但没装 C++ 桌面组件,CMake 生成后半点找不到 cl.exe。打开 Visual Studio Installer,在“使用 C++ 的桌面开发”工作负载里,右侧必须确认勾上“Windows 10 SDK”和“MSVC v142 生成工具”,前者决定能编出 target 为 win10 的代码,后者才是真正的 v142 编译器。
装完先验证工具链,在开始菜单打开“Developer Command Prompt for VS 2019”,执行:
cmake --version clcmake --version确认 CMake 在 PATH 里;cl不带参数会输出一段 MSVC 使用说明和参数列表。如果在普通 cmd 里运行cl报“不是内部或外部命令”,不要慌,这是没进开发者命令行环境,不是没装好。CMake 在生成 VS 工程时其实不需要 cl 在 PATH,但后面排查编译问题时你需要能手动调起编译器。
2.3 第三方依赖:vcpkg 还是手工包
OSG 3.6.5 依赖 zlib、libpng、libjpeg、freetype、curl、tiff,OSGEarth 3.1 还要 GDAL。这些依赖版本一旦和系统里已有的混装,会出现各种玄学链接错误。常见做法有两种:手工下载预编译依赖,或统一用 vcpkg。我选 vcpkg,不是因为它快,而是它能把 Release 和 Debug 两套导入库都按固定 triplet 装好,省掉逐个找包的时间。
git clone https://github.com/microsoft/vcpkg.git cd vcpkg bootstrap-vcpkg.bat -disableMetrics vcpkg install zlib:x64-windows libpng:x64-windows libjpeg-turbo:x64-windows freetype:x64-windows curl:x64-windows tiff:x64-windows gdal:x64-windows安装完成后,依赖会落在installed/x64-windows目录下,头文件共用include,Release 导入库在lib,Debug 导入库在debug/lib。注意不要用vcpkg install osg,vcpkg 里虽然有 osg 包,但咱们要自己编译并控制安装目录,装了反而会在后续find_package时抢路径。装依赖时用同一套 triplet,后续 CMake 的CMAKE_MSVC_RUNTIME_LIBRARY才能统一。
2.4 源码和目录结构规划
源码包从 OpenSceneGraph 和 osgEarth 官方仓库的对应标签下载,解压后建议目录结构固定成下面这样,后续所有命令都以这套路径为基准:
D:/3rd/ |-- src/ | |-- OpenSceneGraph-3.6.5/ | `-- osgearth-3.1/ |-- build/ | |-- osg-release/ | |-- osg-debug/ | |-- earth-release/ | `-- earth-debug/ |-- sdk/ | `-- OSG3.6.5/ | |-- include/ | |-- lib/ | | |-- Release/ | | `-- Debug/ | `-- bin/ | |-- Release/ | `-- Debug/ `-- vcpkg/ `-- installed/build下我分 Release/Debug 两个目录,看似浪费磁盘,但后面你会感谢这个决定:第三方依赖的查找路径、插件 DLL 的生成位置都清晰。sdk/OSG3.6.5是 OSG 的安装前缀,也是 OSGEarth 编译时要找的OSG_DIR。OSGEarth 的安装前缀我单独放在sdk/OSGEarth3.1,最终发布时再合并运行目录,编译期保持隔离。
3. 用 CMake 配置并编译 OSG 3.6.5:Release/Debug 两条命令
3.1 CMake 选项:哪些必须动
用 CMake GUI 配置时,源码目录选D:/3rd/src/OpenSceneGraph-3.6.5,构建目录选D:/3rd/build/osg-release,点击 Configure 后生成器选 “Visual Studio 16 2019”,平台选 x64。第一次 Configure 后密集的红色报错不用慌,逐个看是不是依赖没找到。关键选项按表里改:
| CMake 选项 | 我的设置 | 说明 |
|---|---|---|
CMAKE_INSTALL_PREFIX | D:/3rd/sdk/OSG3.6.5 | 决定头文件、库、DLL 最终落点 |
BUILD_OSG_EXAMPLES | OFF | 开的话编译量翻倍,没必要 |
BUILD_OSG_PLUGINS | ON | 必须开,不然读不了图片模型 |
DYNAMIC_OSG | ON | 生成 DLL 而不是静态 lib |
OPENGL_PROFILE | compatibility | 兼容老显卡驱动,别选 core |
CMAKE_TOOLCHAIN_FILE | D:/3rd/vcpkg/scripts/buildsystems/vcpkg.cmake | 让依赖自动从 vcpkg 找 |
OPENGL_PROFILE是老项目最容易被忽略的一项。很多 Win10 机器的集显驱动只完整支持 OpenGL 2.1,选 core profile 后插件照常编译,但运行时效果会莫名缺失。选 compatibility 最稳。
还有个新手容易混淆的点:VS2019 是多配置生成器,CMAKE_BUILD_TYPE填什么都无所谓,真正的 Debug/Release 由你传入--config或 IDE 里的配置决定。不要把 Linux 下的单配置习惯带过来。
3.2 Release/Debug 两条命令
配置完成后,我一般直接命令行构建,不用 VS 打开工程编译,因为命令行能重复执行、日志干净。先编 Release:
cd D:/3rd/build cmake -S D:/3rd/src/OpenSceneGraph-3.6.5 -B osg-release -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX=D:/3rd/sdk/OSG3.6.5 -DCMAKE_TOOLCHAIN_FILE=D:/3rd/vcpkg/scripts/buildsystems/vcpkg.cmake -DBUILD_OSG_EXAMPLES=OFF -DOPENGL_PROFILE=compatibility cmake --build osg-release --config Release --parallel 8 cmake --install osg-release --config Release第一条cmake -S -B只用一条命令完成配置,不用开 GUI;--parallel 8按 CPU 线程数设,16 核机器可以提到 12。第二条cmake --build编译,--config Release在多配置生成器下指定具体配置。第三条cmake --install把结果安装到CMAKE_INSTALL_PREFIX,这一步经常被漏掉,相当于只编译不部署。
然后同一构建目录直接编 Debug:
cmake --build osg-release --config Debug --parallel 8 cmake --install osg-release --config Debug同一个 build 目录包含 Release 和 Debug 两个配置的产物,安装时 CMake 会按配置把文件放对位置。唯一的前提是 vcpkg 装的依赖同时有 debug 和 release 库,否则 Debug 链接时会报找不到某个导入库。
3.3 安装产物检查
装完后目录里能看到明显的版本规律,OSG 的 Release 库名不带后缀,Debug 库名末尾带d:
D:/3rd/sdk/OSG3.6.5/ |-- include/osg、osgDB、osgUtil、osgViewer... |-- lib/ | |-- Release/osg.lib, osgDB.lib, osgViewer.lib... | `-- Debug/osgd.lib, osgDBd.lib, osgViewerd.lib... `-- bin/ |-- Release/osg.dll, osgDB.dll, osgPlugins-3.6.5/*.dll `-- Debug/osgd.dll, osgDBd.dll, osgPlugins-3.6.5/*d.dll验证方法很直接,运行D:/3rd/sdk/OSG3.6.5/bin/Release/osgversion.exe,能打印出 3.6.5 版本号说明主程序和插件版本匹配。这里第一印象最容易骗人:Release 插件叫osgdb_png.dll,Debug 插件叫osgdb_pngd.dll,只差一个 d,拷运行目录时经常带错。
注意:Debug 的 osgPlugins-3.6.5 目录里是带 d 的插件 DLL,如果和 Release 的主程序混用,读图会静默失败。
4. 编译 OSGEarth 3.1:GDAL、OSG_DIR 与双目录合并
4.1 让 CMake 找到 OSG
编译 OSGEarth 前,最常翻车的不是代码,而是 CMake 找不到 OSG。OSGEarth 的 CMake 脚本通过find_package(OSG)定位,它查的是安装前缀下的lib/cmake/OpenSceneGraph/OSGConfig.cmake,不是 include 目录。所以OSG_DIR要指到D:/3rd/sdk/OSG3.6.5,别指到include里。
配置命令:
cd D:/3rd/build cmake -S D:/3rd/src/osgearth-3.1 -B earth-release -G "Visual Studio 16 2019" -A x64 -DOSG_DIR=D:/3rd/sdk/OSG3.6.5 -DCMAKE_PREFIX_PATH=D:/3rd/sdk/OSG3.6.5;D:/3rd/vcpkg/installed/x64-windows -DCMAKE_TOOLCHAIN_FILE=D:/3rd/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX=D:/3rd/sdk/OSGEarth3.1 -DOSGEARTH_BUILD_EXAMPLES=OFFOSG_DIR给 OSGEarth 提供 OSG 的安装位置;CMAKE_PREFIX_PATH同时塞进了 OSG 前缀和 vcpkg 的 installed 目录,让 GDAL、CURL 等库也能被找到。Configure 最后几行会打印Found OpenSceneGraph: D:/3rd/sdk/OSG3.6.5 (found version 3.6.5),看到这个再继续,否则后患无穷。
4.2 OSGEarth 开关与 GDAL
Configure 完成后,过一遍 OSGEarth 自己的选项:
| CMake 选项 | 我的设置 | 理由 |
|---|---|---|
OSGEARTH_BUILD_EXAMPLES | OFF | 示例依赖大量第三方数据 |
OSGEARTH_BUILD_TESTS | OFF | 测试代码拖慢编译 |
OSGEARTH_USE_GDAL | ON | 读 shp/tif 必开 |
OSGEARTH_USE_CURL | ON | 加载网络瓦片需要 |
OSGEARTH_USE_FONTFILL | 保持默认 | 与字体栅格化相关 |
GDAL 版本不用强求最新。vcpkg 默认装的 GDAL 版本如果报“版本太旧”,就在 vcpkg 里升一个具体版本号重新装,别手工去改 OSGEarth 源码里的宏。Debug 和 Release 两套 GDAL 都要有,否则 OSGEarth 的 Debug 工程链接会报LNK1104 cannot open file gdal.lib。
4.3 编译与目录收拢
OSGEarth 的 Release 和 Debug 构建命令和 OSG 一致,同一个 build 目录切两次:
cmake --build earth-release --config Release --parallel 8 cmake --install earth-release --config Release cmake --build earth-release --config Debug --parallel 8 cmake --install earth-release --config Debug安装完,OSG 和 OSGEarth 各有一份 include、lib、bin。运行时我不会把两套 bin 直接混到一个目录,而是收拢成下面这样:
D:/3rd/runtime/ |-- Release/ | |-- osg.dll, osgDB.dll, osgEarth.dll 等 | |-- osgPlugins-3.6.5/ | `-- osgPlugins-3.6.5/osgearth_* (地形插件) `-- Debug/ |-- osgd.dll, osgDBd.dll, osgEarthd.dll 等 |-- osgPlugins-3.6.5/ `-- osgPlugins-3.6.5/osgearth_*d这样处理是因为 Windows 加载 DLL 按 PATH 顺序,Release 和 Debug 混一起,Debug 程序加载到 Release 的 osg.dll 是必然事件。分开后,Debug 工程运行时把D:/3rd/runtime/Debug放在 PATH 最前,Release 工程反之,干净利落。
5. 避坑:Win10 下编译这两个库的 5 条翻车记录
5.1 编译链接期的 3 条翻车记录
现象一:OSG 编译到 osgDB 插件时报fatal error C1083: Cannot open include file: 'curl/curl.h'。明明 vcpkg 装了 curl,CMake 也提示找到依赖,还是报错。
原因:vcpkg 里安装的包没问题,但 OSG 的 CMake 缓存里还残留着第一次 Configure 时“找不到 curl”的状态;另外 curl 的头文件路径没被写进缓存变量。
解决:先确认vcpkg list里有 curl,然后删掉 build 目录下的CMakeCache.txt,重跑 Configure。如果还报,手工给CURL_INCLUDE_DIR和CURL_LIBRARY各填一次 vcpkg installed 里的路径再 Generate。这个坑十有八九是缓存害的,不是依赖没装。
现象二:Debug 链接时一堆LNK2038 mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug',Release 却正常。
原因:某个第三方库是静态 CRT 编译的(/MTd),而你项目是动态 CRT(/MDd),OSG 和 OSGEarth 的默认设置不统一也会触发。手工下载的第三方依赖包里最容易出现这个。
解决:统一走 vcpkg 默认 tripletx64-windows,它的 CRT 链接方式是动态的;同时检查 CMake 里CMAKE_MSVC_RUNTIME_LIBRARY,把它设为MultiThreadedDLL和MultiThreadedDebugDLL。如果哪条链接还报商,找到具体是哪个 lib,去换对应 triplet 的版本,别硬改工程配置。
现象三:链接时报LNK1104 cannot open file 'osg100.lib',或者明明有 osgd.lib 还提示unresolved external symbol。
原因:Debug 安装目录下没有生成带 d 后缀的导入库,或者安装时两个配置互相覆盖。OSG 的CMAKE_DEBUG_POSTFIX在部分自定义配置下会被清空,导致 Debug 输出文件名和 Release 一样。
解决:在 OSG 的 CMakeCache 里确认CMAKE_DEBUG_POSTFIX为d,然后删掉 sdk 下的 Debug 目录重装一次。保险起见,安装 Debug 和 Release 时分别确认 bin 和 lib 目录里 osgd.dll 和 osgDBd.lib 都在。
5.2 运行期的 2 条翻车记录
现象四:Debug 版本 exe 双击直接报0xc000007b,或者启动时报无法定位程序输入点于动态链接库 osg.dll。
原因:PATH 里同时存在 Release 和 Debug 的 bin 目录,Windows 按 PATH 顺序找 DLL,优先加载了 Release 的 osg.dll。这在 Win10 下尤其隐蔽,因为系统不会提示“版本不对”,只会报个模棱两可的错误码。
解决:运行前确认当前 cmd 的环境变量,用echo %PATH%看谁在前面。我一般不在全局 PATH 里加任何开发库目录,只在工程调试环境里设置set PATH=D:/3rd/runtime/Debug;%PATH%,让 Debug 目录绝对靠前。这条规则我在 Win10 专业版和 LTSC 2019 上都复现验证过,不是环境特异问题。
现象五:程序能跑,但读 tif 或者图片时报could not find plugin to read objects from file,Release 和 Debug 都会偶发。
原因:osgPlugins-3.6.5目录不在 DLL 搜索路径里。OSG 的插件加载器不会去当前 exe 同级目录自动找插件,它按OSG_LIBRARY_PATH环境变量的指引找,这个变量没设就会漏。
解决:写代码时在所有读文件之前设置:
osgDB::Registry* reg = osgDB::Registry::instance(); reg->setLibraryFilePathList("D:/3rd/runtime/Release/osgPlugins-3.6.5");或者更省事,在系统环境变量里建一个OSG_LIBRARY_PATH,指向插件目录。注意 Debug 和 Release 各设一次,或者运行时临时切换,否则又会踩回“带 d 和不带 d 混用”的坑。
6. 把开发库接进工程:验证最小样例与 Release/Debug 一键切换
6.1 最小验证程序
拿到开发库后先别急着接业务代码,写一个最小样例跑通,确认 OSG 与 OSGEarth 的链接、插件加载、Debug 断点三条链路都是通的。
#include <osgViewer/Viewer> #include <osgEarth/MapNode> #include <osgEarth/EarthManipulator> #include <osgDB/ReadFile> int main(int argc, char** argv) { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(argc > 1 ? argv[1] : "tif.earth"); if (!node.valid()) return 1; viewer->setSceneData(node.get()); viewer->setCameraManipulator(new osgEarth::Util::EarthManipulator); return viewer->run(); }对应的 CMakeLists 里用 find_package 而不是写死库路径:
find_package(OpenSceneGraph REQUIRED COMPONENTS osgDB osgViewer) find_package(osgEarth REQUIRED) add_executable(min_test main.cpp) target_link_libraries(min_test ${OSGEARTH_LIBRARIES} ${OPENSCENEGRAPH_LIBRARIES})这样 Debug 和 Release 会各自链接到带 d 和不带 d 的库,不会串。CMake 配置时记得加-DCMAKE_PREFIX_PATH=D:/3rd/sdk/OSG3.6.5;D:/3rd/sdk/OSGEarth3.1。
6.2 用 props 一键切 Debug/Release
最后分享一个我最常用的技巧:在 VS2019 的属性管理器里建一份osg365.props,把 Release/Debug 的库名和目录条件化写进去:
<Project> <ItemDefinitionGroup Label="OSG"> <ClCompile> <AdditionalIncludeDirectories>D:\3rd\sdk\OSG3.6.5\include;D:\3rd\sdk\OSGEarth3.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <AdditionalLibraryDirectories Condition="'$(Configuration)'=='Release'">D:\3rd\sdk\OSG3.6.5\lib\Release;D:\3rd\sdk\OSGEarth3.1\lib\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories Condition="'$(Configuration)'=='Debug'">D:\3rd\sdk\OSG3.6.5\lib\Debug;D:\3rd\sdk\OSGEarth3.1\lib\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalDependencies Condition="'$(Configuration)'=='Release'">osgDB.lib;osgViewer.lib;osgEarth.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies Condition="'$(Configuration)'=='Debug'">osgDBd.lib;osgViewerd.lib;osgEarthd.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> </Project>这份 props 丢到工程里后,切换配置时会自动指向对应目录和带 d 的库名。我的习惯是换一台 Win10 重装完系统后,先跑一遍 osgversion 和这个最小样例,确认环境变量和插件路径没问题,再把 props 交给工程。这套流程走顺了,半天就能把一台新机器恢复到可编译状态。希望帮到你。
本文还有配套的精品资源,点击获取