计算格子贴图索引数字

为噪声图生成的随机数值匹配对应的地形

public enum MapVertexType
{
    Frost,
    Marsh,
}

public class MapVertex
{
    public Vector3 Position;
    public MapVertexType VertexType;
}

public class MapCell
{
    public Vector3 Position;
    public int TextureIndex;
}

定义地图类型枚举变量并让顶点持有,为地图格子添加贴图索引成员。

    /// <summary>
    /// 计算格子贴图的索引数字
    /// </summary>
    public int[,] CalculateCellTextureIndex(float [,] noiseMap, float limit)
    {
        int width = noiseMap.GetLength(0);
        int height = noiseMap.GetLength(1);

        for (int x = 1; x <= width; x++)
        {
            for (int z = 1; z <= height; z++)
            {
                //基于噪声的值确定定点类型
                //大于边界是沼泽,否则是森林
                if (noiseMap[x - 1,z - 1] >= limit)
                {
                    SetVertexType(x, z, MapVertexType.Marsh);
                }
                else
                {
                    SetVertexType(x,z, MapVertexType.Forest);
                }
            }
        }
        int [,] textureIndexMap = new int[width,height];
        for (int x = 0; x < width; x++)
        {
            for (int z = 0; z < height; z++)
            {
                textureIndexMap[x, z] = GetCell(x + 1, z + 1).TextureIndex;
            }
        }
        return textureIndexMap;
    }
}

注意:

  • 顶点索引的范围在[1,map.width]和[1,map.height],而格子在[0,map.width]和[0,map.height]。

  • 噪声图索引区间长度和顶点一致是n-1,但噪声图索引范围是[0,map.weight/height - 2],顶点是[1,map.weight/height - 1],所以从根据顶点索引从噪声图中取数据应该-1,即noiseMap[x - 1,z - 1]。

完善边界

将获取格子的逻辑都修改成使用上节优化后的GetCell方法。

    /// <summary>
    /// 获取左下角格子
    /// </summary>
    public MapCell GetLeftBottomMapCell(Vector2Int vertexIndex)
    {
        return GetCell(vertexIndex);
       // return cellDic[vertexIndex];
    }

    /// <summary>
    /// 获取右下角格子
    /// </summary>
    public MapCell GetRightBottomMapCell(Vector2Int vertexIndex)
    {
        return GetCell(vertexIndex.x + 1, vertexIndex.y);
        //return cellDic[new Vector2Int(vertexIndex.x + 1,vertexIndex.y)];
    }
    /// <summary>
    /// 获取左上角格子
    /// </summary>
    public MapCell GetLeftTopMapCell(Vector2Int vertexIndex)
    {
        //return cellDic[new Vector2Int(vertexIndex.x, vertexIndex.y + 1)];
        return GetCell(vertexIndex.x, vertexIndex.y + 1);
    }    
    /// <summary>
    /// 获取右上角格子
    /// </summary>
    public MapCell GetRightTopMapCell(Vector2Int vertexIndex)
    {
        //return cellDic[new Vector2Int(vertexIndex.x + 1, vertexIndex.y + 1)];
        return GetCell(vertexIndex.x + 1, vertexIndex.y + 1);
    }

修改顶点周围的贴图索引

    private void SetVertexType(Vector2Int vertexIndex, MapVertexType mapVertexType)
    {
        MapVertex vertex = GetVertex(vertexIndex);
        if (vertex.VertexType != mapVertexType)
        {
            vertex.VertexType = mapVertexType;
            //只有沼泽需要计算
            if (vertex.VertexType == MapVertexType.Marsh)
            {
                // 计算附近的贴图权重
                MapCell tempCell = GetLeftBottomMapCell(vertexIndex);
                if (tempCell != null) tempCell.TextureIndex += 1;
                tempCell = GetRightBottomMapCell(vertexIndex);
                if (tempCell != null) tempCell.TextureIndex += 2;
                tempCell = GetLeftTopMapCell(vertexIndex);
                if (tempCell != null) tempCell.TextureIndex += 4;
                tempCell = GetRightTopMapCell(vertexIndex);
                if (tempCell != null) tempCell.TextureIndex += 8;
            }
        }
        
    }

只有沼泽存在地形叠加,森林中的每个树独立不需要叠加,四个角的贴图设置成1,2,4,8的原因见地形拼接算法理论,本质是1,2,4,8可以组合生成1-15,覆盖了3*3地形叠加的所有可能情况。

输出每个格子贴图索引


        //确认顶点的类型、计算顶点周围的贴图索引数字
        int[,] celltexutreIndexMap = grid.CalculateCellTextureIndex(noiseMap, limit);

包含每个格子贴图的索引,对应着沼泽贴图不同的叠加形态。

alt