当前位置: 首页 > news >正文

OSG / osgEarth 入门知识体系

我自己是初学者,入行搞这个差不多两个月了,一直处于迷迷糊糊的状态,今天本着自己学习的态度一起来总结一下OSG/osgEarth的知识体系,希望对初学者有帮助。

假设你有一张纸,纸上画了一棵树,这就是二维(2D)。但是现实生活中,树是立体的,你可以绕着树走,可以从前面看、后面看,还可以飞到天上看,这就是三维(3D)。电脑想要画出这样的世界,需要有人帮它,这个帮手就是OSG

OSG(OpenSceneGraph)可以理解成:一个会搭积木的机器人。

它负责告诉电脑,这里有一棵树,那里有一个房子,那里有一辆车,然后电脑就能把整个三维世界画出来。实际上电脑里面不是画画,而是很多很多三角形。例如一个正方形,电脑实际上画的是两个三角形。因为GPU最喜欢画三角形。所以,OSG就是负责管理这些三角形。

OSG名字里面有个Graph,其实不是数学里的图,而是一棵树(树状结构)。

例如:

世界 │ ├──天空 │ ├──地面 │ ├──汽车 │ ├──轮子1 │ ├──轮子2 │ ├──轮子3 │ └──轮子4 │ └──房子 ├──门 └──窗户

是不是像文件夹?

OSG就是这样管理所有东西。

所以叫:

Scene(场景)

Graph(树状结构)

OSG里面最重要的东西叫Node(节点)。可以理解成乐高积木,节点可以是一棵树,一辆车,一个房子等,所有东西都可以是一个Node。

还有OSG里面的group,group就是一个盒子,他只会装东西不会显示。

Geode:Geometry 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高程,行政区,WMS,WMTS,GeoTIFF,Shapefile等这些OSG 都没有。

为什么需要osgEarth?

例如:你想画北京。如果只有OSG,你要自己画地球- >画中国- >画北京 ->贴地图->算经纬度等,工作量巨大。但是如果有osgEarth,mapNode一句, 整个地球就出来了。

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::Geometry+Drawable

几何数据承载

osg::Switch

开关子节点显隐

osg::LOD/PagedLOD

按距离/屏幕大小换细节

osg::Camera

相机(也可嵌套做 RTT)

osg::StateSet

材质、纹理、光照、shader 等状态

入门口诀:节点管结构,StateSet 管怎么画,Drawable 管画什么。

2.2osg::Node/osg::Group/osg::Geode

  • Node:所有节点基类,可挂UpdateCallbackCullCallbackEventCallback
  • Group:可addChild/removeChild,是场景组织的主力。
  • Geode(Geometry Node):传统上专门挂Drawable;较新 OSG 也常直接把Geometry当叶子用。

2.3StateSet(状态集)——很容易被忽视但极关键

StateSet描述渲染状态,可挂在任意节点上,向下继承:

  • 纹理、材质、光照开关
  • GL_DEPTH_TEST、混合、面剔除
  • Shader / Uniform
  • 渲染 bin(透明排序等)

要点:

  1. 子节点可覆盖父节点状态
  2. setMode/setAttribute/setTextureAttribute是三类常用接口
  3. 改状态比改几何更常见,性能也更敏感

2.4 变换节点

  • MatrixTransform:任意 4×4 矩阵(平移+旋转+缩放)
  • PositionAttitudeTransform:位置 + 姿态四元数 + 缩放,语义更直观
  • CoordinateSystemNode:和地理坐标系相关时常见(osgEarth 大量用地理坐标转换)

注意:OSG 默认常是 右手系,相机看向 -Z,上方向 +Y(具体以你用的 Viewer/相机设置为准)。


三、osgViewer:应用的「外壳」

3.1 Viewer 到底是什么

osgViewer::Viewer(或CompositeViewer)是应用主循环的中枢,负责:

  1. 创建/管理 GraphicsContext(窗口、OpenGL 上下文)
  2. 持有 Camera(主相机)
  3. 挂载 SceneData(场景根节点)
  4. 驱动 Event / Update / Cull / Draw 四阶段
  5. 管理 操作器(CameraManipulator):鼠标旋转、平移、缩放

最小心智模型:

Viewer

├── GraphicsWindow / Context

├── Camera(投影 + 视口 + 清屏)

├── SceneData(你的根 Group / MapNode)

├── CameraManipulator(EarthManipulator 等)

└── 事件处理器(键盘、HUD 等)

3.2 典型生命周期

osgViewer::Viewer viewer;

viewer.setSceneData(root); // 挂场景

viewer.setCameraManipulator(...); // 交互

viewer.setUpViewInWindow(x,y,w,h); // 或全屏 / 嵌入 Qt

