OsgEarth的tile

来源:互联网 发布:ce6.6源码 编辑:程序博客网 时间:2024/04/29 13:36

OsgEarth 之 Tile 构建  (转载自网易http://giskel.blog.163.com/blog/static/7166004520137482047116/)

看到OsgEarth的首先想了解的就是这个球怎么绘制出来了;经过了几天代码的漫长跟踪,大致理解了一些。OsgEarth是基于瓦片切片构建的,关键就在于瓦片的构建和管理。主要的类有:

TileModel:瓦片模型(会交给显卡最终绘制出)。
TileModelFactory:瓦片模型工厂,负责瓦片模型的创建。
TileNode:瓦片节点,用于构建场景树,挂接瓦片模型。
TileNodeRegistry:瓦片节点代理,负责瓦片节点的管理,存储了每个已经创建出来的瓦片节点的引用。
TileKey:根据瓦片的行列号以及层级创建的,用做Tile的关键字。
TileSource:瓦片源,它由插件创建并提供给Map根据瓦片关键字创建瓦片。Map中可以含有多个图层,每个图层都指定了数据以及引擎(Driver)。在MapNode初始化的时候都会根据Driver生成TileSource类。所以一个图层对应一个TileSource,用于对数据进行读取和处理。

OsgEarth是按瓦片方式利用PagedLod(分页调度算法)来组织地球的各级节点,加载和卸载节点由OSGPagedLod来管理。根据摄像机的位置动态加载和卸载不同的PagedLod和相应PagedLod上的实体。所以必须提前指定好PagedLod每个层级的文件及距离范围:
osg::PagedLOD* pagedLOD = new osg::PagedLOD;

pagedLOD->setFileName(0, node_1.osg);

pagedLOD->setRange(0, minRange1, maxRange1);

pagedLOD->setFileName(1, node_2.osg);

pagedLOD->setRange(1, minRange2, maxRange2);

OsgEarth的瓦片动态加载流程:
1)根据摄像机的位置,获得距离条件成立的PagedLod(OSG完成);
2)读取PagedLod对应的文件,通过readNode方法生成下一层的四个子节点并根据条件加入PagedLod队列(瓦片基于四叉树),为摄像机到达下一层节点做准备;
3)重复上面过程。
例如:osgEarth_MPTerrainEngineDriver继承osgDB::ReaderWriter,并重载了readNode方法,实现了对瓦片的组织、加载等。由于在创建PagedLod的时候通过setFileName方法指定了文件名,所有在动态加载的时候会按照我们重载的readNode方法读取数据。
第一个瓦片的生成过程里有空间索引的创建,有了第一个切片就能够按照PagedLod方法创建接下来的一层层四叉树瓦片了。随着一层层深入,瓦片就变得越来越小,当瓦片大小比摄像机到瓦片的距离还小时,PagedLod的距离条件就不再符合也就不再调入了。这样视点正下方的瓦片最小也最精细,越远瓦片越大也就越粗糙,符合我们的视觉原理。而总的块数也不会太多,提高了性能。

lod层级的限制条件有很多,其中以影像分辨率限制的最为普遍。在创建Tile的时候会获取影像,获取影像的时候就会用到最小最大lod判断是否有必要创建影像,以致是否创建Tile。如果没有手动设置则会TileSource中计算最小最大的lod级数,大致过程为:

    根据影像的覆盖范围以及分辨率,能够算出分辨率(即一个像素代表的地理范围),这个分辨率作为Tile的最大分辨率。然后从第0层开始计算每层tile的分辨率(根据层数可以算出Tile的地理范围,而Tile的默认图片大小为256*256),如果分辨率小于最大分辨率则停止。

0 0