osgEarth数据加载及组织解析(2)

2020-02-21 17:00

地形引擎需要一个Container来设置光照状态,而不能直接在引擎上来设置_terrainEngineContainer = new osg::Group();_terrainEngineContainer->setDataVariance( osg::Object::DYNAMIC );this->addChild( _terrainEngineContainer.get() );MapNode.cpp_terrainInterface = new Terrain( this, map->getProfile(), map->isGeocentric() );开启一个地形功能界面_map->getProfile()->getSRS()->populateCoordinateSystemNode( this );根据_map的空间参考坐标系设置的TerrainEngineNode的坐标系和椭球模型,其中WKT及PROJ4等有默认值开始只是球体与底图显示,所以此时只用添加底图MapFrame mapf(map, Map::IMAGE_LAYERS);_texCompositor->applyMapModelChange( MapModelChange( MapModelChange::ADD_IMAGE_LAYER, mapf.getRevision(), mapf.getImageLayerAt(i), i ) );首先加入事先存在的影像图层,即底图,此处调用image的driver进行加载数据,主要是因为在applymapModelChange函数中,首先getProfile,因影像先未进行初始化,故需调用相应driver去读取数据信息,获取其profile。// 创建模型节点:_models = new osg::Group();_models->setName( \addChild( _models.get() );// 创建overlay模型节点:_overlayModels = new osg::Group();_overlayModels->setName( \ // 创建overlay models decorator_overlayDecorator = new OverlayDecorator();addTerrainDecorator( _overlayDecorator.get() ); // 加载预先存在的模型图层ModelLayerVector modelLayers;_map->getModelLayers( modelLayers );for(){ onModelLayerAdded( k_>get(), modelLayerIndex };_mapCallback = new MapNodeMapCallbackProxy(this); // 注册MapNodeMapCallback回调函数_map->addMapCallback( _mapCallback.get() );获取状态设置属性和模式MapNode.cpposgearth::MapNode : public osg::Grouposg::Group()地形节点_map->addMapCallback( new TerrainEngineNodeCallbackProxy( this ) )注册回调函数,这样就够处理map模型改变的事件开启背面剔除获取状态设置属性和模式增加Uniform cameraElevationUniform获取Osgearth_ImageLayerAttenuation 并设置TerrainEngineNode.cpp osgEarth:MPTerrainEngineNode******osg::Group()osg::Group()模型节点Overlay模型节点此时MapNode节点结构

图3.8 构建mapNode第一步详细流程

图3.8展示的是构建mapNode第一步的详细流程,最后生成包含了地形节点、模型节点和overlay模型节点的子树。其中,在根据map的空间参考坐标系设置TerrainEngineNode的坐标系和椭球模型时,map对象有获取profile属性。Profile是确定数据的空间信息重要属性,其如何确定数据的空间信息将在后文进行详细说明。若map对象的options中没有设置profile,默认将其中的SRS(空间参考系)设置为WGS84坐标系。

实质调用createTerrain()if (_tileModelFactory) _tileModelFactory->getHeightFieldCache()->clear();_terrain = new TerrainNode( _deadTiles.get() ); this->addChild( _terrain );创建地形的第一层(LOD为0)收集包括地形根瓦片的tile keysstd::vector< TileKey > keys; _update_mapf->getProfile()->getAllKeysAtLOD( *_terrainOptions.firstLOD(), keys )osg::Node* node = factory->createRootNode( keys[i] )If(node) _terrain->addChild(node);为每个root tile key创建一个root节点,在其中读取具体影像与高程,并放置在正确的位置osgearth::MapNode : public osg::Grouposg::Group()地形节点osgEarth:MPTerrainEngineNodeTerrainNodeRootNode(TileNodeGroup)……osg::Group()osg::Group()模型节点Overlay模型节点此时MapNode节点结构MPTerrainEngineNode.cpp图3.9 构建mapNode第二步详细流程

图3.9展示的是构建mapNode第二步详细流程。此处只挑出了重点的函数,主要创建了第一层的TileKey和根节点。每个rootNode包含四叉树索引组织的key,包括范围信息等,然后还包含这块范围的各种数据,所以,创建根节点的createRootNode将是我们下面分析的重点。

确定空间位置并配置其TIleKey创建瓦片模型读取影像,创建纹理贴图读取高程 创建根节点以pagedLOD形式将模型加入根节点

图3.10 创建根节点的逻辑流程

图3.10展示的是创建根节点的逻辑流程。由图可知,归纳为做了两件事,第一件即创建了包含影像图层、高程图层及TileKey的瓦片模型,第二件事是将这个模型以PagedLOD形式加入根节点。其中TileKey包含模型的空间信息,能正确确定数据在三维球上的正确位置,且以四叉树形式被组织起来。PagedLOD即分页LOD,能根据视点范围动态选择加载哪些节点。这两个技术将在后文详细解读。

