OSG / osgEarth 入门知识体系 我自己是初学者入行搞这个差不多两个月了一直处于迷迷糊糊的状态今天本着自己学习的态度一起来总结一下OSG/osgEarth的知识体系希望对初学者有帮助。假设你有一张纸纸上画了一棵树这就是二维2D。但是现实生活中树是立体的你可以绕着树走可以从前面看、后面看还可以飞到天上看这就是三维3D。电脑想要画出这样的世界需要有人帮它这个帮手就是OSG。OSGOpenSceneGraph可以理解成一个会搭积木的机器人。它负责告诉电脑这里有一棵树那里有一个房子那里有一辆车然后电脑就能把整个三维世界画出来。实际上电脑里面不是画画而是很多很多三角形。例如一个正方形电脑实际上画的是两个三角形。因为GPU最喜欢画三角形。所以OSG就是负责管理这些三角形。OSG名字里面有个Graph其实不是数学里的图而是一棵树树状结构。例如世界 │ ├──天空 │ ├──地面 │ ├──汽车 │ ├──轮子1 │ ├──轮子2 │ ├──轮子3 │ └──轮子4 │ └──房子 ├──门 └──窗户是不是像文件夹OSG就是这样管理所有东西。所以叫Scene场景Graph树状结构OSG里面最重要的东西叫Node节点。可以理解成乐高积木节点可以是一棵树一辆车一个房子等所有东西都可以是一个Node。还有OSG里面的groupgroup就是一个盒子他只会装东西不会显示。GeodeGeometry Node是真正画东西的节点。Geode里面放Geometry例如一棵树就是10000个三角形一个房子就是50000个三角形Geometry就是真正的模型OSG最后都是Geometry。Viewer可以理解成摄像机例如如果没有摄像机你什么都看不到。Viewer负责打开窗口接收鼠标接收键盘调GPU每秒刷新60次所以程序一般都有它就是整个窗口。Viewer里面还有Camera。Viewer像电影院Camera像摄影师摄影师站哪里观众就看到哪里。Camera移动观众看到的视角就变化了看到的世界就变了。Manipulator就是鼠标控制器例如你按住鼠标左键拖一下地图就会旋转。Manipulator鼠标移动- camera移动-画面变化。OSG负责建立场景树- 管理模型-管理灯光-管理纹理-管理相机-交给OpenGL画。注意OSG自己不会画。真正画的是OpenGL。OSG只是帮你组织。就像导演不会自己去演戏真正干活的是GPU。OSG只是会管理GPU画三维世界但是不会画地球。因为OSG不知道例如北京在哪里东京在哪里GPS是什么经纬度又是什么等。于是有人在OSG上面写了osgEarth。一句话osgEarth等同于OSG 地图。例如OSG会画汽车osgEarth知道汽车的具体位置在地球的那个地方。osgEarth多了哪些东西它认识地球经纬度海拔地图瓦片影像DEM高程行政区WMSWMTSGeoTIFFShapefile等这些OSG 都没有。为什么需要osgEarth例如你想画北京。如果只有OSG你要自己画地球- 画中国- 画北京 -贴地图-算经纬度等工作量巨大。但是如果有osgEarthmapNode一句, 整个地球就出来了。MapNode可以理解成整个地球所有东西都放这里。例如MapNode ├──影像 ├──高程 ├──道路 ├──建筑 ├──飞机 ├──无人机 └──标记是不是和OSG树一样因为MapNode其实也是Node。上面是通俗易懂的厘清了OSG和osgEarth相关的一些概念后续就是实用角度梳理OSG/osgEarth的概念。一、它们各自解决什么问题库角色一句话OpenSceneGraph (OSG)通用 3D 场景图引擎管「节点、相机、渲染、事件、文件读写」osgEarth基于 OSG 的地理可视化引擎管「地球、地图、瓦片、投影、地形、矢量叠加」关系osgEarth 依赖并扩展 OSG不是替代 OSG。写 osgEarth 程序时渲染循环、相机、节点树仍是 OSG 的地球内容挂在MapNode等节点上。二、OSG 核心场景图思维2.1 场景图是什么OSG 用 有向无环图DAG 组织场景叶子节点几何、文字等「可画的东西」组节点组织子节点、做变换、做状态切换每帧从根节点向下遍历cull再绘制draw常见节点类型类型作用osg::Group普通组挂多个子节点osg::Transform/MatrixTransform/PositionAttitudeTransform局部坐标系变换osg::Geode旧/osg::GeometryDrawable几何数据承载osg::Switch开关子节点显隐osg::LOD/PagedLOD按距离/屏幕大小换细节osg::Camera相机也可嵌套做 RTTosg::StateSet材质、纹理、光照、shader 等状态入门口诀节点管结构StateSet 管怎么画Drawable 管画什么。2.2osg::Node/osg::Group/osg::GeodeNode所有节点基类可挂UpdateCallback、CullCallback、EventCallback。Group可addChild/removeChild是场景组织的主力。GeodeGeometry Node传统上专门挂Drawable较新 OSG 也常直接把Geometry当叶子用。2.3StateSet状态集——很容易被忽视但极关键StateSet描述渲染状态可挂在任意节点上向下继承纹理、材质、光照开关GL_DEPTH_TEST、混合、面剔除Shader / Uniform渲染 bin透明排序等要点子节点可覆盖父节点状态setMode/setAttribute/setTextureAttribute是三类常用接口改状态比改几何更常见性能也更敏感2.4 变换节点MatrixTransform任意 4×4 矩阵平移旋转缩放PositionAttitudeTransform位置 姿态四元数 缩放语义更直观CoordinateSystemNode和地理坐标系相关时常见osgEarth 大量用地理坐标转换注意OSG 默认常是 右手系相机看向 -Z上方向 Y具体以你用的 Viewer/相机设置为准。三、osgViewer应用的「外壳」3.1 Viewer 到底是什么osgViewer::Viewer或CompositeViewer是应用主循环的中枢负责创建/管理 GraphicsContext窗口、OpenGL 上下文持有 Camera主相机挂载 SceneData场景根节点驱动 Event / Update / Cull / Draw 四阶段管理 操作器CameraManipulator鼠标旋转、平移、缩放最小心智模型Viewer├── GraphicsWindow / Context├── Camera投影 视口 清屏├── SceneData你的根 Group / MapNode├── CameraManipulatorEarthManipulator 等└── 事件处理器键盘、HUD 等3.2 典型生命周期osgViewer::Viewer viewer;viewer.setSceneData(root); // 挂场景viewer.setCameraManipulator(...); // 交互viewer.setUpViewInWindow(x,y,w,h); // 或全屏 / 嵌入 Qtwhile (!viewer.done()) {viewer.frame(); // 一帧事件→更新→裁剪→绘制}或viewer.run(); // 内部循环调用 frame()3.3ViewervsCompositeViewerViewerCompositeViewer场景/视图通常一个主视图多个View用途单窗口应用多窗口、多显示器、主从视图复杂度低高共享场景或独立场景都可入门先用Viewer即可。3.4 相机osg::Camera在 Viewer 里的角色主相机通常由 Viewer 创建你可设置投影透视Perspective/ 正交Ortho视口像素区域Clear mask / clear colorRender Order嵌套相机做 HUD、后处理、RTTosgEarth 里经常还有地形相机 / overlay 相机MapNode内部管理的多 pass 渲染入门阶段先把「主相机看向场景」弄清再碰嵌套相机。3.5 操作器ManipulatorOSG 自带TrackballManipulator绕物体转模型查看FlightManipulator/DriveManipulator飞行/驾驶TerrainManipulator贴地感更强osgEarth 常用osgEarth::Util::EarthManipulator地球导航旋转地球、缩放高度、倾斜支持飞到某经纬度、设置视点、home 位置等这是「看地球顺不顺手」的关键一环场景对了操作器不对体验也会差。3.6 事件与回调GUIEventHandler键盘鼠标事件节点回调UpdateCallback每帧逻辑动画、仿真CullCallback裁剪阶段EventCallback事件冒泡到节点和 osgEarth 结合时拾取地图上的点、查询高程、点选要素通常走事件处理器 MapNode工具类。3.7 线程模型入门要知道存在Viewer 可配置SingleThreadedCullDrawThreadPerContextDrawThreadPerContextCullThreadPerCameraDrawThreadPerContext入门用默认即可出黑屏/崩溃时再查线程与上下文问题。四、OSG 渲染管线四阶段理解调试必备每帧大致Event处理输入更新操作器Update执行 UpdateCallback动画、数据更新Cull视锥裁剪、生成渲染列表、状态排序Draw提交 OpenGL 绘制PagedLOD/ 瓦片加载常在 update/cull 相关路径触发osgEarth 的地形瓦片调度也建立在这套机制上。五、osgEarth 核心Map / Layer / MapNode5.1 三层概念最重要Map数据与配置└── 多个 Layer影像、高程、矢量、模型……↓ 被可视化为MapNodeOSG 节点真正进场景图↓ 挂到Viewer.setSceneData(mapNode)类是什么不是什么Map地图「数据模型」有哪些图层、剖面、选项不是可渲染节点Layer一类数据源WMTS、本地瓦片、GeoTIFF、矢量等单独不能当场景根MapNode把 Map 变成可渲染 OSG 子树不只是「一个地球模型文件」口诀Map 管数据MapNode 管显示。5.2Map详解Map负责添加/移除 Layer地图剖面Profile地理范围、瓦片切分方案、 SRS一些全局选项如 elevation pooling、插值等版本间 API 有差异常见操作map-addLayer(imageLayer);map-addLayer(elevationLayer);map-addLayer(featureLayer);注意改 Map 后显示侧由MapNode/ Layer 回调同步多线程下要遵守 osgEarth 的线程安全约定很多操作建议在 update 阶段或按文档要求加锁。5.3MapNode详解重点展开MapNode是 osgEarth 进入 OSG 场景图的 根入口通常osg::ref_ptrosgEarth::MapNode mapNode new osgEarth::MapNode(map);viewer.setSceneData(mapNode);或从.earth文件加载osg::Node* node osgDB::readNodeFile(my.earth);MapNode* mapNode MapNode::findMapNode(node);MapNode 内部大致职责地形引擎Terrain Engine按视点动态生成/回收地形瓦片把影像贴到地形上应用高程DEM做起伏坐标系与椭球地理经纬高↔ 世界直角坐标ECEF 等和SpatialReference、GeoPoint、Ellipsoid协作图层可视化挂载Image / Elevation / Model / Annotation 等变成子图或驱动地形工具入口高程查询、坐标转换、与 Manipulator 配合常用相关 API 思路概念级MapNode::getMap()取回 MapMapNode::getTerrain()/ terrain engine访问地形MapNode::findMapNode(node)从场景里找回 MapNode加载 .earth 后很常用开启/配置一些渲染选项光照、裙边 skirt、四叉树策略等随版本变化MapNode 和普通 OSG 节点的关系MapNode就是osg::Group一类节点可再挂子节点模型、标注子节点若要用「贴地」「按经纬度放」常用 osgEarth 的GeoTransformAnnotation/PlaceNode/FeatureNodeTerrain::getHeight等做贴地5.4 Layer 类型图谱Layer 类型作用典型数据ImageLayer贴到地表的影像XYZ/WMTS/TMS、GeoTIFF、MBTilesElevationLayer高程 DEMGeoTIFF、S3、本地高程瓦片ModelLayer把 OSG 模型当图层放进地图城市模型、机场模型FeatureImageLayer / FeatureModelLayer矢量渲染成影像或模型Shapefile、GeoJSON、WFSAnnotationLayer标注层地名、图标VisibleLayer可显隐图层基类概念统一setVisible入门路径建议一张在线或本地 ImageLayer 球加 ElevationLayer 看起伏再加矢量/模型5.5.earth文件XML/JSON 风格的地图描述具体格式随版本声明 Map、Layer、驱动driver、URL、缓存策略可用osgviewer mymap.earth或代码readNodeFile直接打开价值把「数据配置」和「C 逻辑」分离适合入门实验和产品配置化。六、坐标系osgEarth 最容易卡的地方6.1 关键对象概念含义SRS / SpatialReference空间参考WGS84、WebMercator、投影坐标等GeoPoint带 SRS 的地理点经纬高或投影 x/y/zGeoExtent地理范围Profile瓦片金字塔剖分方案如 global-geodetic、spherical-mercatorECEF地心直角坐标系OSG 世界里地球常用6.2 两套「位置」不要混地理坐标lon/lat/alt世界坐标osg::Vec3d场景图里 MatrixTransform 用的转换路径概念上GeoPoint(lon, lat, alt, srs)→ toWorld(Vec3d)→ MatrixTransform / GeoTransform反过来世界坐标 → 地理坐标拾取、标注时常用。6.3GeoTransform把子节点放到地理坐标位置并可选贴地、跟随地形。比手写 ECEF 矩阵更安全是「在地球上放飞机/标注」的常规做法。七、地形、瓦片与缓存7.1 为什么地球必须「瓦片化」全球影像/DEM 极大不可能一次加载。osgEarth按 Profile 切瓦片按相机距离选 LOD 层级异步加载、内存/磁盘缓存、过期回收这和 OSG 的PagedLOD思想一致但是地理瓦片专用实现。7.2 影像 vs 高程影像改颜色纹理高程改顶点高度几何两者分辨率、覆盖范围常不一致地形引擎会做采样/混合。7.3 缓存常见关注点内存缓存已解码瓦片磁盘缓存HTTP 瓦片落地缓存策略影响「第一次慢、第二次快」调试「花屏/不更新」时有时是缓存旧数据。八、交互EarthManipulator 与拾取8.1 EarthManipulator典型能力旋转、缩放、倾斜、平移setViewpoint/ 飞行动画到某点与地形碰撞/贴地选项版本相关Viewpoint 通常包含经纬、高度、heading/pitch/range 等。8.2 地图拾取常见需求鼠标点 → 经纬高。思路屏幕坐标 → 射线与地形求交交点转 GeoPointosgEarth 提供 util/intersection 相关工具类名随版本略有不同入门时把它当成「地图专用 intersector」。九、标注、矢量与模型进阶入门9.1 AnnotationPlaceNode图标文字LabelNode文字CircleNode/LineString等几何标注特点常自动面向屏幕、深度测试策略与普通模型不同。9.2 FeatureFeature一条矢量要素属性 几何FeatureSource读 shp/geojsonStyle/RenderSymbol怎么画线宽、挤出高度、贴地9.3 在地球上挂 OSG 模型两种层次ModelLayer作为地图图层管理GeoTransform 模型节点代码里灵活放置注意缩放单位ECEF 下模型尺度、朝向ENU 局部坐标系非常容易错。十、一套最小程序的知识清单对照用写第一个地球程序你会用到osgViewer::Viewer— 窗口与主循环MapImageLayer— 数据MapNode— 场景根EarthManipulator— 交互可选ElevationLayer— 地形起伏可选GeoTransform— 放一个模型知识闭环数据(Map/Layer) → 节点(MapNode) → 视图(Viewer) → 操作(EarthManipulator)↑ |└──────── 坐标(GeoPoint/SRS) ←───────┘