ARTICLE DETAIL

资讯详情

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

osgEarth 2.10 demo 全解析:从地形渲染到三维GIS开发实战

osgEarth 2.10 demo 全解析:从地形渲染到三维GIS开发实战 如果你准备在项目里用 osgEarth 做三维地形开发那你大概率会和我一样先从官网下载源码编译然后打开一个叫 demo 的目录。这个目录在 osgEarth 2.10 里一直存在里面是几十个可以直接运行的演示程序很多人却只是随便点开一两个看个热闹然后就去试着自己写代码。我建议你把它们当成一套免费的地形渲染实战教材来看。这篇文章要说的就是 osgEarth 2.10 的 demo 到底藏了哪些功能每个 demo 能帮你解决什么问题以及怎么从这些 demo 里挖掘出能直接抄进自己项目的代码。看完之后你至少能少走我当年走过的一半弯路。1. osgEarth 2.10 demo 的整体设计思路与价值1.1 为什么官方要把功能拆成这么多小 demoosgEarth 是个基于 OpenSceneGraph 的地形渲染引擎核心能力是加载海量影像和高程数据、实时动态分页、叠加矢量与标注。2.10 虽然是老版本但它的整体架构已经非常成熟官方把功能拆成一个一个独立的可执行程序放在 applications 目录下每个 demo 只负责演示一个特性。这么做的好处很直接你想了解影像加载就去跑 osgearth_imagery你想看高程处理就去跑 osgearth_elevation你想搞明白物体贴地压平就去跑 osgearth_clamp。每个 demo 的代码量都不大通常在几百行以内刚好是“还能看明白”的范畴。这种设计思路对于学习的价值是非常大的。你不需要一开始就啃整个引擎源码只要挑一个和你需求最接近的 demo把代码读一遍再运行起来看效果很快就能建立“这个功能是怎么实现的”概念。我当年就是从 osgearth_viewer 这个最简单的 demo 入手的通过改 earth 文件里的数据源理解了整个地形渲染管线和数据组织方式。后来做项目时遇到问题第一反应也是去 applications 目录里搜有没有对应的 demo有的话直接复制代码改改基本就能跑出原型。1.2 demo 目录结构给你什么信息2.10 版本的 demo 都放在源码的 src/applications 目录下每个 demo 是一个独立的小工程名字基本都是 osgearth_ 开头。编译成功之后所有 demo 会生成到同一个输出目录你可以在命令行里逐个运行。目录结构本身就在告诉你两件事第一osgEarth 鼓励模块化开发想加点功能就新建一个 osgEarth 应用而不是把代码堆在地形节点里第二所有 demo 共享同一套底层库比如 osgEarth、osgEarthUtil、osgEarthFeatures 这些所以你在自己的项目里引用的库名其实和 demo 里的引用是完全一致的。还有一个容易忽略的点每个 demo 里面都有一个或多个 earth 文件。这些文件才是这个引擎的灵魂。earth 文件的本质是一个 XML 格式的文本用来声明数据源、图层、渲染选项等demo 运行时会解析它然后动态构建地形场景。你可以把 earth 文件类比成数据库的连接配置改了它几乎不用改代码就能换数据源、换投影、换渲染效果。搞懂这些 demo 的 earth 文件比搞懂 C 代码更重要因为实际项目中你百分之七十的时间都在调 earth 文件参数。2. 核心 demo 功能分类与关键参数2.1 影像与地形加载类最容易上手的 demo 是 osgearth_viewer它基本是 osgEarth 的“hello world”。这个程序不做任何复杂的事只是读取命令行指定的 earth 文件然后创建一个窗口把地形显示出来。它里面会创建一个 osgEarth::MapNode 节点挂到场景里再启用相机控制器让你可以鼠标拖拽旋转、滚轮缩放。看这个 demo你能学到最基础的地形加载流程以及如何把 osgEarth 集成进一个普通的 OSG 程序。另一个非常实用的是 osgearth_imagery它专门测影像数据源。影像数据源有很多种比如本地图片、WMS 服务、TMS 切片、MBTiles 文件甚至内存里的图像。这个 demo 会在窗口里列出几个可切换的影像图层你可以直观看到不同数据源的加载效果和清晰度。这里有个关键点osgEarth 2.10 默认支持的影像格式和扩展插件可能没有新版那么多如果你遇到某种格式加载不了先看插件是不是没编进去很常见。高程加载类必须提 osgearth_elevation。地形的高度数据通常是一张灰度图或一个高程服务引擎根据灰度值把平面网格顶点抬起来。这个 demo 展示了如何给地形添加高程层、如何设置高程的垂直比例、如何让高程和影像数据叠加。说个容易踩的坑有时候你加载了高程数据但整个地形看起来还是平的原因多半是高程范围太小或者影像盖住了细节。把 osgearth_viewer 里的 earth 文件里高程层的 min/max 或 multiplier 参数调整一下效果立刻不一样。2.2 矢量数据与标注类矢量数据在地形引擎里指的是点、线、面通常来自 SHP、GeoJSON、KML 这些文件。osgearth_vector 和 osgearth_features 这两个 demo 就是专门展示矢量图层加载与样式化的。它们可以给一个行政区划文件填充半透明颜色给一条道路画成带边框的粗线还能让某些区域显示成多边形的“大棚”效果。掌握了这些 demo你就能在三维地形上叠加业务数据比如人口分布、管网走向、地块边界。标注类 demo 集中在 osgearth_annotation。这个 demo 是我做项目时用得最多的因为它在三维地球上放文字、放图标、放自带弹窗的标记还能让标注始终朝向相机不会因为视角转动而变模糊。它内部用的是 osgEarth::Annotation 命名空间里面有 TextNode、PlaceNode、LabelNode 等一堆现成节点。你只需要传入经纬度坐标和内容它就会自动帮你算屏幕位置、做遮挡剔除。如果你要做类似“点击地物弹出信息面板”的功能这个 demo 值得反复读。这里我顺手整理了一份我常用的 demo 功能对照表方便你按需求速查demo 名称核心功能适合场景osgearth_viewer加载 earth 文件并显示地形最基础的入门和调试osgearth_imagery切换影像数据源验证数据源是否可用osgearth_elevation叠加高程数据地形立体感调整osgearth_vector矢量图层加载与样式业务数据可视化osgearth_annotation文字、图标标注标注、POI 显示osgearth_manip相机操控与周视旋转了解摄像头运动模型osgearth_pick地理坐标拾取点选、坐标查询osgearth_views多视口同步渲染大屏、指挥系统osgearth_measure距离面积测量量算工具osgearth_graticule经纬网格绘制地图辅助显示osgearth_clamp模型贴地放置建筑、坦克、车辆布设osgearth_splat地表纹理混合模拟草地、砂石、雪地2.3 环境交互与相机控制类osgEarth 2.10 里相机控制器的实现分布在 osgEarthUtil 库中osgearth_manip 这个 demo 会把几种控制器都列出来供测试。常见的有 TrackballManipulator轨迹球、OrbitManipulator围绕目标点旋转、FirstPersonManipulator第一人称。项目里做三维 GIS 一般用 Orbit 比较多因为它能让用户始终围绕一个关注点浏览。用这个 demo你可以实时切换控制器体验不同操控手感然后决定你的项目选哪套。osgearth_pick 也很有价值。它演示的是鼠标点选场景后把屏幕坐标反算成经纬度和高程。这个功能在业务系统里太常用了比如用户点击地图上的设备图标需要知道它在哪个经纬度或者用户在地表上点击系统要弹出一个坐标标记。这个 demo 里会用 osgUtil::IntersectionVisitor 去做线段和地形节点的求交拿到交点后通过 MapNode 的变换矩阵把局部坐标转成世界地理坐标。你把这段代码摘出来放到自己的工程里几乎不用改就能用。2.4 特效与工具类需要注意的细节很多特效 demo 看起来炫但在 2.10 里对显卡和 OpenGL 版本要求比较高。比如 osgearth_splat 做地表纹理混合效果很像很多游戏中草地和泥地自然过渡的样子但它需要多纹理单元和着色器支持老显卡上可能会直接黑屏。我建议你在自己的电脑上跑一遍机器配置足够的话再用到项目中否则后期维护成本会很高。osgearth_measure 是一个很实用的小工具 demo它演示了在地球表面测量两点距离、测量多边形面积还能画折线。实现原理不难把用户鼠标点的屏幕位置转成经纬度再把经纬度连成线段/多边形用椭球面上的大圆距离公式计算。如果你项目里需要“标尺”“测距”这类功能这个 demo 就是现成模板。我实际用它做过一个应急系统里的测距功能改改样式和单位就上线了。3. 实操从编译到运行 osgEarth 2.10 demo3.1 编译前的环境准备编译 demo 之前你的机器上得有完整的 osgEarth 依赖链。osgEarth 2.10 依赖 OpenSceneGraph简称 OSG通常用 3.6.x 版本编译比较稳。另外还少不了一些基础库比如 zlib、libcurl、sqlite3、gdal、freetype、geos。如果不想自己一个个去编译这些玩意儿可以先下载 OSG 官方预编译包然后下载 osgEarth 源码用 CMake 指定 OSG 目录它会自动找其他依赖。我自己常用的一个组合是Windows 10 Visual Studio 2017 OSG 3.6.5 osgEarth 2.10。库的位数必须统一要么全 x64要么全 Win32混着你编译到一半会发现各种链接错误。另外我建议把 OSG 的 bin 目录和 osgEarth 的 bin 目录都加到系统 PATH 环境变量里否则运行 demo 时会提示找不到 DLL。3.2 用 CMake 配置工程并编译下载好 osgEarth 2.10 源码后打开 CMake GUI指定源码目录和构建目录。构建目录随便建比如 build-win64。在 CMake 配置项里先设置 OSG_DIR 指向 OSG 的安装根目录。还要注意勾选 BUILD_OSGEARTH_APPS这个选项控制是否生成 demo 应用工程。如果你只想要库不勾也行但我们的目标是看 demo所以必须勾上。配置好之后点击 Generate 生成 Visual Studio 工程。然后用 VS 打开生成的 osgEarth.sln把解决方案配置改成 Release平台改成 x64。在“生成”菜单里选择“生成解决方案”这个过程会编译所有库和 demo耗时可能比较久。编译完成后到 build/bin 或 build/bin/Release 目录下你会看到一堆 osgearth_*.exe 文件和若干示例数据文件。我建议先跑一次 osgearth_viewer指定官方自带的 earth 文件能出地球就说明编译成功。3.3 运行 demo 的标准操作大部分 demo 都接受一个 earth 文件路径作为命令行参数。以 osgearth_viewer 为例命令行这样写osgearth_viewer.exe samples/earth/simple.earth如果一切正常屏幕上会弹出一个三维窗口可以看到一个纹理较简单的地球或局部地形。鼠标左键旋转、中键平移、滚轮缩放。如果没带参数有些 demo 会弹出使用说明列出支持的参数。还有一部分 demo 不需要 earth 文件比如 osgearth_manip它内部会生成一个默认地图来演示控制器。值得说明的是demo 默认数据源有些是从网络加载的。比如某些 earth 文件里写的影像服务地址如果网络不通或者服务停了你看到的可能就是黑的地球。解决办法是把 earth 文件里的 image 层换成本地数据或者干脆用 tms 缓存。osgEarth 2.10 支持在 earth 文件里加cache typesqlite配置能加快重复加载的速度。3.4 修改 earth 文件快速验证功能我把看懂 earth 文件作为 osgEarth 入门的第一课。下面是一个极简的 earth 文件也是最典型的 demo 结构map nameMyMap typegeocentric image nameBlueMarble drivertms urlhttp://example.com/tiles/url /image elevation nameSRTM drivertms urlhttp://example.com/elevation/url /elevation /mapmap标签声明一个地图typegeocentric表示全球椭球地图image和elevation分别声明影像层和高程层。driver 是必备属性它决定了数据源类型。常见的 driver 有 tms、wms、gdal、agglite、tilecache不同 driver 有不同的扩展参数。你改完这个文件保存再用 osgearth_viewer 打开就能看到新数据源的效果。如果你希望高程起伏更明显可以在 elevation 标签里加multiplier或者设置min/max。比如设置垂直夸张系数 3.0山体就会显得更立体。我经常这么干先开 osgearth_viewer 调 earth 参数调到满意后再去写代码这比每次改代码重新编译高效得多。记住osgEarth 的配置驱动思想贯穿所有 demo编程只是最后一步。4. 常见问题与排查技巧实录4.1 影像加载不出来的常见原因这是新手问得最多的问题。跑 demo 时地球窗口是黑的或影像层没有出现。原因就那么几类第一earth 文件里的 url 指向的是一个需要网络的地址而你的机器访问不了第二url 写的是相对路径但 demo 的工作目录不对导致找不到本地文件第三数据源插件没编进去比如 tms 的插件缺失。排查步骤我建议是先看命令行窗口有没有报错日志。osgEarth 会打印加载信息看到“Failed to open ...”基本就是路径或网络问题。其次用浏览器手动打开 earth 文件中的 url看是否能正常访问。如果确实不想依赖网络就把数据源改成本地缓存或本地文件。另外确认一下生成的 exe 和 earth 文件不在同一个目录时尽量用绝对路径避免很多麻烦。4.2 黑屏或地形无起伏黑屏除了数据源问题还可能是显卡驱动太老OpenGL 版本不够。osgEarth 2.10 用了不少着色器旧驱动编译着色器失败就什么都画不出来。你先跑一个纯 OSG 的例子比如 osgviewer如果这个都黑屏那就是驱动问题先更新显卡驱动。地形无起伏则多半是数据问题。有些高程数据范围很小比如只有一两米的起伏在全局视角下肉眼根本看不出来。这就需要在 elevation 标签里设置 scale。我试过把 SRTM 高程数据加载进去默认看起来是平的加上scale5.0/scale后山地轮廓立刻清楚。这个技巧在展示大范围地形时非常实用但要控制尺度过度夸张会导致等高线变形。4.3 中文路径和编码问题Windows 下做项目时我常遇到中文路径导致的地形加载失败。osgEarth 在读取 earth 文件和本地数据时如果路径包含中文底层某些插件会拿不到正确的 UTF-8 字符串直接报错。解决办法很简单所有数据、代码、输出目录都避免出现中文。这看起来有点土但是最省事的方案。实在绕不开中文路径可以试试在 earth 文件里把路径写成相对路径有时能碰巧绕过编码问题但不可靠。还有一种情况是 earth 文件内部文本编码不是 UTF-8导致 XML 解析出错。你用记事本编辑 earth 文件时保存的时候一定要选择 UTF-8 编码。在 Linux 下一般没问题但 Windows 的记事本默认会用 ANSI 保存一旦里面有中文注释就会解析崩溃。这个坑我踩过好几次后来干脆所有 earth 文件手写注释只写英文。4.4 内存占用过高和加载缓慢第一次跑大型地图时你会发现内存占用涨得飞快加载半天不出影像。这可能是 osgEarth 在地形分页时同时请求了太多瓦片。2.10 版本提供了不少缓存和调度参数例如在 map 标签或 options 里可以限制并发请求数。简单的方式是在 earth 文件里加上options maxLOD17/maxLOD maxRange500000/maxRange /options其中 maxLOD 控制最大细节层级maxRange 控制地形实际加载的距离。数值越大越精细内存和 CPU 消耗也越高。建议先调小看流畅度再逐步增大。如果你的数据源是网络影像还要考虑缓存比如加cache typefilesystem或cache typesqlite来存瓦片第二次加载就会快很多。实测下来sqlite 缓存比较稳而且文件数量少不会撑爆 inode。5. 从 demo 代码到二次开发的借鉴思路5.1 demo 就是最好的代码模板很多初学者喜欢到处找 osgEarth 的项目源码其实官方 demo 就是最权威的参考。以 osgearth_viewer 为例它的核心代码就几行创建一个 MapNode、设置场景、初始化视口、进入渲染循环。你要做自己的地形展示程序完全可以以它为骨架把窗口类换成 MFC、Qt或者纯 Win32。我自己的项目就是在 osgearth_viewer 基础上扩展的加了事件处理和自定义工具栏基本没踩什么坑。读 demo 代码时学会区分哪些是 osgEarth 的 Api哪些是通用 OSG 代码。比如 MapNode、Map、Viewpoint 这类是 osgEarth 的Group、Node、MatrixTransform 则是 OSG 的。只要分清了找资料时就知道往哪个方向查。我习惯把关键调用点记成一张速查表遇到同样需求直接复制 demo 里的代码块再根据项目改个参数。5.2 学习 earth 文件的配置语法earth 文件是 osgEarth 最大的亮点。你写一个 earth 文件就等于配置了一个完整的场景数据源。很多功能不需要改一行 C 代码只要在配置里加上对应的 layer就能叠加新的数据。我建议每个打算长期用 osgEarth 的人都建立一个自己的 earth 文件库把常用数据源、配色、特效都存成模板。需要的时候复制一份再修修改改效率非常高。你要重点理解几个标签组合map 是最外层容器image 是影像层elevation 是高程层vector 是矢量层model 是模型层。每个 layer 都有一堆通用属性比如 name、driver、url、cache、min_level、max_level。这些配置组合在一起就能灵活控制显示效果和性能。官方 demo 里提供了大量范例你可以在源码的 samples 目录里按需查看。5.3 建议的组合练习路径如果你是为了项目而学习我给你一个经过验证的练习顺序。先跑通 osgearth_viewer然后改用本地影像数据再看看 osgearth_elevation 加高程然后叠加一个矢量文件到 osgearth_vector接着试着用 osgearth_annotation 给重要地物加标签。这一套走完你就已经具备做一个三维 GIS 原型的能力了。接下来可以挑战 osgearth_pick 和 osgearth_measure这两个是做交互功能必备的。把这些 demo 串起来其实就是一个完整的业务系统雏形加载地形、加数据、加标注、做交互、做量算。我当年做一个园区三维可视化项目时就是这样一步步把 demos 组合成最终产品。先在 demo 里验证每个功能然后把多个 demo 的代码整合到一个工程最后用 UI 框架包装一下整个过程比从零开始写要节省至少一半时间。5.4 关于版本升级的一点建议2.10 是 osgEarth 的经典版本网上资料多稳定性也不错。但它毕竟不是最新版有些 API 在新版本里已经被替换或改名了。如果你只是做学习或者中小型项目2.10 完全够用如果你要长期维护大型系统建议看下 3.x 的新版很多思想是相通的。不过 2.10 的 demo 依然是很好的入门教材毕竟新版本的 demo 数量更多但核心流程是一样的。我在实际使用中最深的体会是osgEarth 的复杂不在地形渲染本身而在数据源、坐标系、性能这些工程化的东西上。demo 能帮你把每个环节拆开理解但最终要靠你去实际组合、调参、优化。把官方给的这些示例认真过一遍比在网上找碎片化的教程靠谱得多因为它是完整的、可运行的、能自己改的。
返回列表