public void CombineTerrainTileMeshes(List <TerrainTileMesh> tiles) { vertices.Clear(); normals.Clear(); uvs.Clear(); triangles.Clear(); int triangleOffset = 0; for (int i = 0; i < tiles.Count; i++) { TerrainTileMesh tile = tiles[i]; int tileVertexCount = tile.vertices.Count; int tileTriangleCount = tile.triangles.Count; for (int j = 0; j < tileVertexCount; j++) { vertices.Add(tile.vertices[j]); normals.Add(tile.normals[j]); uvs.Add(tile.uvs[j]); } for (int t = 0; t < tileTriangleCount; t++) { triangles.Add(tile.triangles[t] + triangleOffset); } triangleOffset += tileVertexCount; } }
// Start is called before the first frame update void Start() { // Initialise variables tileSize = size / numTiles; prevPlayerTilePos = Vector2Int.one * int.MaxValue; map = new Map(mapSeed, size, numTiles, tileResolution, heightmapProvider); // Create mesh renderers and filters int numLODs = lodDistances.Length; lodGameObjects = new List <GameObject> [numLODs]; tileMeshes = new TerrainTileMesh[numTiles, numTiles]; tileLODs = new int[numTiles, numTiles]; tileEdgeTransitionFlags = new int[numTiles, numTiles]; lodMeshes = new List <CombinedTerrainTileMesh> [numLODs]; meshRenderers = new List <MeshRenderer> [numLODs]; meshFilters = new List <MeshFilter> [numLODs]; // Create LOD meshes for (int i = 0; i < numLODs; i++) { lodGameObjects[i] = new List <GameObject>(8); lodMeshes[i] = new List <CombinedTerrainTileMesh>(8); meshRenderers[i] = new List <MeshRenderer>(8); meshFilters[i] = new List <MeshFilter>(8); for (int m = 0; m < 8; m++) { lodGameObjects[i].Add(new GameObject()); lodGameObjects[i][m].transform.parent = transform; lodGameObjects[i][m].name = "LOD " + i + " mesh " + m; lodGameObjects[i][m].layer = LayerMask.NameToLayer(terrainLayer); CombinedMeshType meshType = CombinedMeshType.Corner; if (i == 0) { meshType = CombinedMeshType.Center; } else if (m > 3) { meshType = CombinedMeshType.Edge; } int prevLODDistance = (i == 0) ? 0 : lodDistances[i - 1]; lodMeshes[i].Add(new CombinedTerrainTileMesh(meshType, tileResolution / MathUtilities.Pow(2, i), lodDistances[i], Mathf.Max(0, lodDistances[i] - prevLODDistance))); meshRenderers[i].Add(lodGameObjects[i][m].AddComponent(typeof(MeshRenderer)) as MeshRenderer); meshRenderers[i][m].sharedMaterial = terrainMaterial; meshFilters[i].Add(lodGameObjects[i][m].AddComponent(typeof(MeshFilter)) as MeshFilter); meshFilters[i][m].mesh = lodMeshes[i][m].mesh; } } // Create tile objects for (int x = 0; x < numTiles; x++) { for (int z = 0; z < numTiles; z++) { tileLODs[x, z] = -1; tileMeshes[x, z] = new TerrainTileMesh(tileResolution); } } // Initialise heightmap provider heightmapProvider.Init(mapSeed, size); // Start mesh updater thread ThreadStart MeshUpdaterThreadStart = MeshUpdateThread; meshUpdaterThread = new Thread(MeshUpdaterThreadStart); meshUpdateThreadStatus = (int)MeshUpdateThreadStatus.Idle; meshUpdaterThread.Start(); }
public static void GenerateTile(TerrainTileMesh tileMesh, Vector2Int tilePosition, float tileSize, int lod0Resolution, int lod, float[,] heightMap, int edgeTransitionFlags) { tileMesh.Clear(); if (lod == -1) { return; } int heightmapStep = MathUtilities.Pow(2, lod); int planeResolution = lod0Resolution / heightmapStep; float positionStep = tileSize / planeResolution; float uvStep = 1.0f / planeResolution; Vector3 tileOrigin = new Vector3(tilePosition.x * tileSize, 0.0f, tilePosition.y * tileSize); Vector3 vertex = new Vector3(); Vector3 normal = new Vector3(0.0f, 1.0f, 0.0f); Vector2 uv = Vector3.zero; float leftHeight, rightHeight, topHeight, bottomHeight; // Create vertices for (int z = 0, heightmapZ = 1; z <= planeResolution; z++, heightmapZ += heightmapStep) { for (int x = 0, heightmapX = 1; x <= planeResolution; x++, heightmapX += heightmapStep) { vertex = tileOrigin; vertex.x += x * positionStep; vertex.y += heightMap[heightmapX, heightmapZ]; vertex.z += z * positionStep; /*leftHeight = heightMap[heightmapX - heightmapStep, heightmapZ]; * rightHeight = heightMap[heightmapX + heightmapStep, heightmapZ]; * topHeight = heightMap[heightmapX, heightmapZ + heightmapStep]; * bottomHeight = heightMap[heightmapX, heightmapZ - heightmapStep];*/ leftHeight = heightMap[heightmapX - 1, heightmapZ]; rightHeight = heightMap[heightmapX + 1, heightmapZ]; topHeight = heightMap[heightmapX, heightmapZ + 1]; bottomHeight = heightMap[heightmapX, heightmapZ - 1]; Vector3 tangent = new Vector3(2.0f, rightHeight - leftHeight, 0.0f); Vector3 bitangent = new Vector3(0.0f, bottomHeight - topHeight, 2.0f); normal = Vector3.Cross(tangent, bitangent).normalized; //normal = (new Vector3(2.0f * (rightHeight - leftHeight), 2.0f * (topHeight - bottomHeight), -4.0f).normalized); uv.x = x * uvStep; uv.y = z * uvStep; tileMesh.vertices.Add(vertex); tileMesh.normals.Add(normal); tileMesh.uvs.Add(uv); } } // Update seams if ((edgeTransitionFlags & (int)TileEdgeTransitionFlags.Top) == (int)TileEdgeTransitionFlags.Top) { for (int x = 1, vert = ((planeResolution + 1) * planeResolution) + 1; x < planeResolution; x += 2, vert += 2) { tileMesh.vertices[vert] = new Vector3(tileMesh.vertices[vert].x, Mathf.Lerp(tileMesh.vertices[vert - 1].y, tileMesh.vertices[vert + 1].y, 0.5f), tileMesh.vertices[vert].z); } } if ((edgeTransitionFlags & (int)TileEdgeTransitionFlags.Bottom) == (int)TileEdgeTransitionFlags.Bottom) { for (int x = 1, vert = 1; x < planeResolution; x += 2, vert += 2) { tileMesh.vertices[vert] = new Vector3(tileMesh.vertices[vert].x, Mathf.Lerp(tileMesh.vertices[vert - 1].y, tileMesh.vertices[vert + 1].y, 0.5f), tileMesh.vertices[vert].z); } } if ((edgeTransitionFlags & (int)TileEdgeTransitionFlags.Left) == (int)TileEdgeTransitionFlags.Left) { for (int z = 1, vert = planeResolution + 1; z < planeResolution; z += 2, vert += (planeResolution + 1) * 2) { tileMesh.vertices[vert] = new Vector3(tileMesh.vertices[vert].x, Mathf.Lerp(tileMesh.vertices[vert - (planeResolution + 1)].y, tileMesh.vertices[vert + (planeResolution + 1)].y, 0.5f), tileMesh.vertices[vert].z); } } if ((edgeTransitionFlags & (int)TileEdgeTransitionFlags.Right) == (int)TileEdgeTransitionFlags.Right) { for (int z = 1, vert = (planeResolution * 2) + 1; z < planeResolution; z += 2, vert += (planeResolution + 1) * 2) { tileMesh.vertices[vert] = new Vector3(tileMesh.vertices[vert].x, Mathf.Lerp(tileMesh.vertices[vert - (planeResolution + 1)].y, tileMesh.vertices[vert + (planeResolution + 1)].y, 0.5f), tileMesh.vertices[vert].z); } } // Calculate indices for (int ti = 0, vi = 0, y = 0; y < planeResolution; y++, vi++) { for (int x = 0; x < planeResolution; x++, ti += 6, vi++) { tileMesh.triangles.Add(vi); tileMesh.triangles.Add(vi + planeResolution + 1); tileMesh.triangles.Add(vi + 1); tileMesh.triangles.Add(vi + 1); tileMesh.triangles.Add(vi + planeResolution + 1); tileMesh.triangles.Add(vi + planeResolution + 2); } } }