3-10 三角形连接区域类型分析

  在上一章中,我们通过判断两个地图单元的高低差,实现了只对Slope类型的连接区域进行阶梯化。接下来,就是要将三角形连接区域进行阶梯化。
  相比于矩形连接区域,三角形连接区域的阶梯化会更加复杂,因为它连接了3个地图单元。这三个地图单元可能是任意高度,每两个地图单元之间的高差类型也是任意的。所以需要在HexMesh.cs中另外添加一个三角形连接区域的专用方法。
  首先,我们先将三角形连接区域相邻的三个地图单元进行分类,分别为Left、Right和Bittom。

  接下来,在新增加的方法中,我们先获取这三个地图单元的位置坐标和其颜色,方便之后进行阶梯化计算。

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// <summary>
/// 构建三角形连接区域的方法
/// 判断相邻3个cell高低的工作,在TriangulateConnection方法中实现了,这里只负责创建连接区域
/// 注意,TriangulateConnection方法只是对入参的顺序做了调整,但是并没有告知3个cell之间相对的连接类型
/// 所以要在这个方法中对连接类型进行判断,这样才能决三角形连接区域定用什么方式进行三角剖分
/// </summary>
/// <param name="bottom">bottom cell的坐标</param>
/// <param name="bottomCell">bottom cell的实例</param>
/// <param name="left">left cell的坐标</param>
/// <param name="leftCell">left cell的实例</param>
/// <param name="right">right cell的坐标</param>
/// <param name="rightCell">right cell的实例</param>
private void TriangulateCorner(
Vector3 bottom, HexCell bottomCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{
//这里先使用旧的方法来构建三角形连接区域,也就是没有阶梯化的那种
//经过连接类型判断后,这个方法就会被代替掉
AddTriangle(bottom, left, right);
AddTriangleColor(bottomCell.color, leftCell.color, rightCell.color);
}

  我们回到TriangulateConnection方法中,在这个方法中,我们要判断与三角形连接区域相邻的三个地图单元,哪一个是最低的。
  这里要注意一点,结合上图,我们现在只是判断哪个地图单元的高度最低,而不是对这三个地图单元的高度进行排序。因为一个三角形连接区域的三个地图单元,其坐标是固定的,当确定了哪个地图单元是最低的一个时,剩下两个的顺序其实就是固定的了。所以不存在排序问题。整理后的逻辑图如下:

  根据整理后的逻辑图可以发现,判断最低的地图单元,实际上就是将图1中的3个地图单元进行顺时针或逆时针的旋转。
  首先我们先检查第一个地图单元的高度,如果它小于其他两个地图单元,那么它就是最低的一个。

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
private void TriangulateConnection(HexDirection direction, HexCell cell, Vector3 v1, Vector3 v2)
{


if (direction <= HexDirection.E && nextNeighbor != null)
{


//参考图 http://magi-melchiorl.gitee.io/pages/Pics/Hexmap/3-10-1.png
//这里要注意,只是要找出3个cell中高度最低的一个
//因为三角形连接区域的3个cell,其坐标是固定的,找出最低的一个时,其他两个cell的入参顺序就是固定的了

//注意,教程4.1是有错误的但是最后给的代码是对的,这里注释掉的语句是教程错误的语句
if (cell.Elevation <= neighbor.Elevation)
{
//并且cell1高度小于cell3
if (cell.Elevation <= nextNeighbor.Elevation)
{
//cell1最低
//TriangulateCorner(v2, cell, v4, nextNeighbor, v5, nextNeighbor);
TriangulateCorner(v2, cell, v4, neighbor, v5, nextNeighbor);
}
}
}
}

  如果cell的高度大于nextNeighbor的高度,说明nextNeighbor的高度最低。

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
private void TriangulateConnection(HexDirection direction, HexCell cell, Vector3 v1, Vector3 v2)
{


if (direction <= HexDirection.E && nextNeighbor != null)
{


if (cell.Elevation <= neighbor.Elevation)
{
//并且cell1高度小于cell3
if (cell.Elevation <= nextNeighbor.Elevation)
{
//cell1最低
//TriangulateCorner(v2, cell, v4, nextNeighbor, v5, nextNeighbor);
TriangulateCorner(v2, cell, v4, neighbor, v5, nextNeighbor);
}
else
{
//cell3 最低
//TriangulateCorner(v5, nextNeighbor, v2, cell, v4, nextNeighbor);
TriangulateCorner(v5, nextNeighbor, v2, cell, v4, neighbor);
}
}
}
}

  最后,如果cell高度大于neighbor,那么只需要检测neighbornextNeighbor之间的高度就可以了。

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
private void TriangulateConnection(HexDirection direction, HexCell cell, Vector3 v1, Vector3 v2)
{


if (direction <= HexDirection.E && nextNeighbor != null)
{


if (cell.Elevation <= neighbor.Elevation)
{
//并且cell1高度小于cell3
if (cell.Elevation <= nextNeighbor.Elevation)
{
//cell1最低
//TriangulateCorner(v2, cell, v4, nextNeighbor, v5, nextNeighbor);
TriangulateCorner(v2, cell, v4, neighbor, v5, nextNeighbor);
}
else
{
//cell3 最低
//TriangulateCorner(v5, nextNeighbor, v2, cell, v4, nextNeighbor);
TriangulateCorner(v5, nextNeighbor, v2, cell, v4, neighbor);
}
}
//如果cell1>cell2,且cell2<cell3
else if (neighbor.Elevation <= nextNeighbor.Elevation)
{
//cell2最低
//TriangulateCorner(v4, nextNeighbor, v5, nextNeighbor, v2, cell);
TriangulateCorner(v4, neighbor, v5, nextNeighbor, v2, cell);
}
else
{
//cell3最低
//TriangulateCorner(v5, nextNeighbor, v2, cell, v4, nextNeighbor);
TriangulateCorner(v5, nextNeighbor, v2, cell, v4, neighbor);
}
}
}

  这样,我们就找到了三角形连接区域中,高度最低的那个地图单元了。在接下来的章节中,我们会在这个基础上,使用循环来对三角形连接区域进行阶梯化,根据不同的高差类型,来构建不同的三角形连接区域外观。

Github代码