osgEarth示例分析——osgearth_splat

前言

osgearth_splat示例,展示如何加载图片贴在地球上,且通过分类,贴文理绘制森林、草地等。

执行命令:osgearth_splatd.exe

效果

整个地球的影像,加载的一张贴图。黑白点点,是不同的贴图。当拉进放大后,才可以看清楚加载的是哪张纹理图。代码设置了15级。

 代码分析

1. 创建 土地覆盖字典选项 LandCoverDictionaryOptions options;
 将xml文件中的字典配置,读入options中,主要是name。

2. 用options初始化土地覆盖字典 LandCoverDictionary dictionary;

3. 设置gdal驱动 GDALOptions coverageDriver;,加载地形。

4. 创建LandCover的可序列化配置选项 LandCoverCoverageLayerOptions coverage;
主要包括驱动 coverageDriver 以及 map表(从xml读入,指定某位置放某类贴图)。

5. 为地图创建土地覆盖层:LandCoverLayer *landCover; 并将coverage设置到此土地覆盖层,指定最大层级。

6. 加载实际纹理映射定义,即map表中对应的分类,需要覆盖哪张图。创建 Surface* surface;通过 SplatCatalog* catalog 加载xml文件,完成name与纹理图的实际对应。

7. 创建Zone* splatZone;来指定surface图要覆盖到地图的哪个区域。

8. 创建 SplatLayer* splatLayer;将dictionary、landCover、splatZone设置到splatLayer 图层.

9. 有了上面的基础内容,可以通过直接加载image的方式创建图层。读取图片osg::ref_ptr<osg::Image> tree; 创建标牌 BillboardSymbol* treeSymbol ;将tree传入treeSymbol; 

10. 创建土地覆盖种群选项,GroundCoverBiomeOptions forestBiome;
将 新物种 treeSymbol ,放置到 "forest" 种群中。

11. 创建 GroundCoverOptions treeOptions 地面覆盖选项,将生物种群 forestBiome 加入到 treeOptions中。同时设置 GroundCover* trees = new GroundCover(treeOptions);

12. 为要添加的 树 ,新增一个区域 Zone* treeZone; treeZone->setGroundCover(trees);

13. 为这些树,创建地面覆盖图层 GroundCoverLayer* treeLayer;并将内容设置进去。

  •     treeLayer->setLandCoverDictionary(dictionary);
  •     treeLayer->setLandCoverLayer(landCover);
  •     treeLayer->zones().push_back(treeZone);


14. 最后将上述设置,组装到map中。    

  •     Map* map = new Map();
  •     map->addLayer(dictionary);
  •     map->addLayer(landCover);
  •     map->addLayer(splatLayer);

 
【注】其中9-13步骤,是概述不通过xml文件,加载纹理图的方式。

完整代码:

#include <osgViewer/Viewer>

#include <osgEarth/MapNode>
#include <osgEarth/Registry>
#include <osgEarth/LandCoverLayer>

#include <osgEarthSplat/SplatLayer>
#include <osgEarthSplat/GroundCoverLayer>

#include <osgEarthDrivers/gdal/GDALOptions>

#include <osgEarthUtil/ExampleResources>
#include <osgEarthUtil/EarthManipulator>

#include <osgEarthSymbology/BillboardSymbol>

#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>


#define LC "[splat] "

using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Splat;
using namespace osgEarth::Drivers;
using namespace osgEarth::Symbology;

int
failed(const std::string& s) {
    OE_WARN << "FAILED: " << s << "\n";
    return -1;
}

