Генерация процедурного меня sh в Unity3D - PullRequest
0 голосов
/ 26 мая 2020

Я создаю программу, в которой я могу преобразовывать черно-белые изображения в ландшафт.

У меня есть рабочий код, но поскольку Unity имеет ограничение на количество вершин, которое может быть у меня sh Код не работает для больших изображений.

Итак, я попытался разделить изображение на меньшие изображения и создать себе sh для каждой части. это работает, но я получаю странный интервал между моими сетками, и я не уверен, почему.

Код:

public static class MeshGenerator
{
    private static Transform CreateGameObjectWithMesh(Mesh m)
    {
        var go = new GameObject();
        go.AddComponent<MeshFilter>().mesh = m;
        go.AddComponent<MeshRenderer>();
        m.RecalculateNormals();
        return go.transform;
    }
    public static void Generate(float[,] heightsData)
    {
        int width = heightsData.GetLength(0);
        int height = heightsData.GetLength(1);
        float topLeftX = (width - 1) / -2f;
        float topLeftZ = (height - 1) / 2f;

        // Just for testing, I am working with 256X256 texture and split it to 4 parts. (would be modified when working)
        for (int i = 0; i < 4; i++)
        {
            var startX = (i % 2) * 128;
            var startY = i < 2 ? 0 : 128;
            StartMeshCreationThread(mesh =>
                {
                    var t = CreateGameObjectWithMesh(mesh);
                    t.position = new Vector3(topLeftX + startX + 128f / 2f, 0, topLeftZ - startY - 128f / 2f);
                }, startX, startY, 128, 128, heightsData,
                new Vector2(topLeftX, topLeftZ), (x, y) => new Vector2(x / (float) width, y / (float) height));
        }
    }

    // Would create a new thread in the future.
    private static void StartMeshCreationThread(Action<Mesh> onFinishedCallback, int startX, int startY, int width,
        int height, float[,] heightsData, Vector2 orgTopLeft, Func<int, int, Vector2> getUVPosition)
    {
        var meshData = new MeshData (width, height);
        float topLeftX = (width - 1) / -2f;
        float topLeftZ = (height - 1) / 2f;
        int vertexIndex = 0;

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                var vertexPosition = new Vector3(topLeftX + x, heightsData[x + startX, y + startY] * 10f, topLeftZ - y);
                meshData.AddVertexData(vertexIndex, vertexPosition, getUVPosition(x + startX, y + startY));

                if (x < width - 1 && y < height - 1)
                {
                    meshData.AddTriangle (vertexIndex, vertexIndex + width + 1, vertexIndex + width);
                    meshData.AddTriangle (vertexIndex + width + 1, vertexIndex, vertexIndex + 1);
                }

                vertexIndex++;
            }
        }

        onFinishedCallback(meshData.CreateMesh());
    }

    private class MeshData
    {
        private readonly Vector3[] vertices;
        private readonly Vector2[] uvs;
        private readonly int[] triangles;
        private int triangleIndex;

        public MeshData(int width, int height)
        {
            vertices = new Vector3[width * height];
            uvs = new Vector2[width * height];
            triangles = new int[(width - 1) * (height - 1) * 6];
            triangleIndex = 0;
        }

        public void AddVertexData(int index, Vector3 vertexPosition, Vector2 uvPosition)
        {
            vertices[index] = vertexPosition;
            uvs[index] = uvPosition;
        }
        public void AddTriangle(int v1, int v2, int v3)
        {
            triangles[triangleIndex + 0] = v1;
            triangles[triangleIndex + 1] = v2;
            triangles[triangleIndex + 2] = v3;
            triangleIndex += 3;
        }

        public Mesh CreateMesh()
        {
            var mesh = new Mesh {vertices = vertices, triangles = triangles, uv = uvs};
            return mesh;
        }
    }
}

Результат (для 256X256) текстура: Result (for 256X256) texture

( основной источник )

...