Search code examples
c#unity-game-enginemeshprocedural-generation

Why does my procedural grid mesh not triangulate properly for grids bigger than 256x256?


I've been making procedural terrain height maps with the diamond square algorithm and the mesh with the triangulation method below:

        public Map GenerateMap()
        {
            Mesh mapMesh = new();

            vertices = new Vector3[(Resolution + 1) * (Resolution + 1)];
            Vector2[] uv1 = new Vector2[vertices.Length];
            Vector2[] uv2 = new Vector2[vertices.Length];
            Vector2[] uv3 = new Vector2[vertices.Length];
            DiamondSquare diamondSquare = new(Resolution, Roughness, Seed, HeightLevels);
            float[,] heightFloatMap = diamondSquare.DoDiamondSquare();
            tex = new Texture2D(Resolution, Resolution);

            for (int y = 0, i = 0; y <= Resolution; y++)
            {
                for (int x = 0; x <= Resolution; x++, i++)
                {
                    //float height = heightMap.GetPixel(x,y).r;
                    float height = heightFloatMap[x, y];
                    vertices[i] = new Vector3(x * CellSize.x, height * CellSize.y, y * CellSize.z);
                    tex.SetPixel(x, y, new Color(height, height, height, 1));
                    if (height == 0)
                        uv1[i] = new Vector2(vertices[i].x, vertices[i].z);
                    else if (height < 0.4)
                        uv2[i] = new Vector2(vertices[i].x, vertices[i].z);
                    else if (height < 0.4)
                        uv3[i] = new Vector2(vertices[i].x, vertices[i].z);
                }
            }
            mapMesh.vertices = vertices;
            mapMesh.uv = uv1;
            mapMesh.uv2 = uv2;

            int[] triangles = new int[Resolution * Resolution * 6];
            Cell[,] cellMap = new Cell[Resolution / 4, Resolution / 4];
            for (int ti = 0, vi = 0, y = 0; y < Resolution; y++, vi++)
            {
                for (int x = 0; x < Resolution; x++, ti += 6, vi++)
                {
                    triangles[ti] = vi;
                    triangles[ti + 3] = triangles[ti + 2] = vi + 1;
                    triangles[ti + 4] = triangles[ti + 1] = vi + Resolution + 1;
                    triangles[ti + 5] = vi + Resolution + 2;

                    Vector3[] cellVerts = new Vector3[]
                        {
                            vertices[vi], vertices[vi + 1], vertices[vi + Resolution + 1], vertices[vi + Resolution + 2]
                        };
                    Cell cell = new(new Vector2Int(x, y), cellVerts, CalculateCellGeometry(cellVerts));
                    cellMap[x / 4, y / 4] = cell;
                }
            }
            mapMesh.triangles = triangles;

            mapMesh.RecalculateNormals();
            mapMesh.RecalculateTangents();
            mapMesh.RecalculateBounds();

            Map map = new(mapMesh, cellMap, heightFloatMap, vertices);
            return map;
        }
    }

This works fine with grid sizes 16x16, 32x32... 256x256 but breaks when I try it on 512x512 or above

256x256

Mesh is perfect

512x512

It successfully triangulates up until the rows starting y=128

On the underside of the terrain there are these bars

I've mapped out the vertices generated from 512x512 and above resolutions and they are all good so I'm 99% sure its down to the triangulation.

I'm new to procedural meshes and am stumped by this issue, any help would be greatly appreciated.


Solution

  • Turns out it wasn't triangulation, the vertex limit was being reached as my mesh was set to use a 16-bit index buffer.

    I added this line

    mapMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
    

    and the issue is fixed. An annoying oversight on my part but that's part of the learning process!