将 PerlinNoise 映射到网格

Mapping PerlinNoise to a Grid

我正在尝试在我的地图上生成一个网格并根据 perlin 噪声值添加节点。根据从某个位置的 perlin 噪声获得的值,我将添加一个新节点,该节点将属于某种类型,例如山,水等代表terrian。在这里,我试图做到这一点,如果该值 > 0.5,这意味着它只有山脉,所以黑色立方体应该围绕着山区,但是,我的黑色立方体与 perlin 噪声中的山区不匹配,我似乎无法弄清楚为什么我会出错。如果能深入了解我如何实现这一目标,我将不胜感激。

private void LocateWalkableCells()
{
    for(int z = 0; z < Height; z++)
    {
        for(int x = 0; x < Width; x++)
        {
            noise = GetNoiseValue(x, z);
            if(noise > 0.5) {
                grid[x,z] = new Node(new Vector3(x, 0, z), TerrainType.Mountain, 1);
            } 
            else {
                grid[x,z] = new Node(new Vector3(x, 0, z), TerrainType.Grass, 1);
            }
        }
    }
}

private float GetNoiseValue(int x, int z)
{
    int pos = (x * Width) + z;
    return Mathf.Round(terrainGenerator.noiseArray[pos] * 10) / 10;
}

// Draw gizmos to visualize colour
void OnDrawGizmos()
{
    Gizmos.DrawWireCube(transform.position, new Vector3(Width, 1, Height));
    if(grid != null)
    {
        foreach(Node n in grid)
        {
            if(n.TerrainType == TerrainType.Grass)
            {
                Gizmos.color = Color.green;
            } 
            else if(n.TerrainType == TerrainType.Mountain)
            {
                Gizmos.color = Color.black;
            } 

            Gizmos.DrawCube(n.Position, Vector3.one * (nodeDiameter - .1f));
        }
    }
}

noiseArray用于地形的顶点,代码如下:

vertices = new Vector3[(Width + 1) * (Depth + 1)];
noiseArray = PerlinNoise();

int i = 0;
for(int z = 0; z <= Depth; z++)
{
    for(int x = 0; x <= Width; x++)
    {
        var currentHeight = noiseArray[i];

        if(currentHeight > HeightThreshold)
        {
            currentHeight *= HeightMultiplier;
        }

        vertices[i] = new Vector3(x, currentHeight, z);
        i++;
    }
}

输出

建议答案的结果

似乎还是遗漏了一些山区,用绿色代替黑色。

认为问题出在

var pos = (x * Width) + z;

因为 x 你索引的是你可能更想要的网格宽度

var pos = z * Width + x;

换句话说你想要

  • 跳过 z
  • 每行有 Width 个元素
  • 然后从那里取出第 x 个元素

假设您的地形已布置 row-wise。

或者如果它被布局 column-wise(这很不寻常但可能)

var pos = x * Height + z;

或者换句话说

  • 跳过 x
  • 每列有 Height 个元素
  • 然后从那里取出第 z 个元素

另见 Converting index of one dimensional array into two dimensional array i. e. row and column


更新

现在您已经展示了地形生成代码,它需要

var pos = z * (Width + 1) + x;

因为地形数组实际上每行有 Width + 1 个元素。