3-11 Slope类型的三角形连接区域构建

  在上一章中,我们对一个三角形连接区域,相邻的三个地图单元高度进行了分析,通过判断和比较,知道了三个地图单元中,哪个地图单元最高,哪个底图单元最低。
  再结合之前章节中对高度差的分类,我们现在就可以对三角形连接区域进行构建了。不过因为高度差不同,所以三角形连接区域的构建也有很多种类。这里我们需要分类进行实现。
  我们要构建三角形链接区域,首先需要知道我们处理的是哪种连接区域类型,在HexCell.cs中添加一个新的方法,来回去两个单元格之间对连接类型

HexCell.cs
1
2
3
4
5
6
7
8
9
/// <summary>
/// 对比自身和另一个cell的高度,返回两个cell的连接类型
/// </summary>
/// <param name="otherCell">另一个cell的实例</param>
/// <returns>两个cell的连接类型</returns>
public HexEdgeType GetEdgeType(HexCell otherCell)
{
return HexMetrics.GetEdgeType(elevation, otherCell.elevation);
}

  在HexMesh.TriangulateCorner方法中,使用GetEdgeType确认相邻的Left和Right地图单元的连接类型。

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
private void TriangulateCorner(
Vector3 bottom, HexCell bottomCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{
//这里先获取Left和Right两个cell,相较于Bottom cell的高度类型,这样才能决定怎样做三角剖分
HexEdgeType leftEdgeType = bottomCell.GetEdgeType(leftCell);
HexEdgeType rightEdgeType = bottomCell.GetEdgeType(rightCell);


}

  如果Left和Right两个地图单元,相较于Bottom对连接类型都是Slope类型。那么就说明,Left和Right两个地图单元高度是相同的,他们两者之间的连接类型是Flat。而且Left和Right两个地图单元与Bottom地图单元对矩形连接区域,都是阶梯状的。我们称这种连接类型为Slope-Slope-Slat,或者简称SSF。如图所示:

  为了方便观察新构建的三角形连接区域,我们将之前的构建三角形连接区域的语句注释掉,代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
}


private void TriangulateConnection(HexDirection direction, HexCell cell, Vector3 v1, Vector3 v2)
{


//AddTriangle(v2, v4, v5);
//AddTriangleColor(cell.color, neighbor.color, nextNeighbor.color);
}

  接下来,我们创建一个新的方法TriangulateCornerTerraces,这个方法专门用来创建阶梯状的三角形连接区域。如果在TriangulateConnection方法中判断两个相邻的地图单元难道连接类型为SSF,那么就调用这个方法。代码如下:

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
private void TriangulateCorner(
Vector3 bottom, HexCell bottomCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{


//这里通过获取的Left和Right 相较于Bottom的连接类型进行判断,具体三个cell的高度关系
//判断完成后,直接调用对应的方法构建三角形连接区域,而不使用之前通用的方法构建
if (leftEdgeType == HexEdgeType.Slope)
{
if (rightEdgeType == HexEdgeType.Slope)
{
//这里判断为SSF类型
TriangulateCornerTerraces(bottom, bottomCell, left, leftCell, right, rightCell);
return;
}
}


}

/// <summary>
/// 创建阶梯状的三角形连接区域
/// </summary>
/// <param name="begin">初始cell位置</param>
/// <param name="beginCell">初始cell实例</param>
/// <param name="left">左侧cell位置</param>
/// <param name="leftCell">左侧cell实例</param>
/// <param name="right">右侧cell位置</param>
/// <param name="rightCell">右侧cell实例</param>
private void TriangulateCornerTerraces(
Vector3 begin,HexCell beginCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{
}

  在Unity中运行代码,会看到现在符合SSF类型的连接,三角形连接区域是一个洞,这表明在洞的位置,我们调用了TriangulateCornerTerraces方法,而不是默认构建三角形连接区域的方法,如下图所示:

  现在让我们用阶梯化的三角形连接区域填补上这个洞。要填补这个洞,就需要连接左右两个地图单元的矩形阶梯化连接区域。思路与创建矩形阶梯化连接区域基本相同,先从底部第一个阶梯开始构建。只不过顶点需要从左右两边的阶梯状矩形连接区域获取。代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void TriangulateCornerTerraces(
Vector3 begin,HexCell beginCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{
//计算出与begin相邻的两个cell,每个阶梯的顶点和其对应的颜色
Vector3 v3 = HexMetrics.TerraceLerp(begin, left, 1);
Vector3 v4 = HexMetrics.TerraceLerp(begin, right, 1);
Color c3 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, 1);
Color c4 = HexMetrics.TerraceLerp(beginCell.color, rightCell.color, 1);

//与矩形阶梯区域不同的是,阶梯三角形连接区域最下端是一个三角形,这里先构建这个三角形
AddTriangle(begin, v3, v4);
AddTriangleColor(beginCell.color, c3, c4);
}

  这样,我们就得到了底部的第一段阶梯,如图所示:

  与阶梯化矩形连接区域步骤相同,我们直接进行最后一步的构建,将第一段阶梯的两个顶点,和末端的两个顶点相连接,组成一个梯形。这里与阶梯化矩形区域不同的是,梯形的4个端点颜色是不同的,代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
private void TriangulateCornerTerraces(
Vector3 begin,HexCell beginCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{


//构建剩余的部分
AddQuad(v3, v4, left, right);
AddQuadColor(c3, c4, leftCell.color, rightCell.color);
}

  最后,与构建阶梯矩形连接区域类似,循环获取阶梯上的各个顶点和颜色值,创建各个阶梯矩形区域即可。代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void TriangulateCornerTerraces(
Vector3 begin,HexCell beginCell,
Vector3 left, HexCell leftCell,
Vector3 right, HexCell rightCell)
{


//循环获取中间部分的顶点位置和颜色信息
for (int i = 2; i < HexMetrics.terraceSteps; i++)
{
Vector3 v1 = v3;
Vector3 v2 = v4;
Color c1 = c3;
Color c2 = c4;
v3 = HexMetrics.TerraceLerp(begin, left, i);
v4 = HexMetrics.TerraceLerp(begin, right, i);
c3 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, i);
c4 = HexMetrics.TerraceLerp(beginCell.color, rightCell.color, i);
AddQuad(v1, v2, v3, v4);
AddQuadColor(c1, c2, c3, c4);
}
}

  这样,我们就完成了SSF类型连接区域的构建。不过SSF类型还存在一些变体情况,我们在下一个章节进行完善。

Github代码