public NoiseParams(float noiseScale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { this.noiseScale = noiseScale; this.octaves = octaves; this.persistance = persistance; this.lacunarity = lacunarity; this.offset = offset; this.normalizeMode = normalizeMode; }
public static Tensor MatBgr2Tensor(Mat m, NormalizeMode mode = NormalizeMode.None, int resizeWidth = -1, int resizeHeight = -1, long[] shape = null, float[] imgbuffer = null) { if (resizeHeight != -1 && resizeWidth != -1) { m.Resize(new Size(resizeWidth, resizeHeight)); } if (shape == null) { shape = new long[] { (int)m.Height, (int)m.Width, m.Channel }; } float[] buffer = m.GetArray(imgbuffer); if (mode != NormalizeMode.None) { Vector <float> imgBuf = CreateVector.Dense(buffer); switch (mode) { case NormalizeMode.ZeroMean: imgBuf.Divide(127.5f, imgBuf); imgBuf.Subtract(1.0f, imgBuf); break; case NormalizeMode.ZeroOne: imgBuf.Divide(255.0f, imgBuf); break; case NormalizeMode.CenterZero: imgBuf.Subtract(imgBuf.Average(), imgBuf); imgBuf.Divide((float)Statistics.StandardDeviation(imgBuf), imgBuf); break; default: throw new NotImplementedException("unknown one"); } buffer = imgBuf.Storage.AsArray(); } TFTensor tensor = TFTensor.FromBuffer(new TFShape(shape), buffer, 0, buffer.Length); return(new Tensor(tensor)); }
public enum NormalizeMode { local, global } //The way noise maps are localized depends on whether we're using the endlessTerrain system or not /// <summary> /// Generates a perlin noise map /// </summary> /// <param name="mapWidth">The width of the map</param> /// <param name="mapHeight">The heigh of the map</param> /// <param name="seed">The seed for the random offsets</param> /// <param name="mapOffset">The complete offset of the map</param> /// <param name="scale">The scale of magnification of the map</param> /// <param name="octaves">The number of octaves (ie runs of the perlin calculation) for any map value. Think of them as levels of detail</param> /// <param name="persistence">The rate of change of reduction influence of each octave. Should be 1 or less</param> /// <param name="lacunarity">The rate of change of reduction of gradualness (like, how jagged an octive is) per octve </param> /// <returns>A 2D map of values from 0 to 1</returns> public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, Vector2 mapOffset, float scale, int octaves, float persistence, float lacunarity, NormalizeMode mode, float globalDivisor) { float[,] map = new float[mapWidth, mapHeight]; System.Random random = new System.Random(seed); Vector2[] octaveOffets = new Vector2[octaves]; //These offsets are applied to ocatves to add variance //Calculating the max possible non-clamped value attainable float maxPossibleHeight = 0; float tempAmplitude = 1; for (int i = 0; i < octaves; i++) { octaveOffets[i] = new Vector2(random.Next(-10000, 10000) + mapOffset.x, random.Next(-10000, 10000) - mapOffset.y); maxPossibleHeight += tempAmplitude; tempAmplitude *= persistence; } if (scale <= 0) { scale = 0.0001f; } float minLocalNoiseHeight = float.MaxValue; float maxLocalNoiseHeight = float.MinValue; 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 octave = 0; octave < octaves; octave++) { float sampleX = ((x + octaveOffets[octave].x) / scale) * frequency; float sampleY = ((y + octaveOffets[octave].y) / scale) * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY); perlinValue = perlinValue * 2 - 1; //Changing this value's range from 0-1 to -1-1 to allow some octaves to reduce noiseHeight noiseHeight += perlinValue * amplitude; amplitude *= persistence; frequency *= lacunarity; } map[x, y] = noiseHeight; if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } } } //Restricting the range back to 0-1 for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (mode == NormalizeMode.local) { map[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, map[x, y]); } else { //We first have to devide the values by the maximum attainable value //Then we change their range back from -1-1 to 0-1 //We should keep in mind though, that there's little chance that a perlin value will get anywhere close to maxPossibleHeight //So we'll divide maxPossibleHeight by a number to reduce the devision effect float normalizedHeight = ((map[x, y] / (maxPossibleHeight / globalDivisor)) + 1) / 2; map[x, y] = Mathf.Clamp01(normalizedHeight); //Clamping in case we a high value stayed out of range after out calculations } } } return(map); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeigth, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noisemap = new float[mapWidth, mapHeigth]; System.Random prng = new System.Random(seed); Vector2[] octaveOffSets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1;// More frequency more changes in the values(terrain) 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeigth = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeigth = mapHeigth / 2f; for (int y = 0; y < mapHeigth; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; // More frequency more changes in the values(terrain) float noiseHeigth = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffSets[i].x) / scale * frequency; float sampleY = (y - halfHeigth + octaveOffSets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // Values between 0 and 1 we multiply by 2 and sustract 1 to make values between -1 and 1; noiseHeigth += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } if (noiseHeigth > maxLocalNoiseHeigth) { maxLocalNoiseHeigth = noiseHeigth; } else if (noiseHeigth < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeigth; } noisemap [x, y] = noiseHeigth; } } for (int y = 0; y < mapHeigth; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { noisemap [x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeigth, noisemap [x, y]); } else { float normalizeHeigth = (noisemap [x, y] + 1) / (maxPossibleHeight / 1.5f); noisemap [x, y] = Mathf.Clamp(normalizeHeigth, 0, int.MaxValue); } } } return(noisemap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float noiseScale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; // For seed, in case we need to generate the same map System.Random prng = new System.Random(seed); Vector2[] octaveOffset = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < octaves; i++) { float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; octaveOffset[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } // Prevent noise scale from being negative. if (noiseScale <= 0) { noiseScale = 0.0001f; } //set to temp values. updated in loop float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { // Higher frequency = further apart samples meaning steeper slopes float sampleX = (x - halfWidth + octaveOffset[i].x) / noiseScale * frequency; float sampleY = (y - halfHeight + octaveOffset[i].y) / noiseScale * frequency; //Perlin value in range -1 to 1 float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; //Amplitude decreases per octave amplitude *= persistance; //Frequency increases per octave frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } // Normalize noisemap for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { //For non-endless terrain noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] PerlinNoise(int size, float scale, int seed, float offsetX, float offsetY, int octaves, float persistence, float lacunarity, NormalizeMode normalizeMode) { float[,] map = new float[size, size]; float min = float.MaxValue; float max = float.MinValue; float maxPossibleHeight = 0; float frequency = 1; float amplitude = 1; System.Random rand = new System.Random(seed); float halfSize = size / 2f; Vector2[] octaveOffsets = new Vector2[octaves]; int randRange = 10000; for (int i = 0; i < octaves; i++) { octaveOffsets[i].x = rand.Next(-randRange, randRange) + offsetX / scale; octaveOffsets[i].y = rand.Next(-randRange, randRange) - offsetY / scale; maxPossibleHeight += amplitude; amplitude *= persistence; } // Generate the noise for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { float sample = 0; frequency = 1; amplitude = 1; for (int o = 0; o < octaves; o++) { float xCoord = (x - halfSize) / scale + octaveOffsets[o].x; float yCoord = (y - halfSize) / scale + octaveOffsets[o].y; float perlinValue = Mathf.PerlinNoise(xCoord * frequency, yCoord * frequency) * 2 - 1; sample += perlinValue * amplitude; frequency *= lacunarity; amplitude *= persistence; } if (sample < min) { min = sample; } if (sample > max) { max = sample; } map[x, y] = sample; } } // Normalize the data for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { if (normalizeMode == NormalizeMode.Global) { float normalizedHeight = (map [x, y] + 1) / (maxPossibleHeight * 0.8f); map[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } else { map[x, y] = Mathf.InverseLerp(min, max, map[x, y]); } } } return(map); }
public static float[,] GenerateNoiseMap( int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistence, float lacunarity, Vector2 offset, NormalizeMode normalizeMode ) { float[,] noiseMap = new float[mapWidth, mapHeight]; // sample each octave from a different location in the noise domain System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < octaves; i++) { // limit to 100K, as higher input returns same noise float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistence; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; // used to scale from the center float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; // PerlinNoise returns 0..1 // To get negative noise values, mul by 2, then subtract 1 float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= persistence; // decrease ampl -- pers is 0..1 frequency *= lacunarity; // increase freq -- lacu s/b > 1 } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { // normalize noiseHeight: InverseLerp returns 0..1 noiseMap[x, y] = Mathf.InverseLerp( minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y] ); } else { // estimate min/max NoiseHeight across multiple chunks float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight); // reverse (sample * 2 - 1) op that gave negative values noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, float scale, int octaves, float persistance, float lacunarity, int seed, Vector2 offset, NormalizeMode normalizeMode) { float [,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); float maxPossibleHeight = 0; float amplitude = 1f; float frequency = 1f; 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1f; frequency = 1f; float noiseHeight = 0f; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // * 2 -1 -> to get negative numbers instead of 0->1 noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { // Good for finite generation, but not for infinete generation because we dont know exactly what min and max height is noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / maxPossibleHeight; noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; float maxPossibleHeight = 0f; float amplitude = 1; System.Random rng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; for (int i = 0; i < octaves; i++) { octaveOffsets[i] = new Vector2( rng.Next(-100000, 100000) + offset.x, rng.Next(-100000, 100000) + offset.y ); maxPossibleHeight += amplitude; amplitude = amplitude * persistance; } float maxLocalNoiseVal = float.MinValue; float minLocalNoiseVal = float.MaxValue; float halfW = mapWidth / 2f; float halfH = mapHeight / 2f; for (float y = 0; y < mapHeight; y++) { for (float x = 0; x < mapWidth; x++) { amplitude = 1; float frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float xCoord = (x - halfW + octaveOffsets[i].x) / scale * frequency; float yCoord = (y - halfH + octaveOffsets[i].y) / scale * frequency; float val = Mathf.PerlinNoise(xCoord, yCoord) * 2f - 1f; noiseHeight += val * amplitude; amplitude *= persistance; frequency *= lacunarity; if (val > maxLocalNoiseVal) { maxLocalNoiseVal = val; } if (val < minLocalNoiseVal) { minLocalNoiseVal = val; } } noiseMap[(int)x, (int)y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseVal, maxLocalNoiseVal, noiseMap[x, y]); } else { noiseMap[x, y] = Mathf.Clamp((noiseMap[x, y] + 1f) / maxPossibleHeight, 0f, float.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistence, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float maxPossibleHeight = 0; // The maximum possible height of the terrain float amplitude = 1; float frequency = 1; // Generates random noise seed System.Random prng = new System.Random(seed); // prng = Pseudo-random number generator // Each octave is sampled from a different location Vector2[] octaveOffsets = new Vector2[octaves]; for (int i = 0; i < octaves; i++) { // Offset allows you to scroll through noise float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; // Subtract y to simulate forward motion octaveOffsets [i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistence; } float[,] noiseMap = new float[mapWidth, mapHeight]; if (scale <= 0) { scale = 0.0001f; } // Keep track of min and max noise height for normalization later float minLocalNoiseHeight = float.MaxValue; float maxNoiseHeight = float.MinValue; // Allows you to scale the noise towards the center float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { // Point from which height values are sampled // Higher frequency means height will change more rapidly float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; // Determine the height for each point and assign to noise map float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // Increase noise height by perlin value of each octave noiseHeight += perlinValue * amplitude; amplitude *= persistence; frequency *= lacunarity; } if (noiseHeight > maxNoiseHeight) { maxNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap [x, y] = noiseHeight; // Apply noise height to map at x, y } } // Normalize range of the noise map to between 0, 1 for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { // Preferred method if not doing endless terrain noiseMap [x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxNoiseHeight, noiseMap [x, y]); } else { float normalizedHeight = (noiseMap [x, y] + 1) / maxPossibleHeight; noiseMap [x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GeneratePerlinNoise(int width, int height, int seed, float scale, int octaves, Vector2 offset, float persistance = 0.5f, float lacunarity = 2, float step = 0, NormalizeMode normalizeMode = NormalizeMode.Local) { float[,] noiseMap = new float[width, height]; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = width / 2f; float halfHeight = height / 2f; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (float)(x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (float)(y - halfHeight + octaveOffsets[i].y) / scale * frequency; float pNoise = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += pNoise * amplitude; amplitude *= persistance; frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (step != 0) { noiseMap[x, y] = Mathf.Round(noiseMap[x, y] / step); noiseMap[x, y] = step * noiseMap[x, y]; //Debug.Log(noiseMap[x, y]); } if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight / 2f); noiseMap[x, y] = normalizedHeight; } } } return(noiseMap); }
/** * * seed = if we want to get the same map again, we just have to use the same seed * // return a 2d array of float values **/ public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; // pnrg = seeder random number generator System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1f; float frequency = 1f; 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; // used to move to the center when modifying the noiseScale float halfWidth = mapWidth / 2f; float halfHeigth = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1f; frequency = 1f; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { // the higher the frequency, the further apart the sample points will be // the height values will change more rapidly float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeigth + octaveOffsets[i].y) / scale * frequency; // by default perlin noise is in the range of 0 to 1 // but we want our perlin value to be sometimes negative than that so that // our noiseHeight decrease : float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // we want to increase the noise height by the perlin value of each octave noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { // InverseLerp method returns a value between 0 and 1, // so f.e if our noiseMap value = to minNoiseHeight => returns 0 // if it's equals to maxNoiseHeight => returns 1 // if it's half way between the two of it it returns 0.5, etc... if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } // doing smtg consistent across the entire map else { float normalizedHeight = (noiseMap[x, y] + 1) / maxPossibleHeight; noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int width, int height, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[width, height]; System.Random prng = new System.Random(seed); Vector2[] octavesOffsets = new Vector2[octaves]; float maxPossibleHeight = 0, amplitude = 1, frequency = 1; for (int i = 0; i < octaves; i++) { octavesOffsets[i] = new Vector2(prng.Next(-100000, 100000), prng.Next(-100000, 100000)) - offset; maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue, minLocalNoiseHeight = float.MaxValue; float halfWidth = width * .5f; float halfHeight = height * .5f; for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octavesOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octavesOffsets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } if (minLocalNoiseHeight > noiseHeight) { minLocalNoiseHeight = noiseHeight; } else if (maxLocalNoiseHeight < noiseHeight) { maxLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { switch (normalizeMode) { case NormalizeMode.Global: noiseMap[x, y] = Mathf.Clamp((noiseMap[x, y] + 1) / maxPossibleHeight, 0, int.MaxValue); break; default: noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); break; } } } return(noiseMap); }
/// <summary> /// Generates a perlin noise map. /// </summary> /// <param name="mapChunkSize">Width of the map (X).</param> /// <param name="mapChunkSize">Height of the map (Z).</param> /// <param name="seed">Custom seed for random values.</param> /// <param name="scale">Scale of the noise (smaller vs bigger).</param> /// <param name="octaves">Octave to control amount of detail of the Perlin Noise.</param> /// <param name="persistance">How quickly the amplitude diminishes per octave.</param> /// <param name="lacunarity">How quickly the frequency increases per octave.</param> /// <param name = "offset">Custom offset for scrolling through noise.</param> /// <returns>Float[] NoiseMap</returns> public static float [,] GenerateNoiseMap(int width, int height, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float [,] noiseMap = new float[width, height]; float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; // Psuedo Random Number Generator System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; for (int i = 0; i < octaves; i++) { // Generate random offsets per octave float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } // Half values for scaling (zooming) from the center float halfWidth = width / 2f; float halfHeight = height / 2f; // Loop through all "points" of our map for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; // Loop through different "octaves", remember Mountain vs Hill vs Stone // The greater the octave, the less effect it has on the overall noise for (int i = 0; i < octaves; i++) { // Frequency used for number of cycles per unit length // Multiply values by frequency, will "flatten/exaggerate" out the noise // Offset the values per octave for more randomness // - Added halfHeight and halfWidth for scaling off the center float sampleX = ((x - halfHeight) + octaveOffsets[i].x) / scale * frequency; float sampleY = ((y - halfWidth) + octaveOffsets[i].y) / scale * frequency; // Perlin generates between 0 ~ 1 // But lets generate a perlin value between -1 ~ 1 to add more 'height' float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // Multiply by the amplitude, effecting the overall maximum height noiseHeight += perlinValue * amplitude; // Range 0 - 1 amplitude *= persistance; // Range increases frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Normalize the noiseMap using InverseLerp // InverseLerp returns a value between 0 ~ 1 // If noiseMap == minLocalNoiseHeight it will return 0 // If noiseMap == maxLocalNoiseHeight, it will return 1 if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { // this reverses perlinValue caluclation float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); // this is used for global normalization to get infinite terrain chunks to be about same height noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } // If generating map chunk by chunk, this min and max noise height will vary between chunks, so the chunks will be slightly off when normalized } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { // scale can never be zero or negative if (scale <= 0) { scale = 0.0001f; } System.Random prng = new System.Random(seed); Vector2[] octavesOffset = new Vector2[octaves]; float maxPossibleHeight = 0; float frecuencyMod = 1; float amplitudeMod = 1; for (int i = 0; i < octaves; i++) { // set random limit to get interesting values int limit = 1000; float offsetX = prng.Next(-limit, limit) + offset.x; float offsetY = prng.Next(-limit, limit) - offset.y;//y goes the other way around octavesOffset[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitudeMod; // with each octave ammplitude decreases due to persistance having to be between 0 and 1 amplitudeMod *= persistance; } float[,] noiseMap = new float[mapWidth, mapHeight]; float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { // reset the values for each position frecuencyMod = 1; amplitudeMod = 1; float noiseHeight = 0; // process octaves for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octavesOffset[i].x) / scale * frecuencyMod; float sampleY = (y - halfHeight + octavesOffset[i].y) / scale * frecuencyMod; // perlin noise is between 0 and 1 -> turn to -1 to 1 to have more interesting noise float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitudeMod; // with each octave ammplitude decreases due to persistance having to be between 0 and 1 amplitudeMod *= persistance; // with each octave frecuency increases due to lacunarity having to be greater than 1 frecuencyMod *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalzedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight / 1.45f); noiseMap[x, y] = Mathf.Clamp(normalzedHeight, 0, int.MaxValue); } } } return(noiseMap); }
private static void NormalizeNoiseMap(float[,] noiseMap, int mapWidth, int mapHeight, float minLocalNoiseHeight, float maxLocalNoiseHeight, float maxGlobalNoiseHeight, NormalizeMode normalizeMode) { if (normalizeMode == NormalizeMode.Local) { for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } } } }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacinarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2; float halfHeight = mapHeight / 2; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; //perlin between negative 1 and 1 so noiseheight can decrease and incr not only incr float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; // amplitude decreases every octave amplitude *= persistance; //frequency increases every octave, widers sample = more frequent height change frequency *= lacinarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { //Only takes into account local chunks mins and maxes so has different normalization if (normalizeMode == NormalizeMode.Local) { //normalized noisemap return val between min and max between 0 and 1 noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, float.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap( int mapWidth, int mapHeight, int seed, float noiseScale, int octaves, float persistence, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; // Pseudo Random Number Generator System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; 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); maxPossibleHeight += amplitude; amplitude *= persistence; } if (noiseScale <= 0) { noiseScale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / noiseScale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / noiseScale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= persistence; frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { // Normalize the noise map, so if value is less than minNoiseHeight, return minNoiseHeight. // Same goes for maxLocalNoiseHeight. noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { // Multiply maxPossibleHeight by 2 and divide by some factor 1~2 to mess with max peak height float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float maxHeight = 0; //altezza massima raggiungibile float amplitude = 1; //amplitudine float frequency = 1; //frequenza float noiseHeight = 0; //altezza del rumore float[,] noiseMap = new float[mapWidth, mapHeight]; //height map System.Random rnd = new System.Random(seed); //seed casuale Vector2[] octOffs = new Vector2[octaves]; for (int i = 0; i < octaves; i++) { float offsetX = rnd.Next(-100000, 100000) + offset.x; float offsetY = rnd.Next(-100000, 100000) - offset.y; octOffs[i] = new Vector2(offsetX, offsetY); maxHeight = maxHeight + amplitude; amplitude = amplitude * persistance; } if (scale <= 0) { scale = 0.0001f; } float maxNoiseHeight = float.MinValue; //tener trccia dei valori minori e maggiori 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++) { amplitude = 1; frequency = 1; noiseHeight = 0; for (int i = 0; i < octaves; i++) { float coordX = (x - halfWidth + octOffs[i].x) / scale * frequency; float coordY = (y - halfHeight + octOffs[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(coordX, coordY) * 2 - 1; //passo i valori alla funizone di Perlin implementata su Unity noiseHeight += perlinValue * amplitude; amplitude = amplitude * persistance; frequency = 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++) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, y]); //ritorna i valori tra 1 e 0 in base ai valori min e max passati } else { float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxHeight); noiseMap[x, y] = normalizedHeight; } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } if(noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for(int y = 0; y < mapHeight; y++) { for(int x = 0; x < mapWidth; x++) { if(normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / maxPossibleHeight; noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return noiseMap; }
/** * Method that generates the noise map (a 2D representation of what the 3D terrarin will look like) * @param mapChunkSize Width of the generated map * @param mapHeight Height of the generated map * @param seed The unique seed which determines the appearance of the map * @param scale The scale (or zoom) of the map * @param octaves Variable that controls the amount of "fine details" in the map * @param persistence Controls the amount that the amplitude of the octaves increases * @param lacunarity Controls the amount that the frequency of the octaves increases * @param offset Allows the generated terrain to be "scrolled" * @param normalizeMode The mode in which the terrain heights are normalized based on a curve */ public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistence, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { // Noise map initialized float[,] noiseMap = new float[mapWidth, mapHeight]; // Random number generator for the offset System.Random rng = new System.Random(seed); // Allows each octave to sample from a different point in the noise Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; // Set the octave offsets for (int i = 0; i < octaves; i++) { float offsetX = rng.Next(-100000, 100000) + offset.x; float offsetY = rng.Next(-100000, 100000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistence; } // Divide-by-zero preventificator if (scale <= 0) { scale = 0.0001f; } // Variables for keeping track of local max and min noise (terrain) heights float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; // For use in aligning the noise scale to the center rather than top right float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; // Noise loop for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { // Default values amplitude = 1; frequency = 1; float noiseHeight = 0; // Applying the octaves for (int i = 0; i < octaves; i++) { // Applying all functionality to each coordinate in the noise map float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; // Perlin noise calculation, allowed to use negative values for increased visual appeal float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // Noise height set accordingly noiseHeight += perlinValue * amplitude; // More functionality of the various variables amplitude *= persistence; frequency *= lacunarity; } // Set max and min noise heights if need be if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } // Actual assigning of the value to the noise map noiseMap[x, y] = noiseHeight; } } // Second pass on the noise map values to apply a reverse linear interpolation (a method of fitting the values to the curve we want) for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { // Map is not infinite noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { // Map is infinite float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] NoiseMapData(NoiseSettings settings, Vector2 center, int width, int length, bool preview) { #region Variables Random.State initialState = Random.state; Random.InitState(settings.seed); NormalizeMode normalizeMode_previewsafe = (preview) ? NormalizeMode.Local : settings.normalizeMode; float scale_previewsafe = settings.scale; float[,] noiseMap = new float[width, length]; float halfWidth = width / 2f; float halfLength = length / 2f; float noiseValue = 0; float noiseEstimate = 0; float noiseMin = (normalizeMode_previewsafe == NormalizeMode.Global) ? 0 : float.MaxValue; float noiseMax = (normalizeMode_previewsafe == NormalizeMode.Global) ? 0 : float.MinValue; float amplitude = 1; float frequency = 1; #endregion #region Random Number Generator System.Random prng = new System.Random(settings.seed); Vector2[] octaveOffsets = new Vector2[settings.octaves]; for (int o = 0; o < settings.octaves; o++) { float xOffset = prng.Next(-100000, 100000) + settings.offset.x + center.x; float yOffset = prng.Next(-100000, 100000) - settings.offset.y - center.y; octaveOffsets[o] = new Vector2(xOffset, yOffset); if (normalizeMode_previewsafe == NormalizeMode.Global) { noiseMax += amplitude * Mathf.Pow(settings.persistance, o); } else { noiseEstimate += amplitude; } amplitude *= settings.persistance; } if (normalizeMode_previewsafe == NormalizeMode.Global) { noiseMin = -noiseMax; } #endregion #region Main for (int y = 0; y < length; y++) { for (int x = 0; x < width; x++) { amplitude = 1; frequency = 1; noiseValue = 0; for (int o = 0; o < settings.octaves; o++) { float xSample = (x - halfWidth + octaveOffsets[o].x) / scale_previewsafe * frequency; float ySample = (y - halfLength + octaveOffsets[o].y) / scale_previewsafe * frequency; float perlinValue = Mathf.PerlinNoise(xSample, ySample) * 2f - 1f; noiseValue += perlinValue * amplitude; amplitude *= settings.persistance; frequency *= settings.lacunarity; } #region Normalization if (normalizeMode_previewsafe != NormalizeMode.Global) { if (noiseValue > noiseMax) { noiseMax = noiseValue; } if (noiseValue < noiseMin) { noiseMin = noiseValue; } } #endregion if (normalizeMode_previewsafe != NormalizeMode.Global) { noiseMap[x, y] = noiseValue; } else { noiseMap[x, y] = Mathf.InverseLerp(noiseMin, noiseMax, noiseValue); } } } #endregion #region Normalization if (normalizeMode_previewsafe != NormalizeMode.Global) { for (int y = 0; y < length; y++) { for (int x = 0; x < width; x++) { if (normalizeMode_previewsafe == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(noiseMin, noiseMax, noiseMap[x, y]); } else { noiseMap[x, y] = Mathf.Clamp((noiseMap[x, y] + 1f) / (2f * noiseEstimate / 1.70f), 0, int.MaxValue); } } } } #endregion Random.state = initialState; return(noiseMap); }
/// <summary> /// Generate a noise map by sampling points from Perlin noise /// </summary> /// <param name="mapWidth">Width of noise map</param> /// <param name="mapHeight">Height of noise map</param> /// <param name="seed">Seed for octave offset randomization</param> /// <param name="scale">Zoom scale of map</param> /// <param name="octaves">Controls number of layers of detail</param> /// <param name="persistence">Controls decay in amplitude over octaves</param> /// <param name="lacunarity">Controls frequenct/level of detail in an octave</param> /// <param name="offset"></param> public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); // Want each ocatve to be sampled from radically different locations on the Perlin noise Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; // Generate random sample location offset + the user-controlled "pan offset" for the 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); // For Global normalize mode maxPossibleHeight += amplitude; amplitude *= persistance; } // To prevent division by 0, scale should be positive if (scale <= 0) { scale = 0.0001f; } // These will keep track of the highest and lowest height values on the map for normalization float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; // Used to make noise scale grow about the centre of the map float halfHeight = mapHeight / 2f; float halfWidth = mapWidth / 2f; for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { // Initial values for a given point amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { // Increased frequency results in points being sampled further apart and therefore more rapid change in heights // Add octaveOffsets to make sure that each octave is sampling from random locations in the Perlin noise float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; // Sample Perlin noise // * 2 - 1 to give range of -1 to 1, and allow some octaves to potentially decrease noiseHeight float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // Will give us a range -1 to 1 noiseHeight += perlinValue * amplitude; // Update amplitude and frequency for successive octaves amplitude *= persistance; // Amplitude decreases each octave (0 < persistance < 1) frequency *= lacunarity; // Frequency increases each octave (lacunarity > 1) } // Max and min height updates if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } // Normalize the noise map back to the range 0 to 1 for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { // Returns value from 0 to 1 // i.e. if noiseMap[x,y] == minNoiseHeight, InverseLerp returns 0 // if noiseMap[x,y] == maxNoiseHeight, InverseLerp returns 1 if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { // Since out actual values in the noiseMap are rarely ever going to come close to the maxPossibleHeight // we just divide maxPossibleHeight by some arbitrary value (1.75) just so that it's a bit more reasonable float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight / 1.75f); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); //pseudorandomnumber for seed Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; //sets the random number with a seed //at the end of this loop we have found the maxPossibleHeight value for (int i = 0; i < octaves; i++) { float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; //minus so y offset gets inverted, scroll up to see whats below //makes it possible to scroll in x and y octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; //clamp to min value } //keep track for max height for normalizing and keeping numbers between 0 and 1 float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; //zooming in in the middle instead of corner float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; //basic changes for perlin noise map for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; //reset the values to 1 frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { //at which point sampling the height values float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; //scale of noise for noninteger values. offset is inside the brackets, so landmasses dont change in shape, while adjusting offset) float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // for mor interesting results * 2 -1 to get between -1 to 1; so sometimes noise is negative noiseHeight += perlinValue * amplitude; //calculates height for each of the octaves. maximum Scenario is when perlinvalue is 1 every single octave -> amplitude *= persistance; //and amplitude also gets multiplied by persistence frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; //apply to noise map } } //normalize noise hight to be between 0 and 1 for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) //local mode { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); //min and max noise height will have slightly different values between the chunks, thats why its not perfectly lining up. if we generate the entire map at ones it wouldnt be a problem, because we know the max noise height, but endless terrain makes it a problem when its creates chunk by chunk } //do something else, that is consistent over the entire map else //global mode { float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight / 0.9f); //reverse the operation where perlinValue is *2 and then subtracted with -1 above with adding +1 and dividing with maxPossibleHeight noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); //Clamp so it is at least not less than 0 } } } return(noiseMap); }
public static float[,] GenerateNoiseGrid( int width, int height, int seed = 0, float noiseScale = 100f, int octaves = 6, float persistance = 0.5f, float lacunarity = 2f, Vector2 offset = default(Vector2), NormalizeMode normalizeMode = NormalizeMode.Local ) { noiseScale = (noiseScale <= 0) ? 1 : noiseScale; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; for (int i = 0; i < octaves; i++) { float xOff = prng.Next(-SYSTEM_RANDOM_RANGE, SYSTEM_RANDOM_RANGE) + offset.x; float yOff = prng.Next(-SYSTEM_RANDOM_RANGE, SYSTEM_RANDOM_RANGE) - offset.y; octaveOffsets[i] = new Vector2(xOff, yOff); maxPossibleHeight += amplitude; amplitude *= persistance; } float[,] noiseGrid = new float[width, height]; float minLocalNoiseHeight = float.MaxValue; float maxLocalNoiseHeight = float.MinValue; float halfWidth = width / 2f; float halfheight = height / 2f; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { amplitude = 1; frequency = 1; float noiseSum = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / noiseScale * frequency; float sampleY = (y - halfheight + octaveOffsets[i].y) / noiseScale * frequency; float noiseValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseSum += noiseValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } minLocalNoiseHeight = Mathf.Min(minLocalNoiseHeight, noiseSum); maxLocalNoiseHeight = Mathf.Max(maxLocalNoiseHeight, noiseSum); noiseGrid[x, y] = noiseSum; } } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (normalizeMode == NormalizeMode.Local) { noiseGrid[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseGrid[x, y]); } else { float normalizedHeight = (noiseGrid[x, y] + 1) / (maxPossibleHeight); noiseGrid[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseGrid); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; //float[] noiseMap = new float[mapWidth * mapHeight]; System.Random prng = new System.Random(seed); //prng = pseudo random number generator for generating //noise at random locations on the map Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; 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); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = 0.0001f; } float maxLocalNoiseHeight = float.MinValue; //Storing the minimum and maximum float minLocalNoiseHeight = float.MaxValue; //noise values for the terrain Perlin.Reseed(); float halfWidth = mapWidth / 2f; //In order to get the central map noise values float halfHeight = mapHeight / 2f; //when zooming in on the terrain map for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; //Deciding the sample points float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; //where the noise will be sampled and the number of samples float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; /*float perlinValue = Perlin.Noise(sampleX, sampleY); * minLocalNoiseHeight = Mathf.Min(minLocalNoiseHeight, noiseHeight); * maxLocalNoiseHeight = Mathf.Max(maxLocalNoiseHeight, noiseHeight);*/ amplitude *= persistance; frequency *= lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap [x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight / 2f); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GeneradorRuido(int ancho, int largo, int seed, float escalado, int octaves, float persistencia, float lacunaridad, Vector2 offset, NormalizeMode normalizeMode) { float[,] mapaRuido = new float[ancho, largo]; System.Random rnd = new System.Random(seed); Vector2[] octaveOffset = new Vector2[octaves]; float maxPosibleHeigth = 0; float amplitud = 1f; float frecuencia = 1f; //Queremos que cada octave se muestree de una zona diferente del ruido, por eso el offset for (int i = 0; i < octaves; i++) { //En Y restamos para que al alterar el offset de forma positiva vaya hacia abajo. En principio no deberia de haber problema porque estuviera al reves octaveOffset[i] = new Vector2(rnd.Next(-100000, 100000) + offset.x, rnd.Next(-100000, 100000) + offset.y); //Maxima altura posible (multiplicamos por PerlinNoise pero como su maximo valor es 1 pues no hace falta multiplicar xD). Para el uso de modo global maxPosibleHeigth += amplitud; amplitud *= persistencia; } if (escalado <= 0) { escalado = 0.0001f; } float maxLocalAlturaRuido = float.MinValue; float minLocalAlturaRuido = float.MaxValue; for (int y = 0; y < largo; y++) { for (int x = 0; x < ancho; x++) { //Reduce la altura de cada octava por lo que cada una tendra mayores detalles porque tendremos valores en un menor rango?¿? //va en funcion de la persistencia, a mayor valor, mas granular sera cuando se sumen octavas, a menor, menos granular amplitud = 1f; //Es aproximadamente el 'zoom' que hacemos sobre el ruido en cada octave. Cada vez va a mas para mejorar los detalles al acumular octavas frecuencia = 1f; float alturaRuido = 0f; for (int i = 0; i < octaves; i++) { //Valores x e y que vamos a usar para el ruido. restamos a x e y la mitad del mapa para que al aumentar el escalado lo haga hacia el centro de la textura //El restado del offset del octave esta dentro para que tambien le afecte el escalado. Aunque en principio no pasa nada porque este fuera float X = (x - (ancho / 2f)) / escalado * frecuencia + octaveOffset[i].x; float Y = (y - (largo / 2f)) / escalado * frecuencia + octaveOffset[i].y; //*2-1 es para que tambien pueda dar valores negativos lo que hara que alturaRuido pueda reducirse lo que hara que haya ruido mas interesante float valorPerling = Mathf.PerlinNoise(X, Y) * 2 - 1; //La altura que vamos acumulando de juntar diferentes capas de ruido alturaRuido += valorPerling * amplitud; //Reducimos la amplitud por lo que los posibles valores seran reducidos amplitud *= persistencia; //Aumentamos la frecuencia lo que se traduce en un 'zoom' sobre la textura frecuencia *= lacunaridad; } //Como podemos tener valores negativos (ya no solo entre 0 y 1) vamos a almacenar el valor mas alto y mas bajo para normalizarlo despues if (alturaRuido > maxLocalAlturaRuido) { maxLocalAlturaRuido = alturaRuido; } else if (alturaRuido < minLocalAlturaRuido) { minLocalAlturaRuido = alturaRuido; } mapaRuido[x, y] = alturaRuido; } } //Es esto lo que causa que los chunks vecinos no esten perfectamente pegados. El problema es que minLocalAlturaRuido y maxLocalAlturaRuido son diferentes en cada chunk //Como podemos tener valores diferentes de [0,1] vamos a normalizarlos for (int y = 0; y < largo; y++) { for (int x = 0; x < ancho; x++) { if (normalizeMode == NormalizeMode.Local) { //Normaliza el valor de mapaRuido[x,y] entre los valores minLocalAlturaRuido y maxLocalAlturaRuido mapaRuido[x, y] = Mathf.InverseLerp(minLocalAlturaRuido, maxLocalAlturaRuido, mapaRuido[x, y]); } else { //Como dividimos entre maxPosibleHeigth que puede ser muy muy grande, todo quedara pequeño, por eso dividimos entre 1.85 para conseguir valores mas pequeño y normales float normalizedHeight = (mapaRuido[x, y] + 1) / (2f * maxPosibleHeigth / 2f); mapaRuido[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(mapaRuido); }
//Method to generate the noise map public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { //Creating a 2D float array (noise map) with the defined dimensions float[,] noiseMap = new float[mapWidth, mapHeight]; //Creating a seed with random number generator System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < octaves; i++) { float offsetX = prng.Next(-10000, 10000) + offset.x; float offsetY = prng.Next(-10000, 10000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } //Clamping the scale value to remove divide by 0 errors if (scale <= 0) { scale = 0.0001f; } //Used for normalising the noise map at the end of the loops float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; //Calculating the values of the centre of the map to allow for the noise scale to zoom in on the centre (default top right) float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; //Looping over the noise map for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; //Looping through all the octaves for (int i = 0; i < octaves; i++) { //Setting up float values to sample over //Higher frequency means the height points will change more rapidly float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; //Generating the Perlin Value (Perlin noise is coherent noise - looks more like mountains) //Multiply by 2 and -1 to give negative perlinValues float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; //Amplitude and frequecny increase after each octave as persistance and lacunarity are > 1 amplitude *= persistance; frequency *= lacunarity; } //Updating the min/maxNoiseHeight where necessary if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { //Returns a value between 0 - 1 to normalise the noiseMap // minNoiseHeight returns 0, maxNoiseHeight returns 1 if (normalizeMode == NormalizeMode.Local) { //Ideal method for non endless terrains noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight / 2.25f); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] generateNoiceMap(int mapWidth, int mapHeight, float scale, int seed, int octaves, float lacunarity, float persistance, Vector2 offset, NormalizeMode mode) { float[,] noiseMap = new float[mapWidth, mapHeight]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; float noiseHeight = 0; // when scale is increased, the map should zoom in towards the center: float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; //seed controls the output of the random object. if the seed is constant, the random generator will always have the same output. System.Random prng = new System.Random(seed); //Each octave should be sampled from a different location. Vector2[] Octaveoffsets = new Vector2[octaves]; //determining the values for the offset. for (int i = 0; i < octaves; i++) { // user offset value is also added. enables user to scroll through various noise maps. float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; Octaveoffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } //clamping the scale if scale is zero.(Can't do division by zero) if (scale <= 0) { scale = 0.001f; } //initializing the max and min. float maxNoiseValue = float.MinValue; float minNoiseValue = float.MaxValue; // cycling through all the points of the map. for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; noiseHeight = 0; for (int z = 0; z < octaves; z++) { // higher the frequency, further apart the sample points will be. change in heights will be more rapid. //applying the offset to get a different sample location float SampleX = ((x - halfWidth) + Octaveoffsets[z].x) / scale * frequency; float SampleY = ((y - halfHeight) + Octaveoffsets[z].y) / scale * frequency; // PerlinNoise method returns only 0 to 1. to have negative values, *2-1 float PerlinValue = Mathf.PerlinNoise(SampleX, SampleY) * 2 - 1; noiseHeight += PerlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } //update the min and max noiseHeight //determines the rfange of noiseHeight values. if (noiseHeight > maxNoiseValue) { maxNoiseValue = noiseHeight; } else if (noiseHeight < minNoiseValue) { minNoiseValue = noiseHeight; } noiseMap[x, y] = noiseHeight; } } //normalize the noiseMap values (make it range between 0 and 1) //process through all values and clamp it between 0 and 1. for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { //InverseLerp returns value between 0 & 1. if noiseMap[x,y] = min, returns 0, if it is equal to max, returns 1 if (mode == NormalizeMode.local) { noiseMap[x, y] = Mathf.InverseLerp(minNoiseValue, maxNoiseValue, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (2f * (maxPossibleHeight / 1.75f)); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random rng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; for (int i = 0; i < octaves; ++i) { float offsetX = rng.Next(-100000, 100000) + offset.x; float offsetY = rng.Next(-100000, 100000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } if (scale <= 0) { scale = float.MinValue; } 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) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; ++i) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; 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) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight / 0.9f); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }
//The purpose of this method is to create a noise map based off width, height, scale, octaves, persistance, and lacunarity. //Octaves are, essentially, how mnany times the map will run through the system, with each octave increasing in frequency according to its square value // //(In signal processing, this is literally the case - yay, my electrical engineering degree is useful here!) // //The persistance value is the degree to which higher octaves will affect the overall height map //The lacunarity affects where the octaves will be placed according to given frequency // //The seed also allows for the system to recall the map based off the given seed value //An offset is given to more directly affect the sampling within the map as opposed to just the seed public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizeMode normalizeMode) { float[,] noiseMap = new float[mapWidth, mapHeight]; System.Random prng = new System.Random(seed); Vector2[] octaveOffsets = new Vector2[octaves]; float maxPossibleHeight = 0; float amplitude = 1; float frequency = 1; //The seed will offset the sample values according to the RNG given for the seed, providing the octave with an appropriate value to be added or subtracted for (int i = 0; i < octaves; i++) { //The perlin noise generator seems to work best when random values are set between -100,000 and 100,000 float offsetX = prng.Next(-100000, 100000) + offset.x; float offsetY = prng.Next(-100000, 100000) - offset.y; octaveOffsets[i] = new Vector2(offsetX, offsetY); maxPossibleHeight += amplitude; amplitude *= persistance; } //A negative scale or a scale equal to zero are simply not mathematically possible here, so if those are given, set it equal to some epsilon value if (scale <= 0) { scale = 0.0001f; } //Create max and min values to normalize the noise map to [0->1] once it's finished float maxLocalNoiseHeight = float.MinValue; float minLocalNoiseHeight = float.MaxValue; //Force the scale to zoom in and out relative to the center of the noise map as opposed to the top right by subtracting the half-values from x and y float halfWidth = mapWidth / 2f; float halfHeight = mapHeight / 2f; //The noise map itself will be generated based off width, height, and octaves. Amplitude scales with persistance, frequency scales with lacunarity //Each point is sampled from the perlin noise generator //Perlin noise is used to generate the amplitude value within the given signals for each octave. Negative values are allowed here to create a more interesting map for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { amplitude = 1; frequency = 1; float noiseHeight = 0; for (int i = 0; i < octaves; i++) { float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency; float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency; float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; noiseHeight += perlinValue * amplitude; amplitude *= persistance; frequency *= lacunarity; } //Define the maximum and minimum height values as they're generated if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; } } //Normalize the noise map for each value within the 2D array using an inverse lerp for (int y = 0; y < mapHeight; y++) { for (int x = 0; x < mapWidth; x++) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } return(noiseMap); }