WorldWind Java 版学习:4、地型网格的构造与渲染

1、在 WorldWindowGLAutoDrawable 对象的 display 方法中,会调用 doDisplay 方法,继而调用 AbstractSceneController 对象的 repaint 方法,在 repaint 方法中,首先调用 initializeDrawContext 方法,初始化了 DrawContext 对象,初始化过程主要的一步是清理上一帧的 SectorGeometryList 对象,然后调用 BasicSceneController 对象的 doRepaint 方法,在这个方法中通过调用 createTerrain 方法创建地型。

 

2、在 AbstractSceneController 的 createTerrain 方法中,首先判断 SectorGeometryList 对象是否为空,之前提到了,SectorGeometryList 对象会在初始化的时候被清空,所以这里将为空,然后依次获得 Model 对象和 Globe 对象,然后调用 Globe 的 tessellate 方法,而实际是调用了 Globe 的 Tessellator 类成员对象的 tessellate 方法计算生成 SectorGeometryList 对象。

 

3、在 RectangularTessellator 的 tessellate 方法中,首先创建了缓冲池,然后判断第 0 层的 Tile 是否存在,不存在而创建出来,在地型的渲染过程中,会遇到三类不同的 Tile 类型,分别是 RectTile、ElevationTile 和 TextureTile,其中 RectTile 可以理解为定义区域的,一般是用来进行求交运算的,第 0 层的切分为 3 X 6,这个值来自 RectangularTessellator 类的成员变量 DEFAULT_NUM_LAT_SUBDIVISIONS 和 DEFAULT_NUM_LON_SUBDIVISIONS,第二种 ElevationTile 是和地型有关的,存储了地型数据的网格,为 RectTile 对象提供地型数据,第 0 层的切分为 9 X 18,这个值来自文件 EarthElevationModelAsBil16.xml 中的配置(<LevelZeroTileDelta><LatLon units="degrees" latitude="20" longitude="20" /></LevelZeroTileDelta>),第三类 TextureTile 是和影像有关的,为 RectTile 对象提供纹理数据,第 0 层的切分为 5 X 10,这个值来自文件 BMNGWMSLayer.xml 中的配置(<LevelZeroTileDelta><LatLon units="degrees" latitude="36" longitude="36"/></LevelZeroTileDelta>)。

 

4、在 RectangularTessellator 的 createTopLevelTiles 方法中使用循环然后调用 createTile 方法创建了 3 X 6 = 18 个第 0 层的具有区域属性的 Tile,在 createTile 方法中,设置了 tile 的 cellSize 属性,用于之后分辨率的比较。

 

5、创建第 0 层 Tile 完成后,清理了 SectorGeometryList 类型的 currentTiles 对象,然后调用了 selectVisibleTiles 计算视域内的 Tile。selectVisibleTiles 方法采用递归的方式对每个 Tile 及其子 Tile 进行了求交和切分的操作,如果不在视域内的,直接返回,如果未达到最高分辨率且需要切分的,则将其切分为 4 份,然后继续递归计算,否则就添加到 currentTiles 中。当有视域内的 Tile 加入列表中,同时计算并合并列表的区域范围。

 

6、在判断是否达到最大分辨率时,首先通过 tile 的 sector 得到所能达到的最精细层,此处会使用到 SectorResolution 数组对象,用于限制某些特定的区域数据不能达到最精细层的情况。得到所能达到的最精细层后,取得该层的维度跨度,然后在取得 tile 的中心点对应的半径,求得两个值的乘积在去对数,最后与 tile 的 log10CellSize 属性,即前面提到的 cellSize 进行比较。在判断是否需要向下层切分时,首先计算了包括 Tile 中心和四个角在内的五个点,求出这五个点与视点的最短距离,求对数等计算之后,再与 tile 的 log10CellSize 属性进行比较。

 

7、得到所有的视域内的 RectTile,即 currentTiles 对象构造完成后,遍历其中的 SectorGeometry 对象,调用 makeVerts 方法为每个 RectTile 创建顶点。在 makeVerts 方法中,首先去缓冲池中找,有则返回,没有就调用 buildVerts 创建顶点。在 buildVerts 方法中,首先构造顶点数组对象,然后调用 computeLocations 得到 Tile 的各个顶点所对应的经纬度,在调用 globe 的 getElevations 方法得到每个顶点对应的高程值,然后使用循环计算每个顶点的空间坐标,如果使用裙边(makeSkirts),会在计算前修改高程值,最后将得到的顶点数组赋值给 tile 对象,此时,这个 tile 对象的地型网格即构造完成。

 

8、在 RectangularTessellator 对象调用 buildVerts 创建顶点完成后,则 SectorGeometryList 对象构造完成,返回至 BasicSceneController 的 createTerrain 方法,然后会调用 draw 方法开始渲染过程。在 AbstractSceneController 的 draw 方法中,使用循环对图层进行逐层渲染,初始的图层是从配置中读取的。与地型图层有关的是 Blue Marble (WMS) 2004 图层,对应的类型为 WMSTiledImageLayer,创建此对象的过程与读取配置创建地型模型的过程类似,图层的属性在 BMNGWMSLayer.xml 文件中配置。经过一系列的 render 调用后,程序转到 TiledImageLayer 的 doRender 方法中,继而进入 TiledImageLayer 的 draw 方法。

 

9、在 TiledImageLayer 的 draw 方法中,首先调用了 assembleTiles 方法计算获取全部视域内的 Tile,这里是具有影像数据的 TextureTile 对象列表,创建的过程与创建区域 RectTile 的过程类似,也是首先创建第 0 层的 TextureTile 列表,然后递归调用 addTileOrDescendants 方法进行添加和切分,中间调用 meetsRenderCriteria 方法判断是否可以添加。得到 currentTiles 列表后,首先进行了排序操作,然后获取了 SurfaceTileRenderer 对象,这里是 GeographicSurfaceTileRenderer 对象,然后调用了 renderTiles 方法开始真正的渲染过程

 

10、在 SurfaceTileRenderer 的 renderTiles 方法中,先是进行了一些 GL 的设置,然后获取在创建地型时生成的 SectorGeometryList 对象,然后循环其中的每个 SectorGeometry,这里就是之前提到的 RectTile 对象,调用 getIntersectingTiles 方法计算获取与之相交的 currentTiles 列表中的 TextureTile 对象,计算完成后得到符合条件的 TextureTile 对象列表,然后再循环 TextureTile 对象列表,对每个符合条件的对象进行纹理矩阵变换,最后调用 RectTile 对象的 renderMultiTexture 方法进行渲染,然后再经过一系列的调用,进入 RectangularTessellator 的 render(DrawContext dc, RectTile tile, int numTextureUnits) 方法,然后判断了系统是否支持 VBO,然后采用相应的方法进行最终的渲染。

posted on 2012-11-07 16:23  redfler  阅读(786)  评论(0编辑  收藏  举报

导航