int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    bool fromXML = arguments.find("--xml") >= 0;

    // Create a land cover dictionary.创建 陆地覆盖词典 对象
    LandCoverDictionary* dictionary;

    if (fromXML)
    {
        LandCoverDictionaryOptions options;
        if (options.loadFromXML("D:/FreeXGIS/osgearth_gch/data/land_cover_dictionary.xml") == false)
            return failed("Cannot find XML land cover dictionary");
        
        dictionary = new LandCoverDictionary(options);
    }
    else
    {
		// 如果没有找到,则新建一个对象。下面的内容同xml中标签一致
        dictionary = new LandCoverDictionary();
        dictionary->setName("Land Cover Dictionary");
        dictionary->addClass("forest");
        dictionary->addClass("cropland");
        dictionary->addClass("grassland");
        dictionary->addClass("savanna");
        dictionary->addClass("swamp");
        dictionary->addClass("desert");
        dictionary->addClass("rock");
        dictionary->addClass("water");    
        dictionary->addClass("tundra");
        dictionary->addClass("urban");
    }

    // Create the data source for our land cover data and
    // map each value to a class in the dictionary.
    // This example uses the ESA GLOBCOVER data set from
    // http://due.esrin.esa.int/page_globcover.php
    GDALOptions coverageDriver;// gdal驱动
    //coverageDriver.url() = "D:/FreeXGIS/osgearth_gch/data/splat/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif"; // 未找到,换一个
	coverageDriver.url() = "earth_image/heightfield/30m.tif";// 30m高程数据
	//coverageDriver.url() = "earth_image/globe/globel.tif";// 加载影像,拉进的过程中,控制台会输出错误信息
    coverageDriver.profile() = ProfileOptions("global-geodetic");// 创建地球

	// landCover 可序列化配置选项
    LandCoverCoverageLayerOptions coverage;
    coverage.driver() = coverageDriver;// 指定驱动
    coverage.warp() = 0.035;// 弯曲率?
    if (fromXML)
    {
        if (coverage.loadMappingsFromXML("D:/FreeXGIS/osgearth_gch/data/land_cover_ESA_GLOBCOVER.xml") == false)
            return failed("Cannot find coverage mappings XML\n");
    }
    else
    {
		// 如果读取不到xml数据则创建。以下name值与dictionary的class值保持一致
        coverage.map(11, "cropland");// 农田
        coverage.map(14, "cropland");
        coverage.map(20, "cropland");
        coverage.map(30, "cropland");
        coverage.map(40, "forest");// 森林
        coverage.map(50, "forest");
        coverage.map(60, "forest");
        coverage.map(70, "forest");
        coverage.map(80, "forest");
        coverage.map(90, "forest");
        coverage.map(100, "forest");
        coverage.map(110, "grassland");// 草场
        coverage.map(120, "grassland");
        coverage.map(130, "savanna");// 稀树草原
        coverage.map(140, "savanna");
        coverage.map(150, "savanna");
        coverage.map(160, "swamp");// 沼泽
        coverage.map(170, "swamp");
        coverage.map(180, "swamp");
        coverage.map(190, "urban");// 城市
        coverage.map(200, "desert");// 沙漠
        coverage.map(210, "water");// 水
        coverage.map(220, "tundra");// 冻土带
        coverage.map(230, "water");
    }

    // Create the land cover layer for the map:
	// 为地图创建土地覆盖层:
    LandCoverLayer* landCover = new LandCoverLayer();
    landCover->setName("LandCover");
    landCover->options().cachePolicy() = CachePolicy::NO_CACHE;
    landCover->options().coverages().push_back(coverage);
    landCover->options().maxDataLevel() = 15u;// 最大层级

    // Next, load the definitions that map land cover classes to actual textures.
	// 接下来,加载将土地覆盖类映射到实际纹理的定义。
    Surface* surface = new Surface();
	// 在catalog中,指明了 每一个class对应的图,比如forest对应森林图
    SplatCatalog* catalog = SplatCatalog::read("D:/FreeXGIS/osgearth_gch/data/splat/splat_catalog.xml");
    if (catalog == 0L)
        return failed("Reading splat catalog");
	// 将读取到的策略,应用到surface中
    surface->setCatalog(catalog);

    // The zone designates the geographic area over which to apply the surface.
    // At least one zone is required and by default it covers the entire map.
	// 区域指定要应用曲面的地理区域。
	// 至少需要一个区域,默认情况下它覆盖整个地图。
    Zone* splatZone = new Zone();//定义一个区域,将特定表面或土地覆盖层限制在一组地理边界内。
    splatZone->setSurface(surface);
    
    // Create an imagery splatting layer that uses the configured land cover.
	// 使用配置的土地覆盖图 创建 图像splatting层。即将纹理贴在地形上
    SplatLayer* splatLayer = new SplatLayer();
    splatLayer->setName("Splat imagery");
    splatLayer->options().cachePolicy() = CachePolicy::NO_CACHE;
    splatLayer->setLandCoverDictionary(dictionary);
    splatLayer->setLandCoverLayer(landCover);
    splatLayer->zones().push_back(splatZone);


    // Now, the trees:

    // Load a tree image and make a billboard symbol from it:
    osg::ref_ptr<osg::Image> tree = URI("D:/FreeXGIS/osgearth_gch/data/splat/pine2.png").getImage();
    if (tree.valid() == false)
        return failed("Loading tree image");

	// 标牌
    BillboardSymbol* treeSymbol = new BillboardSymbol();
    treeSymbol->setImage(tree.get());
    treeSymbol->width() = 12.0f;
    treeSymbol->height() = 16.0f;

    // Add this symbol to a "frest" biome.
	// 将此符号添加到“新”生物群落中。
    GroundCoverBiomeOptions forestBiome;
    forestBiome.biomeClasses() = "forest";
    forestBiome.symbols().push_back(treeSymbol);
    
    // Assemble the ground cover coniguration:
	// 组装覆盖地面的配置
    GroundCoverOptions treeOptions;
    treeOptions.biomes().push_back(forestBiome);
    treeOptions.maxDistance() = 15000.0;
    treeOptions.density() = 4.0;
    treeOptions.fill() = 0.85;
    treeOptions.brightness() = 2.0;// 亮度
    treeOptions.contrast() = 1.0;// 对比度
    GroundCover* trees = new GroundCover(treeOptions);//控制地面覆盖物外观的接口。

	// 新增一个区域,绘制trees
    Zone* treeZone = new Zone();
    treeZone->setGroundCover(trees);

    // Now, create a ground cover layer for some trees.
	// 现在,为这些树创建地面覆盖层。
    GroundCoverLayer* treeLayer = new GroundCoverLayer();
    treeLayer->setName("Ground cover");
    treeLayer->options().lod() = 13;
    treeLayer->setLandCoverDictionary(dictionary);
    treeLayer->setLandCoverLayer(landCover);
    treeLayer->zones().push_back(treeZone);


    // Assemble the Map.组装地图
    Map* map = new Map();
    map->addLayer(dictionary);
    map->addLayer(landCover);
    map->addLayer(splatLayer);
    map->addLayer(treeLayer);

    // Activate the REX terrain engine (required for splatting)激活REX地形引擎
    osgEarth::Registry::instance()->overrideTerrainEngineDriverName() = "rex";

    // create a viewer:
    osgViewer::Viewer viewer(arguments);
    viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
    viewer.setCameraManipulator( new EarthManipulator(arguments) );
    viewer.setSceneData(new MapNode(map));

	viewer.addEventHandler(new osgViewer::StatsHandler());
	viewer.addEventHandler(new osgViewer::WindowSizeHandler());

    return viewer.run();
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值