目标:(十七)中问题48
主要包含两个过程:
1、以处理过请求的加载
这是真正意义上的加载,刚创建出来的请求是从缓存或文件没有关联影像、高程等数据的,需要经过多线程处理后才有数据(详见(十七))。对于这些处理过的请求,在PagerLoader的更新遍历traverse中会进行实质性的处理。具体如下:
osgEarthDrivers/engine_rex/Loader.cpp
void
PagerLoader::traverse(osg::NodeVisitor& nv)
{
for(count=0; count < _mergesPerFrame && !_mergeQueue.empty(); ++count)
{
Request* req = _mergeQueue.begin()->get();
if ( req && req->_lastTick >= _checkpoint )
{
OE_START_TIMER(req_apply);
req->apply( getFrameStamp() );
double s = OE_STOP_TIMER(req_apply);
req->setState(Request::FINISHED);
}
_mergeQueue.erase( _mergeQueue.begin() );
}
}
(1)限定处理的请求数目
在PagerLoader创建时就会设置这个数目(详见(十四))
(2)对请求的时间合法性进行判断
首先是_checkpoint,它是在rex引擎refresh的时候调用PagerLoader的clear方法设置的,是一个64位的高精度整型,不同的编译器定义不同。这个值只设置一次,后面不会再修改。
osgEarthDrivers/engine_rex/Loader.cpp
void
PagerLoader::clear()
{
// Set a time checkpoint for invalidating old requests.
_checkpoint = osg::Timer::instance()->tick();
}
这里的tick函数为:
osg/Timer.cpp
Timer_t Timer::tick() const
{
LARGE_INTEGER qpc;
if (QueryPerformanceCounter(&qpc))
{
return qpc.QuadPart;
}
}
这里的QueryPerformanceCounter为windows的API函数,用于获取高精度的时间。感觉这里没有必要采用这么高精度的时间吧?
再者是请求的_lastTick,这个值在PagerLoader的load函数中设置,为系统的当前时间。
只有请求的_lastTick在PagerLoader的_checkpoint之后才有意义。
(3)应用请求apply()
(3.1)比较请求的瓦片模型和地图的版本是否一致
请求的瓦片模型_dataModel在请求的流转过程中由请求的invoke函数创建,是根据_mapFrame中的版本号来的。地图的版本号初始值为-1,在添加、删除、移动图层后,地图的版本号都会增加1。
(3.2)将瓦片模型合并到瓦片节点中
(3.2.1)合并颜色(影像)
(3.2.2)合并高程
(3.2.3)合并法线
(3.2.4)合并其它共享层
(3.2.5)更新子瓦片节点
(3.2.6)通知地形节点添加了瓦片
(3.3)设置瓦片节点请求信息数据标志TileNode::setDirty
(4)设置请求的状态为已完成Request::FINISHED
(5)从合并请求队列_mergeQueue中移除该请求,注意在请求队列_requests中还存在
2、对一些请求进行裁剪
遍历所有请求列表_requests中的请求,对每一个请求执行如下操作:
(1)如果请求完成(状态为FINISHED),设置请求状态为IDLE,更新寄存器中瓦片的活动记录,从请求列表中删除请求。
(2)如果请求还没有放入请求合并队列_mergeQueue,并且请求的帧号和当前的帧号差值超过2,更新寄存器中瓦片的活动记录,从请求列表中删除请求。
(3)如果请求还已放入请求合并队列_mergeQueue,并且请求的帧号和当前的帧号差值超过1800,更新寄存器中瓦片的活动记录,从请求列表中删除请求。
3、执行父节点的更新遍历
osgearth中可能用到的几个全局实例对象(osgDB::Registry osgEarth::Registry osg::Timer osg::DisplaySetting)
osgEarth::Map::addLayer过程详解
TileNode::setDirty过程详解
请求四个状态的含义(IDLE RUNNING MERGING FINISHED)
请求经过PagerLoader加载时初始化为RUNNING 请求在加入合并队列_mergeQueue时设为MERGING 请求在执行完apply()时设置为FINISHED 请求在PagerLoader的traverse后会进行裁剪状态会设为IDLE
什么时候删除TileNode节点,不会一直增加吧
寄存器中请求状态活动记录的含义Registry::instance()->endActivity( req->getName() );