osgEarth的Rex引擎原理分析(三十三)分页瓦片卸载器子节点的作用

本文详细分析了osgEarth的Rex引擎中分页瓦片卸载器子节点的作用。在RexTerrainEngineNode的渲染遍历过程中,卸载器通过扫描器判断并添加休眠状态的瓦片节点,随后在更新遍历时移除这些瓦片,同时管理资源释放器,确保在适当时间释放OpenGL资源,维持场景与活跃瓦片寄存器的一致性。

目标:(十二)中的问题22

分页瓦片卸载器是在Rex引擎的setMap函数中创建的,创建之初就关联了活跃瓦片寄存器和资源释放器。作用见下面分析。

osgEarthDrivers/engine_rex/RexTerrainEngineNode.cpp
void
RexTerrainEngineNode::setMap(const Map* map, const TerrainOptions& options)
{  
    // Make a tile unloader
    _unloader = new UnloaderGroup( _liveTiles.get() );
    _unloader->setThreshold( _terrainOptions.expirationThreshold().get() );
    _unloader->setReleaser(_releaser.get());
    this->addChild( _unloader.get() );
}

1、渲染遍历时在RexTerrainEngineNode裁剪遍历阶段向卸载器中添加要删除的瓦片节点,如何确定要删除的瓦片节点 由RexTerrainEngineNode的上下文环境中的endCull函数中的扫描器来确定(endCull最终是在RexTerrainEngineNode在渲染遍历时调用):

osgEarthDrivers/engine_rex/EngineContext.cpp
void
EngineContext::endCull(osgUtil::CullVisitor* cv)
{
    std::vector<TileKey> tilesWithChildrenToUnload;
    Scanner scanner(tilesWithChildrenToUnload, cv->getFrameStamp());
    _liveTiles->run( scanner );
    if ( !tilesWithChildrenToUnload.empty() )
    {        
        getUnloader()->unloadChildren( tilesWithChildrenToUnload );
    }
}
osgEarthDrivers/engine_rex/TileNodeRegistry.cpp
void
TileNodeRegistry::run( const TileNodeRegistry::ConstOperation& op ) const
{
    Threading::ScopedReadLock lock( _tilesMutex );
    op.operator()( _tiles );
    OE_TEST << LC << _name << ": tiles=" << _tiles.size() << std::endl;
}

扫描器的扫描过程如下:

osgEarthDrivers/engine_rex/EngineContext.cpp
        enum Policy {
            POLICY_FIND_ALL,
            POLICY_FIND_SOME,
            POLICY_FIND_ONE
        };
        void operator()(const TileNodeRegistry::TileNodeMap& tiles) const
        {
            if ( tiles.empty() ) return;
            unsigned f = _stamp->getFrameNumber(), s = tiles.size();

            switch (_policy)
            {
                case POLICY_FIND_ALL:
                {
                    for (TileNodeRegistry::TileNodeMap::const_iterator i = tiles.begin(); i != tiles.end(); ++i)
                    {
                        const TileNode* tile = i->second.tile.get();
                        if (tile->areSubTilesDormant(_stamp))
                            _keys.push_back(i->first);
                    }
                }
                break;

                case POLICY_FIND_ONE:
                {
                    const TileNode* tile = tiles.at(f%s);
                    if (tile->areSubTilesDormant(_stamp))
                    {
                        _keys.push_back(tile->getKey());
                    }
                }
               
<think>根据用户的问题,用户想要了解在osgEarth中加载TMS地形瓦片时如何设置最大瓦片级数。结合提供的引用,特别是引用[3]中提到了瓦片分级(rex引擎的21级和Google的23级),我们可以推断设置最大瓦片级数可能与瓦片地图服务本身的能力以及osgEarth的配置有关。 在osgEarth中,通常通过Earth文件(.earth)中的配置项来设置瓦片层的属性。对于TMS地形瓦片,我们可以在对应的图层(ImageLayer或ElevationLayer)中设置最大层级(max_level)。 具体步骤: 1. 在Earth文件中,找到对应的地形图层(可能是ElevationLayer)。 2. 在图层内添加`<max_level>`标签,设置最大层级数值。 示例Earth文件片段: ```xml <elevation name="my_tms_terrain" driver="tms"> <url>http://example.com/tms/terrain</url> <max_level>18</max_level> </elevation> ``` 注意: - `max_level`的值应该根据你的TMS服务实际支持的最大级别来设置。如果设置的级别超过服务实际提供的级别,可能会导致加载失败或空白。 - 引用[3]中提到rex引擎默认最大为21级,而Google为23级,这可能是不同瓦片服务采用的级别不同,所以需要根据实际情况设置。 另外,如果是在代码中动态设置,可以使用osgEarth的API。例如: ```cpp osg::ref_ptr<osgEarth::ElevationLayer> layer = new osgEarth::ElevationLayer(); layer->setName("my_tms_terrain"); layer->setURL("http://example.com/tms/terrain"); layer->options().maxLevel() = 18; ``` 但是用户的问题中并没有明确是使用Earth文件还是代码,通常Earth文件配置更常见,所以优先给出Earth文件的配置方法。 如果用户遇到设置后无效的情况,可能需要检查: 1. TMS服务是否支持该级别。 2. 是否在正确的图层(地形图层)中设置。 3. 是否有其他设置覆盖了最大层级(比如在Map选项中设置了全局最大层级)。 引用[3]中提到的rex引擎的默认21级,这可能是osgEarth内部引擎的限制。如果用户需要超过21级,可能需要检查osgEarth的版本和配置。不过,通常TMS服务的最大级别不会超过23级(如Google地图)。 总结:在Earth文件中对应的地形图层内添加`<max_level>`标签并设置所需的最大层级。 </think> 在 osgEarth 中加载 TMS 地形瓦片时,可通过以下方法设置最大瓦片级数: ### 1. **在 Earth 文件中配置** 在 TMS 图层的定义中添加 `<max_level>` 标签指定最大级别: ```xml <elevation name="tms_terrain" driver="tms"> <url>http://tileserver/{z}/{x}/{y}.terrain</url> <max_level>18</max_level> <!-- 设置最大加载级别 --> </elevation> ``` ### 2. **通过代码动态设置** 在 C++ 代码中使用 `ElevationLayer::setMaxLevel()` API: ```cpp #include <osgEarth/ElevationLayer> #include <osgEarth/TMS> // 创建 TMS 地形层 TMSOptions tmsOptions; tmsOptions.url() = "http://tileserver/{z}/{x}/{y}.terrain"; // 设置最大瓦片级别为 18 tmsOptions.maxLevel() = 18; // 添加到地图 ElevationLayer* layer = new ElevationLayer("tms_terrain", tmsOptions); map->addElevationLayer(layer); ``` ### 关键注意事项: 1. **级别范围** 最大级别需在 TMS 服务支持的范围内(通常 `0` 为最低分辨率,`18-23` 为最高),超出实际级别会导致加载失败[^3]。 2. **性能平衡** 高级别瓦片(如 `>20`)会显著增加内存和渲染负载,需根据硬件能力调整。 3. **引擎限制** osgEarthRex 引擎默认最大支持 21 级,若需更高(如 23 级),需修改引擎配置。 4. **坐标系匹配** 确保瓦片坐标系(如 `EPSG:3857`)与 osgEarth 的 `SpatialReference` 设置一致。 > **示例效果**:设置 `max_level=18` 后,当地形缩放级别超过 18 时,将自动停止加载更精细的瓦片,改用下级瓦片插值。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值