public static Mesh GenerateTerrainMesh(int terrainWidth, int resolution, TerrainPreset terrainValues) { // Generate the heightmap float[] heightMap = GenerateHeightMap(terrainWidth, resolution, terrainValues); // Create vertices, UVs, and triangles Vector2[] terrainVertices = CreateTerrainVertices(heightMap, resolution); Vector2[] terrainUV = GenerateTerrainUV(heightMap, terrainWidth); Vector2[] terrainUV2 = GenerateTerrainUV2(heightMap, resolution, terrainValues.terrainType); int[] terrainTriangles = Triangulate(terrainVertices.Length); // Convert our Vector2s to Vector3s Vector3[] meshVertices = new Vector3[terrainVertices.Length]; for (int i = 0; i < terrainVertices.Length; i++) { meshVertices[i] = new Vector3(terrainVertices[i].x, terrainVertices[i].y, 0); } Mesh mesh = new Mesh(); mesh.vertices = meshVertices; mesh.uv = terrainUV; mesh.uv2 = terrainUV2; mesh.triangles = terrainTriangles; mesh.RecalculateNormals(); mesh.RecalculateBounds(); return(mesh); }
static void RollingHills(float[] heightMap, TerrainPreset terrainValues) { // Find the midpoint of the array for this step float midHeight = (heightMap[0] + heightMap[heightMap.Length - 1]) / 2; // Distance each hill/valley should be from each other int distance = (int)Mathf.Ceil((heightMap.Length - 1) / (terrainValues.featureCount + 1)); int currentLocation = 0; // Array to store the points in the heightMap where the hills are int[] hillLocationsIndex = new int[terrainValues.featureCount + 2]; hillLocationsIndex[0] = 0; hillLocationsIndex[hillLocationsIndex.Length - 1] = heightMap.Length - 1; // For each hill... for (int i = 0; i < terrainValues.featureCount; i++) { // ...set their locations... currentLocation += distance; hillLocationsIndex[i + 1] = currentLocation; // ...and generate a new displacement between the roughness factor heightMap[currentLocation] = midHeight + UnityEngine.Random.Range(-terrainValues.roughness, terrainValues.roughness); } int nextHillLocation = 1; // Iterate through the heightMap.. for (int i = 1; i < heightMap.Length - 1; i++) { if (i >= hillLocationsIndex[nextHillLocation]) { nextHillLocation++; } // and determine the Y value for each point between the hills using cosine interpolation heightMap[i] = CosineInterpolate(heightMap[hillLocationsIndex[nextHillLocation - 1]], heightMap[hillLocationsIndex[nextHillLocation]], (i - (float)hillLocationsIndex[nextHillLocation - 1]) / ((float)hillLocationsIndex[nextHillLocation] - hillLocationsIndex[nextHillLocation - 1])); } }
static float[] GenerateHeightMap(int terrainWidth, int resolution, TerrainPreset terrainValues) { // Create a heightmap array and set the start and endpoints float[] heightMap = new float[terrainWidth * resolution + 1]; heightMap[0] = UnityEngine.Random.Range(terrainValues.absoluteMinHeight, terrainValues.absoluteMaxHeight); heightMap[heightMap.Length - 1] = UnityEngine.Random.Range(terrainValues.absoluteMinHeight, terrainValues.absoluteMaxHeight); // Call the desired method to generate the heightmap TerrainMethod method = terrainMethods[(int)terrainValues.terrainType]; method(heightMap, terrainValues); // Adjust hightmap to be centered float heightMapHighest = terrainValues.absoluteMinHeight; float heightMapLowest = terrainValues.absoluteMaxHeight; for (int i = 0; i < heightMap.Length; i++) { if (heightMap[i] > heightMapHighest) { heightMapHighest = heightMap[i]; } if (heightMap[i] < heightMapLowest) { heightMapLowest = heightMap[i]; } } float heightMapMedian = (heightMapLowest + heightMapHighest) / 2; float middleHeight = (terrainValues.absoluteMinHeight + terrainValues.absoluteMaxHeight) / 2; float adjustment = middleHeight - heightMapMedian; for (int i = 0; i < heightMap.Length; i++) { heightMap[i] = heightMap[i] + adjustment; } return(heightMap); }
static void RockyMountains(float[] heightMap, TerrainPreset terrainValues) { RockyMountainsSubFunction(0, heightMap.Length - 1, terrainValues.roughness, terrainValues.smoothingFactor, heightMap); }