public static VoxelMeshData CreateMeshData(float[] heightMap, int width, int height, int chunkX, int chunkY,
                                                   int chunkWidth, int chunkHeight, TerrainTable terrainTable, bool edges = true, float edgeThickness = 1f)
        {
            var terrainMap = terrainTable.GetTerrainMap(heightMap);

            var xOffset = chunkX * chunkWidth;
            var yOffset = chunkY * chunkHeight;

            var meshData = new VoxelMeshData(width, height, new Vector2Int(xOffset, yOffset));

            for (var y = 0; y < chunkHeight && y + yOffset < height; y++)
            {
                for (var x = 0; x < chunkWidth && x + xOffset < width; x++)
                {
                    var mapX = x + xOffset;
                    var mapY = y + yOffset;

                    var terrain = terrainMap[mapY * width + mapX];

                    var front = mapY + 1 < height ? terrainMap[(mapY + 1) * width + mapX] : null;
                    var back  = mapY - 1 >= 0 ? terrainMap[(mapY - 1) * width + mapX] : null;
                    var right = mapX + 1 < width ? terrainMap[mapY * width + mapX + 1] : null;
                    var left  = mapX - 1 >= 0 ? terrainMap[mapY * width + mapX - 1] : null;

                    meshData.AddUpQuad(x, y, terrain.MinElevation);

                    if (left != null && left.MinElevation < terrain.MinElevation)
                    {
                        meshData.AddLeftQuad(x, y, terrain.MinElevation, terrain.MinElevation - left.MinElevation);
                    }
                    else if (edges && mapX - 1 < 0)
                    {
                        meshData.AddLeftQuad(x, y, terrain.MinElevation, terrain.MinElevation + edgeThickness);
                    }

                    if (front != null && front.MinElevation < terrain.MinElevation)
                    {
                        meshData.AddFrontQuad(x, y, terrain.MinElevation, terrain.MinElevation - front.MinElevation);
                    }
                    else if (edges && mapY + 1 >= height)
                    {
                        meshData.AddFrontQuad(x, y, terrain.MinElevation, terrain.MinElevation + edgeThickness);
                    }

                    if (right != null && right.MinElevation < terrain.MinElevation)
                    {
                        meshData.AddRightQuad(x, y, terrain.MinElevation, terrain.MinElevation - right.MinElevation);
                    }
                    else if (edges && mapX + 1 >= width)
                    {
                        meshData.AddRightQuad(x, y, terrain.MinElevation, terrain.MinElevation + edgeThickness);
                    }

                    if (back != null && back.MinElevation < terrain.MinElevation)
                    {
                        meshData.AddBackQuad(x, y, terrain.MinElevation, terrain.MinElevation - back.MinElevation);
                    }
                    else if (edges && mapY - 1 < 0)
                    {
                        meshData.AddBackQuad(x, y, terrain.MinElevation, terrain.MinElevation + edgeThickness);
                    }
                }
            }

            return(meshData);
        }
        public async void DisplayMap(WorldMapData worldMapData)
        {
            if (!enabled)
            {
                return;
            }

            var heightMapLayer = worldMapData.GetLayer <HeightMapLayerData>();
            var regionMapLayer = worldMapData.GetLayer <RegionMapLayerData>();

            var width  = worldMapData.width;
            var height = worldMapData.height;

            var heightMap = heightMapLayer.heightMap;
            var regions   = regionMapLayer.regions;
            var regionMap = regionMapLayer.regionMap;

            var terrainMap = _terrainTable.GetTerrainMap(heightMap);
            var colorMap   = TerrainTable.GetColorMap(heightMap, terrainMap, gradiate);

            if (fillRegions && regionColors.Length > 0)
            {
                for (int i = 0; i < colorMap.Length; i++)
                {
                    var regionIndex = regionMap[i];
                    if (regionIndex <= 0)
                    {
                        continue;
                    }

                    var regionColor = regionColors[(regionIndex - 1) % regionColors.Length];
                    var alpha       = Mathf.Clamp01(regionColor.a * regionFillAlpha);
                    colorMap[i] = regionColor * alpha + (1 - alpha) * colorMap[i];
                }
            }

            if (drawBorders && regionColors.Length > 0)
            {
                foreach (var region in regions)
                {
                    foreach (var pt in region.borderPoints)
                    {
                        int index       = pt.y * width + pt.x;
                        var regionIndex = regionMap[index];
                        var regionColor = regionColors[regionIndex - 1];
                        var alpha       = regionColor.a * borderAlpha;
                        colorMap[index]   = regionColor * alpha + (1 - alpha) * colorMap[index];
                        colorMap[index].a = 1;
                    }
                }
            }

            if (drawSpawnPoints)
            {
                foreach (var region in regions)
                {
                    var pt    = region.spawnPt;
                    int index = pt.y * width + pt.x;
                    colorMap[index] = Color.black;
                }
            }

            if (drawPoissonPoints)
            {
                var poissonLayer = worldMapData.GetLayer <PoissonMapLayerData>();
                if (poissonLayer != null)
                {
                    foreach (var pt in poissonLayer.points)
                    {
                        int index = pt.y * width + pt.x;
                        colorMap[index] = Color.black;
                    }
                }
            }

            var texture = TextureUtility.GetColorMap(colorMap, width, height);

            texture.filterMode = filterMode;
            SetTexture(texture);

            if (scaleTexture)
            {
                await TextureScale.BilinearAsync(texture, Mathf.Min(2048, Mathf.RoundToInt(width *textureScale)), Mathf.Min(2048, Mathf.RoundToInt(height *textureScale)));
            }
        }