I'm trying to implement a terrain based on a noise map. The code is from internet so credits to Sebastian Lague. Everything went well, the map is generated fine but i wanted to make it bigger. Considering the fact that Unity doesn't allow more than ~65000 meshes/vertices, i generated the noise map, splitted into 4 mapChunks. The issue is that , eventhough i splitted into 4 , when i try to allign all the chunks in the scene view, a mesh is missing.
I've used the same code to generate the 2DNoiseMaps and they allign perfectly, so it's because the meshes. Is there a way to combine the mapChunk meshes somehow? Noise.cs:
using UnityEngine;
using System.Collections;
public static class Noise
{
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset)
{
float[,] noiseMap = new float[mapWidth, mapHeight];
System.Random prng = new System.Random(seed);
Vector2[] octaveOffsets = new Vector2[octaves];
for (int i = 0; i < octaves; i++)
{
float offsetX = prng.Next(-100000, 100000) + offset.x;
float offsetY = prng.Next(-100000, 100000) + offset.y;
octaveOffsets[i] = new Vector2(offsetX, offsetY);
}
if (scale <= 0)
{
scale = 0.0001f;
}
float maxNoiseHeight = float.MinValue;
float minNoiseHeight = float.MaxValue;
float halfWidth = mapWidth / 2f;
float halfHeight = mapHeight / 2f;
for (int y = 0; y < mapHeight; y++)
{
for (int x = 0; x < mapWidth; x++)
{
float amplitude = 1;
float frequency = 1;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++)
{
float sampleX = (x - halfWidth) / scale * frequency + octaveOffsets[i].x;
float sampleY = (y - halfHeight) / scale * frequency + octaveOffsets[i].y;
float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistance;
frequency *= lacunarity;
}
if (noiseHeight > maxNoiseHeight)
{
maxNoiseHeight = noiseHeight;
}
else if (noiseHeight < minNoiseHeight)
{
minNoiseHeight = noiseHeight;
}
noiseMap[x, y] = noiseHeight;
}
}
for (int y = 0; y < mapHeight; y++)
{
for (int x = 0; x < mapWidth; x++)
{
noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, y]);
}
}
return noiseMap;
}
}
MeshGenerator & MeshData classes
public static class MeshGenerator
{
public static MeshData GenerateTerrainMesh(float[,] heightMap, float heightMultiplier, AnimationCurve _heightCurve, int levelOfDetail)
{
AnimationCurve heightCurve = new AnimationCurve(_heightCurve.keys);
int width = heightMap.GetLength(0);
int height = heightMap.GetLength(1);
float topLeftX = (width - 1) / -2f;
float topLeftZ = (height - 1) / 2f;
int meshSimplificationIncrement = (levelOfDetail == 0) ? 1 : levelOfDetail * 2;
int verticesPerLine = (width - 1) / meshSimplificationIncrement + 1;
MeshData meshData = new MeshData(verticesPerLine, verticesPerLine);
int vertexIndex = 0;
for (int y = 0; y < height; y += meshSimplificationIncrement)
{
for (int x = 0; x < width; x += meshSimplificationIncrement)
{
meshData.vertices[vertexIndex] = new Vector3(topLeftX + x, heightCurve.Evaluate(heightMap[x, y]) * heightMultiplier, topLeftZ - y);
meshData.uvs[vertexIndex] = new Vector2(x / (float)width, y / (float)height);
if (x < width - 1 && y < height - 1)
{
meshData.AddTriangle(vertexIndex, vertexIndex + verticesPerLine + 1, vertexIndex + verticesPerLine);
meshData.AddTriangle(vertexIndex + verticesPerLine + 1, vertexIndex, vertexIndex + 1);
}
vertexIndex++;
}
}
return meshData;
}
}
public class MeshData
{
public Vector3[] vertices;
public int[] triangles;
public Vector2[] uvs;
int triangleIndex;
public MeshData(int meshWidth, int meshHeight)
{
vertices = new Vector3[meshWidth * meshHeight];
uvs = new Vector2[meshWidth * meshHeight];
triangles = new int[(meshWidth - 1) * (meshHeight - 1) * 6];
}
public void AddTriangle(int a, int b, int c)
{
triangles[triangleIndex] = a;
triangles[triangleIndex + 1] = b;
triangles[triangleIndex + 2] = c;
triangleIndex += 3;
}
public Mesh CreateMesh()
{
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
return mesh;
}
}
Also the GenerateMap method which will create all the stuff:
public void GenerateMap()
{
MapDisplay display = FindObjectOfType<MapDisplay>();
meshHeightCurve = BrokenConstantCurve.GenerateCurveBasedOnBiomes(meshHeightCurve, regions);
meshHeightCurve = BrokenConstantCurve.CreateBrokenConstantCurve(meshHeightCurve);
float[,] noiseMap = Noise.GenerateNoiseMap(mapChunkSize * 2, mapChunkSize * 2, seed, noiseScale, octaves, persistance, lacunarity, offset);
float[,] upperLeft = new float[mapChunkSize, mapChunkSize];
float[,] upperRight = new float[mapChunkSize, mapChunkSize];
float[,] lowerLeft = new float[mapChunkSize, mapChunkSize];
float[,] lowerRight = new float[mapChunkSize, mapChunkSize];
List<float[,]> noiseMapChunks = new List<float[,]>() { upperLeft, upperRight, lowerLeft, lowerRight };
for (var x = 0; x < mapChunkSize; x++)
{
for (var y = 0; y < mapChunkSize; y++)
upperLeft[x, y] = noiseMap[x, y];
}
for (var x = mapChunkSize; x < mapChunkSize * 2; x++)
{
for (var y = 0; y < mapChunkSize; y++)
try
{
upperRight[x - mapChunkSize, y] = noiseMap[x, y];
}
catch (Exception ex)
{
}
}
for (var x = 0; x < mapChunkSize; x++)
{
for (var y = mapChunkSize; y < mapChunkSize * 2; y++)
lowerLeft[x, y - mapChunkSize] = noiseMap[x, y];
}
for (var x = mapChunkSize; x < mapChunkSize * 2; x++)
{
for (var y = mapChunkSize; y < mapChunkSize * 2; y++)
lowerRight[x- mapChunkSize, y - mapChunkSize] = noiseMap[x, y];
}
display.ClearMeshes();
for (var chunkIndex = 0; chunkIndex < noiseMapChunks.Count; chunkIndex++)
{
Color[] colourMap = new Color[mapChunkSize * mapChunkSize];
for (int y = 0; y < mapChunkSize; y++)
{
for (int x = 0; x < mapChunkSize; x++)
{
//if (useFalloff)
//{
// chunk[x, y] = Mathf.Clamp01(chunk[x, y] - falloffMap[x, y]);
//}
float currentHeight = noiseMapChunks[chunkIndex][x, y];
for (int j = 0; j < regions.Length; j++)
{
if (currentHeight <= regions[j].curveX)
{
colourMap[y * mapChunkSize + x] = regions[j].colour;
break;
}
}
}
}
display.DrawMesh(MeshGenerator.GenerateTerrainMesh(noiseMapChunks[chunkIndex], meshHeightMultiplier, meshHeightCurve, levelOfDetail), TextureGenerator.TextureFromColourMap(colourMap, mapChunkSize, mapChunkSize), chunkIndex);
//display.DrawTexture(TextureGenerator.TextureFromHeightMap(noiseMapChunks[chunkIndex]), chunkIndex);
}
If you need other methods/classes, let me know. Thank you so much, hopefully someone can help after 5 days of investigation :)
