4-3 顶点扰动

  在上一章中,我们使用世界坐标中的一个点,在彩色噪点图上进行采样,得到了一个4D向量。在这一章中,我们使用这个4D向量,对地图内的各个顶点进行扰动,让地图看起来有更多的变化。我们回到HexMesh.cs中,在这里我们添加一个方法Perturb 来负责这个工作。这个方法使用一个世界坐标内的点,进行扰动后,返回扰动后的坐标。代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HexMesh : MonoBehaviour
{


/// <summary>
/// 通过世界内的一个点(vector3),经过彩色噪点图扰动后,返回扰动后的Vect3
/// </summary>
/// <param name="position">世界坐标内的点</param>
/// <returns>经过噪点图扰动后的点坐标</returns>
private Vector3 Perturb(Vector3 position)
{
//利用世界空间内一点,在彩色噪点图上进行采样,得到彩色噪点图内一点的RGBA信息
Vector4 sample = HexMetrics.SampleNoise(position);
}
}

  通过世界坐标采样完成后,我们先使用原始坐标加采样坐标的方式获得新的扰动后坐标,代码如下:

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
private Vector3 Perturb(Vector3 position)
{


//使用原始坐标加上噪点图的采样坐标,得到扰动后坐标
position.x += sample.x;
position.y += sample.y;
position.z += sample.z;
return position;
}

  那么要如何快速的让地图中所有顶点都产生扰动?只需要在AddTriangleAddQuad里添加顶点到列表中时修改每个顶点就行了。代码如下:

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
private void AddTriangle(Vector3 v1, Vector3 v2, Vector3 v3)
{
int vertexIndex = vertices.Count;



//这里的坐标变为扰动后的坐标
vertices.Add(Perturb(v1));
vertices.Add(Perturb(v2));
vertices.Add(Perturb(v3));


}

private void AddQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4)
{
int vertexIndex = vertices.Count;



//这里的坐标变为扰动后的坐标
vertices.Add(Perturb(v1));
vertices.Add(Perturb(v2));
vertices.Add(Perturb(v3));
vertices.Add(Perturb(v4));


}

为什么顶点扰动后四边形依然是平坦的?
很可能并不是。这些四边形由两个不再对齐的三角形构成,因为这些三角形共享两个顶点,这些顶点的法线会平滑变化。这意味着你看不到两个三角形之间的明显过渡,如果扭曲的不是太明显,视觉效果上仍然会感觉这个四边形是平的。

  经过扰动后看起来好像没多大变化,除了单元格的坐标数字不见了之外。这是因为我们把顶点加上了噪声采样的坐标,这些坐标的计算结果总是正值,所以所有三角形都在标签上方并覆盖了它们。所以我们需要把采样的范围控制在-1至1之间。代码如下

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
private Vector3 Perturb(Vector3 position)
{


//将采样后的扰动结果控制在1到-1之间
position.x += sample.x * 2f - 1f;
position.y += sample.y * 2f - 1f;
position.z += sample.z * 2f - 1f;

return position;
}

  现在我们就完成了通过一张彩色噪点图进行采样,并对地图中每个顶点进行伪随机的扰动。但是现在的扰动范围只是在-到-1之间,效果并不是很明显,在接下来的一章中,我们将加入新的参数,来控制扰动的强度。

Github代码