在理解Config的概念之后,就可以进入OE对Earth文件的解析过程,从earth的读写插件osgdb_earth插件开始
打开ReaderWriterOsgEarth.cpp文件
熟悉的自定义osg插件读写框架,直接进入解析正题
virtual ReadResult readNode(std::istream& in, const osgDB::Options* options ) const
在这里看到了亲切的 XmlDocument类,通过它我们将XML文档存储到了Config中
接下来就是根节点辨析了,可以看到支持<<map>>和<<earth>>两种根节点字符串
然后是earh文件的版本控制,新版本增加了一些新的节点序列化,具体可以深入
序列化的最终结果就是将earth文件解析为mapNode 节点,可以将其置入osg的节点体系,进入到osg的渲染过程
继续来到版本2的序列化 EarthFileSerializer2
关键函数
MapNode
EarthFileSerializer2::deserialize( const Config& conf, const std::string& referenceURI ) const
{
MapOptions mapOptions( conf.child( "options" ) );
// legacy: check for name/type in top-level attrs:
if ( conf.hasValue( "name" ) || conf.hasValue( "type" ) )
{
Config legacy;
if ( conf.hasValue("name") ) legacy.add( "name", conf.value("name") );
if ( conf.hasValue("type") ) legacy.add( "type", conf.value("type") );
mapOptions.mergeConfig( legacy );
}
Map* map = new Map( mapOptions );
// Yes, MapOptions and MapNodeOptions share the same Config node. Weird but true.
MapNodeOptions mapNodeOptions( conf.child( "options" ) );
// Read the layers in LAST (otherwise they will not benefit from the cache/profile configuration)
// Image layers:
ConfigSet images = conf.children( "image" );
for( ConfigSet::const_iterator i = images.begin(); i != images.end(); i++ )
{
Config layerDriverConf = *i;
layerDriverConf.add( "default_tile_size", "256" );
ImageLayerOptions layerOpt( layerDriverConf );
layerOpt.name() = layerDriverConf.value("name");
//layerOpt.driver() = TileSourceOptions( layerDriverConf );
map->addImageLayer( new ImageLayer(layerOpt) );
}
// Elevation layers:
for( int k=0; k<2; ++k )
{
std::string tagName = k == 0 ? "elevation" : "heightfield"; // support both :)
ConfigSet heightfields = conf.children( tagName );
for( ConfigSet::const_iterator i = heightfields.begin(); i != heightfields.end(); i++ )
{
Config layerDriverConf = *i;
layerDriverConf.add( "default_tile_size", "15" );
ElevationLayerOptions layerOpt( layerDriverConf );
layerOpt.name() = layerDriverConf.value( "name" );
map->addElevationLayer( new ElevationLayer(layerOpt) );
}
}
// Model layers:
ConfigSet models = conf.children( "model" );
for( ConfigSet::const_iterator i = models.begin(); i != models.end(); i++ )
{
const Config& layerDriverConf = *i;
ModelLayerOptions layerOpt( layerDriverConf );
layerOpt.name() = layerDriverConf.value( "name" );
layerOpt.driver() = ModelSourceOptions( layerDriverConf );
map->addModelLayer( new ModelLayer(layerOpt) );
//map->addModelLayer( new ModelLayer( layerDriverConf.value("name"), ModelSourceOptions(*i) ) );
}
// Overlay layers (just an alias for Model Layer with overlay=true)
ConfigSet overlays = conf.children( "overlay" );
for( ConfigSet::const_iterator i = overlays.begin(); i != overlays.end(); i++ )
{
Config layerDriverConf = *i;
if ( !layerDriverConf.hasValue("driver") )
layerDriverConf.set("driver", "feature_geom");
ModelLayerOptions layerOpt( layerDriverConf );
layerOpt.name() = layerDriverConf.value( "name" );
layerOpt.driver() = ModelSourceOptions( layerDriverConf );
layerOpt.overlay() = true; // forced on when "overlay" specified
map->addModelLayer( new ModelLayer(layerOpt) );
}
// Mask layer:
ConfigSet masks = conf.children( "mask" );
for( ConfigSet::const_iterator i = masks.begin(); i != masks.end(); i++ )
{
Config maskLayerConf = *i;
MaskLayerOptions options(maskLayerConf);
options.name() = maskLayerConf.value( "name" );
options.driver() = MaskSourceOptions(options);
map->addTerrainMaskLayer( new MaskLayer(options) );
}
//Add any addition paths specified in the options/osg_file_paths element to the file path. Useful for pointing osgEarth at resource folders.
Config osg_file_paths = conf.child( "options" ).child("osg_file_paths");
ConfigSet urls = osg_file_paths.children("url");
for (ConfigSet::const_iterator i = urls.begin(); i != urls.end(); i++)
{
std::string path = osgEarth::getFullPath( referenceURI, (*i).value());
OE_DEBUG << "Adding OSG file path " << path << std::endl;
osgDB::Registry::instance()->getDataFilePathList().push_back( path );
}
MapNode* mapNode = new MapNode( map, mapNodeOptions );
// External configs:
Config ext = conf.child( "external" );
if ( !ext.empty() )
{
mapNode->externalConfig() = ext;
}
return mapNode;
}
从上面可以看到
1 earth插件 map 统筹OE中所有"层"的概念,支持多层影像,高程,模型,镂空层(mask)等
2各个层相应配置的属性由指定的Option类从Config中获取,如果对应Config中有Option类指定元素相应值的配置Option将其写入
现将OE支持的层节点和部分属性分列如下(仅供参考)