目标:(十二)中的问题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());
}
}
break;
default:
case POLICY_FIND_SOME:
{
for(unsigned i=0; i<4; ++i) {
const TileNode* tile = tiles.at((f+i)%s);
if ( tile->areSubTilesDormant(_stamp) )
_keys.push_back( tile->getKey() );
}
}
}
}
扫描策略默认为POLICY_FIND_ALL,扫描的对象即为活跃瓦片寄存器。对于活跃瓦片寄存器中的每一个瓦片,判断其子瓦片是否处于休眠状态Dormant,也即判断最近一次遍历时的帧号和时间与当前做比