while (!viewer.done()) {

viewer.frame(); // 一帧:事件→更新→裁剪→绘制

}

或:

viewer.run(); // 内部循环调用 frame()

3.3ViewervsCompositeViewer

ViewerCompositeViewer

场景/视图

通常一个主视图

多个View

用途

单窗口应用

多窗口、多显示器、主从视图

复杂度

高(共享场景或独立场景都可)

入门先用Viewer即可。

3.4 相机(osg::Camera)在 Viewer 里的角色

主相机通常由 Viewer 创建,你可设置:

  • 投影:透视Perspective/ 正交Ortho
  • 视口:像素区域
  • Clear mask / clear color
  • Render Order:嵌套相机做 HUD、后处理、RTT

osgEarth 里经常还有:

  • 地形相机 / overlay 相机
  • MapNode内部管理的多 pass 渲染

入门阶段:先把「主相机看向场景」弄清,再碰嵌套相机。

3.5 操作器(Manipulator)

OSG 自带:

  • TrackballManipulator:绕物体转(模型查看)
  • FlightManipulator/DriveManipulator:飞行/驾驶
  • TerrainManipulator:贴地感更强

osgEarth 常用:

  • osgEarth::Util::EarthManipulator:地球导航(旋转地球、缩放高度、倾斜)
  • 支持飞到某经纬度、设置视点、home 位置等

这是「看地球顺不顺手」的关键一环:场景对了,操作器不对,体验也会差。

3.6 事件与回调

  • GUIEventHandler:键盘鼠标事件
  • 节点回调:
    • UpdateCallback:每帧逻辑(动画、仿真)
    • CullCallback:裁剪阶段
    • EventCallback:事件冒泡到节点

和 osgEarth 结合时:拾取地图上的点、查询高程、点选要素,通常走事件处理器 +MapNode工具类。

3.7 线程模型(入门要知道存在)

Viewer 可配置:

  • SingleThreaded
  • CullDrawThreadPerContext
  • DrawThreadPerContext
  • CullThreadPerCameraDrawThreadPerContext

入门用默认即可;出黑屏/崩溃时再查线程与上下文问题。


四、OSG 渲染管线四阶段(理解调试必备)

每帧大致:

  1. Event:处理输入,更新操作器
  2. Update:执行 UpdateCallback,动画、数据更新
  3. Cull:视锥裁剪、生成渲染列表、状态排序
  4. Draw:提交 OpenGL 绘制

PagedLOD/ 瓦片加载常在 update/cull 相关路径触发;osgEarth 的地形瓦片调度也建立在这套机制上。


五、osgEarth 核心:Map / Layer / MapNode

5.1 三层概念(最重要)

Map(数据与配置)

└── 多个 Layer(影像、高程、矢量、模型……)

↓ 被可视化为

MapNode(OSG 节点,真正进场景图)

↓ 挂到

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_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map);

viewer.setSceneData(mapNode);

或从.earth文件加载:

osg::Node* node = osgDB::readNodeFile("my.earth");

MapNode* mapNode = MapNode::findMapNode(node);

MapNode 内部大致职责
  1. 地形引擎(Terrain Engine)

    • 按视点动态生成/回收地形瓦片
    • 把影像贴到地形上
    • 应用高程(DEM)做起伏
  2. 坐标系与椭球

    • 地理(经纬高)↔ 世界直角坐标(ECEF 等)
    • SpatialReferenceGeoPointEllipsoid协作
  3. 图层可视化挂载

    • Image / Elevation / Model / Annotation 等变成子图或驱动地形
  4. 工具入口

    • 高程查询、坐标转换、与 Manipulator 配合
常用相关 API 思路(概念级)
  • MapNode::getMap():取回 Map
  • MapNode::getTerrain()/ terrain engine:访问地形
  • MapNode::findMapNode(node):从场景里找回 MapNode(加载 .earth 后很常用)
  • 开启/配置一些渲染选项(光照、裙边 skirt、四叉树策略等,随版本变化)
MapNode 和普通 OSG 节点的关系
  • MapNode就是osg::Group一类节点,可再挂子节点(模型、标注)
  • 子节点若要用「贴地」「按经纬度放」,常用 osgEarth 的:
    • GeoTransform
    • Annotation/PlaceNode/FeatureNode
    • Terrain::getHeight等做贴地

5.4 Layer 类型图谱

Layer 类型作用典型数据

ImageLayer

贴到地表的影像

XYZ/WMTS/TMS、GeoTIFF、MBTiles

ElevationLayer

高程 DEM

GeoTIFF、S3、本地高程瓦片

ModelLayer

把 OSG 模型当图层放进地图

城市模型、机场模型

FeatureImageLayer / FeatureModelLayer

矢量渲染成影像或模型

Shapefile、GeoJSON、WFS

AnnotationLayer