createRootNode(const TileKey& key)_modelFactory->createTileModle(key,model,real,lodBlending)real指是否含有real data(real data指直接关联到key的数据,相反的称为fallback data,从低一级的LOD key中衍伸的数据),lodBlending指是否含有lodBending一个瓦片节点group必须只能放一个单独的瓦片osg::Group* root = new TileNodeGroup();addTile( model.get(), real, lodBlending, root );return root;SerialKeyNodeFactory.cppreturn root;SerialKeyNodeFactory.cpposgearth::MapNode : public osg::Grouposg::Group()地形节点MapFrame mapf( _map, Map::MASKED_TERRAIN_LAYERS ); const MapInfo& mapInfo = mapf.getMapInfo();osg::ref_ptr model = new TileModel();model->_map = _map;model->_tileKey = key;model->_tileLocator = GeoLocator::createForKey(key, mapInfo);BuildColorData build;build.init( key, layer, order, mapInfo, _terrainOptions, model.get() );bool addedToModel = build.execute();BuildElevationData build;build.init( key, mapf, _terrainOptions, model.get(), _hfCache );build.execute();osgEarth:MPTerrainEngineNodeTerrainNodeosg::PagedLODRootNode(TileNodeGroup)ColorLayerElevationLayerosg::Group()osg::Group()模型节点Overlay模型节点此时MapNode节点结构execute()返回一个bool,实际创建图片加载上图层读取高程,并构建四叉树的key核心函数与image相同,此处可以好好分析key如何分层.其中execute无返回TileModelFactory.cpp

图3.11 createRootNode流程

图3.11展示了创建根节点的详细流程。其中,在创建影像图层和高程图层中,相应的execute函数里分别调用了createImage()函数和createHeightfields()函数,这两个函数根据数据中的option属性,调用了相应driver的插件,而进行了实际具体的数据读取。如果需要写自己的插件读取影像数据或高程数据,则必须重载这两个函数。

GeoLocator::createForKey创建地形块的locator:首先,根据key获取该地形块的范围,分别为double xmin, double ymin, double xmax, double ymax Key中的extent中存储相应info,createForExtent具体处理然后根据地形块对应的范围,创建LocatorSpatialReference::createLocator(double xmin, double ymin, double xmax, double ymax, bool plate_carre ),如果空间参考系为地理坐标系(不是投影)或者map为平面则将 xmin, ymin, xmax, ymax由度数转化为弧度,然后调用getTransformFromExtents( xmin, ymin, xmax, ymax ),否则直接用度数调用static osg::MatrixdgetTransformFromExtents(double minX, double minY, double maxX, double maxY){从原点向左下角移动, osg::Matrixd transform;x轴放大(maxX-minX) transform.set(倍,y轴放大(maxY- maxX-minX, 0.0, 0.0, 0.0,minY)倍 0.0, maxY-minY, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, minX, minY, 0.0, 1.0); return transform;}Locators.cpp图3.12 GeoLocator的具体空间信息处理

GeoLocator确定了瓦片模型的位置,如图3.12所示,主要通过key获取地形块的范围,然后再移至相应的位置。

综上,一个包含地形节点、模型节点和overlay模型节点的mapNode便被正确的构成了。其中最主要的便是地形节点的构造,它包含的影像图层、高程图层等都以四叉树结构进行组织,以分页LOD模式进行动态调度渲染。

更为详细的流程图,可参见附件中的osgEarth数据读取流程。

1.4 加载节点至场景树

最后的加载节点至场景树很简单,就是创建一个group节点,将mapNode包含进去,然后这个将加入osgViewer的渲染流程。

具体代码如下:

osg::Group* root = new osg::Group(); root->addVhild(mapNode.get());

在程序运行时,因为视野的改变,osgEarth会利用PagedLOD动态的加载卸载瓦片节点,而会重复上面构造mapNode的步骤来构造新的节点。

2.空间信息组织编码及位置确定

上一节内容解读了osgEarth如何将earth文件读入,并利用其中的XML标签构建地形结点从而达到渲染目的。这一节则主要解读如何将数据放入三维球正确的位置并进行组织。

简单而言,关于位置属性的记录,osgEarth就只是利用任何地形数据都会包括的投影坐标系及经纬度信息进行定位。这样的优点在于,无论何种数据源的数据,只要能最后确定一定的投影参考系,便能保证被放置在正确的位置,数据之间保持正确的拓扑关系和逻辑关系。而相关的投影系转换,标准,表达方式,国际上规定也十分明确。一个统一的标准,使osgEarth能接纳更多源的数据。

本节,就会首先介绍osgEarth相关的空间参考系,然后再解读其具体如何确定数据在三维球上的位置。同时,由前文可知,osgEarth通过创建用四叉树结构的分层瓦片缓存,可以快速加载大地形数据。最后,将解读其生成的缓存文件编码。

2.1 空间参考系

osgEarth中,每个map对象,layer对象,tilesource对象,均有决定其所属空间位置的属性profile。Profile中,包含记录对象空间参考系的属性SRS。通常,我们用经纬度来表示数据的位置。可是不同空间参考系中,相同的经纬度不一定表示一个地方。所以,osgEarth中每个数据对象都会包含空间参考系属性SRS。

一个空间参考系,包含以下内容[15]: ①坐标系类型 ②水平基准 ③高程基准 ④投影

下面也就这四个方面对osgEarth的空间参考系进行介绍。 (一)坐标系类型

osgEarth支持三种地图的显示方法。 ①地理坐标系类型

展示的方式便是三维数字地球,使用角度制的经纬度。代表包括WGS84坐标系和NAD83坐标系。

②投影坐标系类型

展示的方式是将三维区域投影到二维(X,Y)平面。代表包括UTM投影,墨卡托投影。

① ECEF

即Earth Centered Earthh Fixed。是osgEarth自定义的坐标系类型,是一种三维的笛卡尔坐标系,原点定于球心,X轴指向纬度/经度(0,0),Y轴指向纬度/经度(0,-90),Z轴指向北极。其坐标系体系同OSG的世界坐标系体系是一致的,如图3.13所示。

Z

Y轴 轴

X轴

图3.13 ECEF


osgEarth数据加载及组织解析(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:三年内累积一年工作经验即可申请

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: