6-13 区分是否有河流

  在上一章中,我们对河床最低点的顶点进行了偏移,当鼠标左键按下并拖拽的时候,就会产生相应的河道。但是我们发现河道进入地图单元后,并不像在连接处那样保持宽度,而变成了逐渐向地图单元中心汇集。修复这个问题比较复杂,我们来分情况讨论。首先我们从最简单的情况开始考虑:河流从一侧流入地图单元,又从其相对的方向流出。
  如果一个地图单元中没有河流,其顶点与一条边所组成的图形是一个扇形。当有河流时,就需要把地图单元中被河流穿过的三角形变成四边形,而扇形整体就变成了梯形。如下图所示:

  穿过地图单元的河道要比穿过连接处的河道长很多,所以地图单元内组成河道的各个顶点被扰动后,变化会更加明显。为了减小扰动所带来的这个问题,我们在顶点到边缘之间再插入一个新的顶点,将原来的区域分为两段。如下图所示:

  一个地图单元内,有河流穿过和没有河流穿过,两者的三角剖分会有很大不同。这里我们为此创建一个新的方法。如果一个地图单元内有河流经过,就使用这个新创建的方法,如果没有,就使用之前的方法。代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class HexMesh : MonoBehaviour
{



private void Triangulate(HexDirection direction, HexCell cell)
{
if (cell.HasRiver)
{
//检测当前边缘是否有河流穿过
if (cell.HasRiverThroughEdge(direction))
{
//如果有河流穿过,就降低中间顶点的高度,使其成为河床最低点
e.v3.y = cell.StreamBedY;

//使用带河流的构建方式
TriangulateWithRiver(direction, cell, center, e);
}
}
else
{
//在计算出各个点的位置信息后,直接构建三角面片
//这个是不带河流的构建方式
TriangulateEdgeFan(center, e, cell.Color);
}


}



/// <summary>
/// 当cell中有河流的时候,使用这个方法来进行构建
/// 参考图 http://magi-melchiorl.gitee.io/pages/Pics/Hexmap/6-13-1.png
/// </summary>
/// <param name="direction">河流方向</param>
/// <param name="cell">cell这身实例</param>
/// <param name="center">cell中心点实际位置</param>
/// <param name="e">河流穿过的这个边,在这条边上所有的顶点的位置信息</param>
private void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
{

}
}

  我们虽然创建了有河流经过地图单元时,所使用的三角剖分方法,但是并没有任何内容,所以现在河流经过的地图单元是空的。如下图所示:

  为了更好的观察三角剖分情况,我们先暂时不使用坐标扰动。代码如下:

HexMetrics.cs
1
2
3
4
5
6
public static class HexMetrics
{


public const float cellPerturbStrength = 0f;//4f;
}

  至此,我们根据十一地图单元内是否有河流进行了区分,从而使用了不同的三角剖分方式进行构建。在下一张中,我们先处理最简单的河流情况,也就是河流笔直穿过一个地图单元。

Github代码