public static Tuple <float[, ], float, float> GenerateFalloff(int size, MapGeneratorSettings settings) { float maxHeight = float.MinValue; float minHeight = float.MaxValue; var result = new float[size, size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float _x = i / (float)size * 2 - 1; float _y = j / (float)size * 2 - 1; float value = Mathf.Max(Mathf.Abs(_x), Mathf.Abs(_y)); result[i, j] = Evaluate(value, settings); if (result[i, j] > maxHeight) { maxHeight = result[i, j]; } if (result[i, j] < minHeight) { minHeight = result[i, j]; } } } return(new Tuple <float[, ], float, float>(result, minHeight, maxHeight)); }
static float Evaluate(float value, MapGeneratorSettings settings) { float a = settings.fallOffA; float b = settings.fallOffB; return(Mathf.Pow(value, a) / (Mathf.Pow(value, a) + Mathf.Pow(b - b * value, a))); }
public static float GetFalloff(int x, int y, int size, MapGeneratorSettings settings) { float _x = x / (float)size * 2 - 1; float _y = y / (float)size * 2 - 1; float value = Mathf.Max(Mathf.Abs(_x), Mathf.Abs(_y)); return(Evaluate(value, settings)); }
public static Tuple <float[, ], float, float> GenerateNoise(int size, MapGeneratorSettings settings, Vector2 sampleCenter) { float[,] noiseMap = new float[size, size]; System.Random prng = new System.Random(settings.seed == 0 ? DateTime.Now.Millisecond : settings.seed); Vector2[] octavesOffsets = new Vector2[settings.octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < settings.octaves; i++) { float offsetX = prng.Next(-100000, 100000) + settings.offset.x + sampleCenter.x; float offsetY = prng.Next(-100000, 100000) + settings.offset.y + sampleCenter.y; octavesOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= settings.persistance; } float maxNoiseHeight = float.MinValue; float minNoiseHeight = float.MaxValue; float halfSize = size / 2f; for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < settings.octaves; i++) { float sampleX = (x - halfSize + octavesOffsets[i].x) / settings.noiseScale * frequency; float sampleY = (y - halfSize + octavesOffsets[i].y) / settings.noiseScale * frequency; float perlinNoise = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinNoise * amplitude; amplitude *= settings.persistance; frequency *= settings.lacunarity; } if (noiseHeight > maxNoiseHeight) { maxNoiseHeight = noiseHeight; } if (noiseHeight < minNoiseHeight) { minNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } return(new Tuple <float[, ], float, float>(noiseMap, minNoiseHeight, maxNoiseHeight)); }
public static MapData GenerateHeightMap(MapGeneratorSettings settings, Vector2 sampleCenter) { PositionedTile positionedTiles = new PositionedTile(settings.mapSize * settings.mapSize); var falloffResult = FalloffGenerator.GenerateFalloff(settings.mapSize, settings); var falloff = falloffResult.Item1; var minFalloff = falloffResult.Item2; var maxFalloff = falloffResult.Item3; var lerpNoise = new float[settings.mapSize, settings.mapSize]; if (settings.showFalloffOnly) { for (int y = 0; y < settings.mapSize; y++) { for (int x = 0; x < settings.mapSize; x++) { var index = y * settings.mapSize + x; lerpNoise[x, y] = Mathf.InverseLerp(maxFalloff, minFalloff, falloff[x, y]); var roundX = Mathf.RoundToInt(sampleCenter.x) + x; var roundY = Mathf.RoundToInt(sampleCenter.y) + y; var tileBase = settings.GetTileHeight(lerpNoise[x, y]); positionedTiles.Add(index, roundX, roundY, tileBase); } } return(new MapData(falloff, lerpNoise, positionedTiles)); } var noiseResult = Noise.GenerateNoise(settings.mapSize, settings, sampleCenter); var rawNoise = noiseResult.Item1; var min = noiseResult.Item2; var max = noiseResult.Item3; for (int x = 0; x < settings.mapSize; x++) { for (int y = 0; y < settings.mapSize; y++) { lerpNoise[x, y] = Mathf.InverseLerp(min, max, rawNoise[x, y]) - falloff[x, y]; var tileBase = settings.GetTileHeight(lerpNoise[x, y]); var index = y * settings.mapSize + x; var roundX = Mathf.RoundToInt(sampleCenter.x) + x; var roundY = Mathf.RoundToInt(sampleCenter.y) + y; positionedTiles.Add(index, roundX, roundY, tileBase); } } return(new MapData(rawNoise, lerpNoise, positionedTiles)); }