在上一章中,我们完成了细分后阶梯连接区域的构建。当我们改变地图单元高度的时候,会发现Cliff与Slope类型之间的三角形连接区域,依然会有破面的问题这也是我们之前一直搁置的一个问题。在这一章中,我们先解决cliff-slope-slope (CSS)
和slope-cliff-slope (SCS)
两种连接类型种产生破面的问题。
产生破面的问题是因为分界点(阶梯连接收束到陡峭面边缘的顶点)的计算受到了干扰。这意味着它不是精确的处于陡峭面的边缘线上,所以就产生了一个裂缝。解决方案是不要对分界点应用噪声扰动,就是说我们需要能选择一个点是否应用扰动。最简单的办法是在HexMesh.cs
中添加一个完全不对顶点进行扰动的AddTriangle
方法。代码如下:
HexMesh.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class HexMesh : MonoBehaviour { private void AddTriangleUnperturbed(Vector3 v1, Vector3 v2, Vector3 v3) { int vertexIndex = vertices.Count; vertices.Add(v1); vertices.Add(v2); vertices.Add(v3); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); } … }
|
修改TriangulateBoundaryTriangle
方法中的语句,在使用边界点构建三角面片时,边界点不在进行扰动。代码如下:
HexMesh.cs1 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
| private void TriangulateBoundaryTriangle( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 boundary, Color boundaryColor) { Vector3 v2 = HexMetrics.TerraceLerp(begin, left, 1); Color c2 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, 1);
AddTriangleUnperturbed(Perturb(begin), Perturb(v2), boundary); AddTriangleColor(beginCell.color, c2, boundaryColor);
for (int i = 2; i < HexMetrics.terraceSteps; i++) { Vector3 v1 = v2; Color c1 = c2; v2 = HexMetrics.TerraceLerp(begin, left, i); c2 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, i); AddTriangleUnperturbed(Perturb(v1), Perturb(v2), boundary); AddTriangleColor(c1, c2, boundaryColor); }
AddTriangleUnperturbed(Perturb(v2), Perturb(left), boundary); AddTriangleColor(c2, leftCell.color, boundaryColor); }
|
仔细观察TriangulateBoundaryTriangle
方法可以发现,我们并没没有用v2
去计算其他点的位置。所以在这里我们可以直接先对v2进行扰动,这样就简化了之后调用v2的代码了。代码如下:
HexMesh.cs1 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
| private void TriangulateBoundaryTriangle( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 boundary, Color boundaryColor) { Vector3 v2 = Perturb(HexMetrics.TerraceLerp(begin, left, 1)); Color c2 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, 1);
AddTriangleUnperturbed(Perturb(begin), Perturb(v2), boundary); AddTriangleColor(beginCell.color, c2, boundaryColor);
for (int i = 2; i < HexMetrics.terraceSteps; i++) { Vector3 v1 = v2; Color c1 = c2; v2 = HexMetrics.TerraceLerp(begin, left, i); c2 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, i); AddTriangleUnperturbed(Perturb(begin), v2, boundary); AddTriangleColor(c1, c2, boundaryColor); }
AddTriangleUnperturbed(v2, Perturb(left), boundary); AddTriangleColor(c2, leftCell.color, boundaryColor); }
|
现在看起来好多了,但还是会有一些问题。在TriangulateCornerTerracesCliff
方法里,分界点的位置是通过左右的坐标点插值计算得到的,但这两个点没有应用扰动。要让边界点能精确吻合陡峭斜坡边缘,需要插值去计算两个扰动过的坐标点来求得边界点。代码如下:
HexMesh.cs1 2 3 4 5 6 7 8 9 10 11
| private void TriangulateCornerTerracesCliff( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { …
Vector3 boundary = Vector3.Lerp(Perturb(begin), Perturb(right), b); … }
|
在TriangulateCornerCliffTerraces
方法中也是同理,代码如下:
HexMesh.cs1 2 3 4 5 6 7 8 9 10 11
| private void TriangulateCornerCliffTerraces( Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell) { …
Vector3 boundary = Vector3.Lerp(Perturb(begin), Perturb(right), b); … }
|
这样我们就修复了cliff-slope-slope(CSS)
和slope-cliff-slope(SCS)
两种连接类型种产生破面的问题。在接下来的章节中,我们来解决cliff-cliff-slope
连接类型种破面的问题。
Github代码