延续上文的区块加载触发,触发完了之后要做的事情就是发布加载任务。然而发布加载任务的流程不止在刚刚触发时执行,很多地方都会要执行这个流程,所以便要拎出来单说。阅读本篇前请阅读前文
区块加载任务的发布流程第一步是将要发布任务的区块做一个排序。首先会遍历将要加载的区块列表里的每一个区块坐标和状态,为每一个计算出一个优先级。然后根据这些优先级为区块做一个排序,优先级数值越小的越优先。然后根据排序后的列表一个一个的取出区块,检测它是否满足发布的条件,然后获取加载相关的数据以及要进行什么样的加载任务,最终将它加入任务队列。
区块加载的优先级的计算通过维度的一个ChunkBuildOrderPolicy对象获取。这个对象记录了区块加载的“加载源”,并可以通过坐标查询和添加。加载源是触发区块加载的源头,有三类:0、玩家 1、方形常加载区块 2、圆形常加载区块。然后会遍历每一个加载源,通过每一个加载源计算出一个单独的优先级,然后取这些优先级的最小值作为返回的最终优先级。
玩家源优先级算法:
设玩家所在区块位置为(Px, Pz),要加载的区块的区块位置为(x,z),玩家看向的方向向量为(Vx,Vz)。
Dir1 = (Vx, Vz)/sprt(Vx^2 + Vz^2)
Dir2 = (x-Px,z-Pz)/sprt((x-Px)^2+(z-Pz)^2)
c=Dir1 * Dir2(点积)
如果c<0,w=1, 如果c>=0, w=0.75*(1-c)+0.25
Priority = sprt((x-Px)^2+(z-Pz)^2)*(w+(1-w)*abs(Vx))
圆形常加载优先级算法:
如果区块在加载范围内Priority=1,如果不在就为0
方形常加载优先级算法:
如果在方形范围内 Priority = -somevalue(不清楚),如果不在就等于INT_MAX
在计算完优先级后,便会对这些区块进行排序,然后一个一个取出来构建加载任务并发布。
需要注意的一点是,一个区块加载任务不代表要直接把区块加载完,而是将区块加载从一个阶段推向另一个阶段。
加载任务主要由四部分组成:一个区块加载函数指针,一个Mainchunksource,一个levelchunk对象,一个chunkviewsource。
首先它会从mainchunksource的父级里获取以该区块为中心的3*3范围内的区块坐标。创建一个以mainchunksource为父级,3*3区块为区域的chunkviewsource。这个chunkviewsource用于区块加载任务(有四种,对应四个阶段)中可能的跨区块数据交互。(后文会详细说明)
然后它会遍历这个chunkviewsource里的区块,检查这些区块是否存在。如果有一个没有创建就直接返回不发布任务。
随后会获取这个要加载的区块的加载状态,如果是0就变成1,然后发布区块生成任务。如果是2就变成3,然后发布区块装饰的任务。
就是把偶数(代表阶段完成)推向奇数(代表阶段开始)
1-2:区块生成
3-4:区块装饰
5-6:数据替换
7-8:光照初始化