예제 #1
0
    public static Mesh GenerateTerrainMesh(float[,] heightMap, float heightScale,
                                           AnimationCurve heightCurve, int LOD)
    {
        int width  = heightMap.GetLength(0);
        int height = heightMap.GetLength(1);

        // The x and y position for the top left vertex on the mesh. In 3D, the represent the x and
        // z values. This is used so we can make sure the center vertex of the heightMap will be
        // at the center of the 3D world.
        float topLeftX = (width - 1) / -2f;
        float topLeftY = (height - 1) / 2f;

        // Based on the LOD, the increment in which vertices are chosen.
        int vertexSkip = 1;

        if (LOD > 0)
        {
            vertexSkip = LOD * 2;
        }

        int verticesPerLine = (width - 1) / vertexSkip + 1;

        // Log some info about vertex decrease
        // int totalVertices = verticesPerLine * verticesPerLine;
        // float vertexDecrease = (1f / ((width * height) / totalVertices)) * 100;
        // Debug.Log("Vertices per line: " + verticesPerLine + "; Total: " + totalVertices +
        //     "; Vertex Decrease: " + vertexDecrease + "%");

        // We need a TerrainData variable to store vertices and triangles for our terrain mesh.
        TerrainData terrainData = new TerrainData(verticesPerLine, verticesPerLine);

        // Loop through heights.
        int vertexIndex = 0;

        for (int y = 0; y < height; y += vertexSkip)
        {
            for (int x = 0; x < width; x += vertexSkip)
            {
                // Push a vertex to the end of the array, with the height pulled from the heightmap.
                terrainData.vertices[vertexIndex] = new Vector3(topLeftX + x,
                                                                heightCurve.Evaluate(heightMap[x, y]) * heightScale, topLeftY - y);

                // Push a uv mapping to the end of the array.
                terrainData.uvData[vertexIndex] = new Vector2(x / (float)width, y / (float)height);

                // Squares originate from the top left corners, so we ignore the vertices lining the
                // right side and bottom of the vertex map.
                if (x < width - 1 && y < height - 1)
                {
                    // Add the bottom left triangle of the square to the mesh.
                    terrainData.AddTriangle(vertexIndex, vertexIndex + verticesPerLine + 1,
                                            vertexIndex + verticesPerLine);
                    // Add the top right triangle of the square to the mesh.
                    terrainData.AddTriangle(vertexIndex + verticesPerLine + 1, vertexIndex, vertexIndex + 1);
                }

                vertexIndex++;
            }
        }

        // Instead of directly creating and returning a mesh, we only return the mesh data. The
        // reason for this is because Unity does not allow for creating meshes within a thread.
        // Therefore, we must calculate the mesh data on the thread and create the mesh itself
        // outside of it.
        return(terrainData.ConstructMesh()); // this currently DOES return the mesh.
    }