public MapMesh generateTerrain(Map map, List <List <Vector2> > riverPoints, TriangleNet.Mesh mapTriangulation) { MapMesh terrain = new MapMesh(); List <Vector3> landVertices = new List <Vector3>(); List <Vector3> oceanVertices = new List <Vector3>(); List <Vector3> innerWaterVertices = new List <Vector3>(); Dictionary <Vector2, float> mapVerticesHeights = new Dictionary <Vector2, float>(); foreach (Triangle triangle in mapTriangulation.Triangles) { List <MapVertex> mapVertices = triangle.vertices .Select(vertex => vertex is MapVertex ? (MapVertex)vertex : convertToMapVertex(vertex)) .Reverse() .ToList(); List <Vector3> underWaterShifts = new List <Vector3>(new Vector3[3]); List <bool> needsShoreAdjustments = new List <bool>(new bool[3]); if (mapVertices.Any(mapVertice => mapVertice.hex == null)) { for (int i = 0; i < mapVertices.Count; i++) { if (mapVertices[i].hex != null) { needsShoreAdjustments[i] = true; } } } MapVertex shoreMapVertex = mapVertices.FirstOrDefault(mapVertex => mapVertex.hex != null && (mapVertex.hex.biome == null || mapVertex.hex.biome.name != "Fresh lake")); if (shoreMapVertex != null) { Vector2 shoreCenter = HexMathHelper.hexToWorldCoords(new Vector2(shoreMapVertex.hex.x, shoreMapVertex.hex.y), this.hexSize); //if shore triangle push it underwater to create shore slope for (int i = 0; i < mapVertices.Count; i++) { if (mapVertices[i].hex == null) { underWaterShifts[i] = (new Vector2((float)mapVertices[i].x, (float)mapVertices[i].y) - shoreCenter).normalized * 0.3f; underWaterShifts[i] += new Vector3(0, 0, 0.03f); } } } List <Vector3> triangleVertices = new List <Vector3>(); for (int i = 0; i < mapVertices.Count; i++) { float height = TerrainHelper.getHeight(heightSeed, mapVertices[i], this.hexSize, elevatedHeightmap, mountainHeightmap); Vector3 newVertex = mapVertices[i].toVector3() + underWaterShifts[i] + new Vector3(0, 0, height); if (!mapVerticesHeights.ContainsKey(newVertex) && needsShoreAdjustments[i]) { newVertex.z = Random.Range(0.08f, 0.13f); mapVerticesHeights[newVertex] = newVertex.z; } if (mapVertices[i].isRiver && (mapVertices[i].hex == null || !mapVertices[i].hex.hasTag(RiverHelper.FRESH_LAKE_TAG))) { newVertex += TerrainHelper.getRiverHeightAdjustment(newVertex); } triangleVertices.Add(newVertex); } if (mapVertices.All(mapVertex => mapVertex.hex == null)) { oceanVertices.AddRange(triangleVertices); } else if (mapVertices.All(mapVertex => mapVertex.isRiver)) { innerWaterVertices.AddRange(triangleVertices); } else if (mapVertices.All(mapVertex => mapVertex.hex != null && mapVertex.hex.hasTag(RiverHelper.FRESH_LAKE_TAG))) { innerWaterVertices.AddRange(triangleVertices); } else { landVertices.AddRange(triangleVertices); } } //smooth shore for (int i = 0; i < landVertices.Count; i++) { Vector3 vertex = landVertices[i]; if (mapVerticesHeights.ContainsKey(vertex)) { vertex.z = mapVerticesHeights[landVertices[i]]; landVertices[i] = vertex; } } terrain.landMesh = this.createMesh("Land", landVertices); terrain.oceanMesh = this.createMesh("Ocean", oceanVertices); terrain.innerWaterMesh = this.createMesh("Lakes and Rivers", innerWaterVertices); return(terrain); }