目标:(十六)中问题38
瓦片请求的大概过程是这样的:
1、osgEarth::Drivers::RexTerrainEngine::TileNode在渲染遍历时产生LoadTileData请求,将请求传递给DatabsePager改造成DatabaseRequest请求后(LoadTileData的ID会写入字符串放入DatabaseRequest中),将此请求放入了DatabasePager的_fileRequestQueue队列中
2、DatabasePager的运行线程DatabaseThread又将DatabaseRequest请求部分属性进行设置后(真正的数据获取就在这里完成,调用PagerLoader将请求的瓦片数据(高程、影像等)放入LoadTileData请求中),放入DatabasePager的_dataToMergeList的队列中。
3、在更新遍历DatabasePager时,将其_dataToMergeList列表中的DatabaseRequest请求经过转换成LoadTileData请求后,放入瓦片分页加载器PagerLoader的_mergeQueue队列中
4、在更新遍历时瓦片分页加载器处理_mergeQueue中的请求,构建TileNode的渲染模型_renderModel,TileRenderModel主要记录渲染各个瓦片的通道,一个通道对应一个可视化层(颜色、高层、法线等),每个瓦片TileNode都包含一个TileRenderModel。这样就做好了绘制瓦片的数据准备工作。
5、对瓦片进行绘制,绘制流程见 osgEarth的Rex引擎原理分析(四十五)TileNode绘制过程详解
下面围绕着每个过程中的子过程有哪些,请求是如何在其中运转腾挪的这么一个思路来详细展开。
1、osgEarth::Drivers::RexTerrainEngine::TileNode在渲染遍历时产生请求
(1)在渲染遍历时,TileNode通过PagerLoader加载请求
osgEarthDrivers/engine_rex/TileNode.cpp
void
TileNode::load(TerrainCuller* culler)
{
_context->getLoader()->load( _loadRequest.get(), priority, *culler );
}
这里的_context为rex引擎RexTerrainEngineNode中设置的(见(十二)),在TileNode执行create的时候赋值。getLoader就是获取分页瓦片加载器PagerLoader,然后由PagerLoader执行load方法加载请求。
这里的_loadRequest为LoadTileData对象,是TileNode的成员变量,在TileNode执行create的时候赋值。从代码可以看出,创建瓦片节点时,相应的高程和影像数据并没有同时加载进来,而是通过多线程处理请求的方式来加载。
osgEarthDrivers/engine_rex/TileNode.cpp
void
TileNode::create(const TileKey& key, TileNode* parent, EngineContext* context)
{
_context = context;
_loadRequest = new LoadTileData( this, context );
_loadRequest->setName( _key.str() );
_loadRequest->setTileKey( _key );
}
这里的priority意思为加载瓦片的优先级
这里的culler为裁剪遍历器
(2)PagerLoader再通过DatabasePager处理请求
osgEarthDrivers/engine_rex/Loader.cpp
bool
PagerLoader::load(Loader::Request* request, float priority, osg::NodeVisitor& nv)
{
request->setState(Request::RUNNING);
// remember the last tick at which this request was submitted
request->_lastTick = osg::Timer::instance()->tick();
// update the priority, scale and bias it, and then normalize it to [0..1] range.
unsigned lod = request->getTileKey().getLOD();
float p = priority * _priorityScales[lod] + _priorityOffsets[lod];
request->_priority = p / (float)(_numLODs+1);
request->setFrameNumber( fn );
request->_loadCount++;
char filename[64];
sprintf(filename, "%u.osgearth_rex_loader", request->_uid);
nv.getDatabaseRequestHandler()->requestNodeFile(
filename,
_myNodePath,
request->_