标注层

地名、图标

VisibleLayer

可显隐图层基类概念

统一setVisible

入门路径建议:

  1. 一张在线或本地 ImageLayer 球
  2. 加 ElevationLayer 看起伏
  3. 再加矢量/模型

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/z)

GeoExtent

地理范围

Profile

瓦片金字塔剖分方案(如 global-geodetic、spherical-mercator)

ECEF

地心直角坐标系,OSG 世界里地球常用

6.2 两套「位置」不要混

  1. 地理坐标:lon/lat/alt
  2. 世界坐标: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 地图拾取

常见需求:鼠标点 → 经纬高。

思路:

  1. 屏幕坐标 → 射线
  2. 与地形求交
  3. 交点转 GeoPoint

osgEarth 提供 util/intersection 相关工具(类名随版本略有不同),入门时把它当成「地图专用 intersector」。


九、标注、矢量与模型(进阶入门)

9.1 Annotation

  • PlaceNode:图标+文字
  • LabelNode:文字
  • CircleNode/LineString等:几何标注

特点:常自动面向屏幕、深度测试策略与普通模型不同。

9.2 Feature

  • Feature:一条矢量要素(属性 + 几何)
  • FeatureSource:读 shp/geojson
  • Style/RenderSymbol:怎么画(线宽、挤出高度、贴地)

9.3 在地球上挂 OSG 模型

两种层次:

  1. ModelLayer:作为地图图层管理
  2. GeoTransform + 模型节点:代码里灵活放置

注意缩放单位:ECEF 下模型尺度、朝向(ENU 局部坐标系)非常容易错。


十、一套最小程序的知识清单(对照用)

写第一个地球程序,你会用到:

  1. osgViewer::Viewer— 窗口与主循环
  2. Map+ImageLayer— 数据
  3. MapNode— 场景根
  4. EarthManipulator— 交互
  5. (可选)ElevationLayer— 地形起伏
  6. (可选)GeoTransform— 放一个模型

知识闭环:

数据(Map/Layer) → 节点(MapNode) → 视图(Viewer) → 操作(EarthManipulator)

↑ |

└──────── 坐标(GeoPoint/SRS) ←───────┘

http://www.cnnetsun.cn/news/3591482.html

相关文章:

  • John the Ripper Jumbo:密码安全研究的终极武器与多架构并行计算框架
  • 终极指南:如何在macOS上完全解锁第三方鼠标侧键功能
  • 济南有哪些正规的民办中专
  • NodeBootstrap自动化测试指南:确保项目质量的完整流程
  • tesla_dashcam Docker部署指南:轻松实现GPU加速视频处理
  • 想玩 AI 恋人怕踩坑?看完这篇再下手
  • 团队协作中git的常用操作
  • Unity游戏IL2CPP逆向工程与安全防护实战
  • 震惊!选错试验机赔百万?苏州伺服拉力试验机必须注意这3点!
  • ArkUI 自定义组件与复用:构建高效 HarmonyOS 页面的核心技法
  • 2026年企业机票代订主流服务商盘点 服务能力与选型指南
  • Shodan_VirusTotal_CVE_CSDN
  • Peckham用户指南:解决import重复与路径搜索难题的实用技巧
  • 【DEIM 创新改进】CVPR 2026 | 独家创新首发、特征融合改进篇| 引入SAFusion语义对齐融合模块,助力无人机航拍、遥感影像、小目标检测、语义分割、实例分割、目标跟踪任务,有效涨点
  • 计算机毕业设计之智慧农业系统
  • 2026年7月上海企业搬迁公司推荐,深耕政企搬迁十多年,格睦搬家匠心护航企业办公乔迁安全
  • 同行不会告诉你的课题申报技巧
  • SpringBoot“尽所欲研”学习交流社区系统选题背景
  • 2026泰安黄金回收白银回收铂金回收工商备案可查全城上门回收旧金老店联系方式推荐
  • Windows下使用VirtualBox搭建ROS开发环境完整指南
  • wechatpay-apache-httpclient完全指南:10分钟上手微信支付APIv3开发
  • vt-py扩展开发:零基础构建自定义威胁分析工具的完整指南
  • 靠谱的奢石企业
  • 计算机Python毕设实战-基于 Python 的智能化无人零售超市管理信息系统 基于 Django 的无人超市运营管理系统设计【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 如何使用cppclean快速定位C++项目中的未使用代码与冗余依赖
  • Node API for .NET架构解析:深入理解.NET与JavaScript互操作核心原理
  • BioMamba 生信基地个性化分析服务实战指南
  • Node API for .NET性能揭秘:比Edge.js快2倍的.NET/JS进程内通信技术
  • aws4安全最佳实践:凭证管理与签名验证
  • GEO 优化傻瓜指南