I need a small help, I am trying to create an Island generator using Unity.
However I do not know how to make circular fall Off map.But instead I manage to create an island that is more of a box shaped island.
This is what I am doing:
- I am generating Height map using Perlin noise
- I will generate FallOff map and substract it from Perlin noise
- The Island getsgenerated, but instead of having circular shape the island hasbox-like shape
This is my Perlin noise function
public float[,] GenerateNoise(int mapSize,int octaves, string seed, float noiseScale, float persistence, float lacunarity, Vector2 offset)
{
if (noiseScale <= 0)
{
noiseScale = 0.0001f;
}
float halfWidth = mapSize / 2f;
float halfHeight = mapSize / 2f;
float[,] noiseMap = new float[mapSize 1, mapSize 1];
System.Random rand = new System.Random(seed.GetHashCode());
//Octaves offset
Vector2[] octavesOffset = new Vector2[octaves];
for (int i = 0; i < octaves; i )
{
float offset_X = rand.Next(-100000, 100000) offset.x;
float offset_Y = rand.Next(-100000, 100000) offset.y;
octavesOffset[i] = new Vector2(offset_X / mapSize, offset_Y / mapSize);
}
for (int x = 0; x < mapSize; x )
{
for (int y = 0; y < mapSize; y )
{
float amplitude = 1;
float frequency = 1;
float noiseHeight = 0;
float superpositionCompensation = 0;
for (int i = 0; i < octaves; i )
{
float sampleX = (x - halfWidth) / noiseScale * frequency octavesOffset[i].x;
float sampleY = (y - halfHeight) / noiseScale * frequency octavesOffset[i].y;
float perlinValue = Mathf.PerlinNoise(sampleX, sampleY);
noiseHeight = perlinValue * amplitude;
noiseHeight -= superpositionCompensation;
amplitude *= persistence;
frequency *= lacunarity;
superpositionCompensation = amplitude / 2;
}
noiseMap[x, y] = Mathf.Clamp01(noiseHeight);
}
}
return noiseMap;
}
And this is my FallOff map function
public float[,] GenerateFallOffMap(int mapSize)
{
float[,] fallOffMap = new float[mapSize , mapSize];
for (int x = 0; x < mapSize; x )
{
for (int y = 0; y < mapSize; y )
{
int index = x * mapSize y;
float fallOff_A = x / (float)mapSize * 2 - 1;
float fallOff_B = y / (float)mapSize * 2 - 1;
float value = Mathf.Max(Mathf.Abs(fallOff_A), Mathf.Abs(fallOff_B));
fallOffMap[x,y] = Evaluate(value);
}
}
return fallOffMap;
}
static float Evaluate(float value)
{
float a = 3;
float b = 2.2f;
return Mathf.Pow(value, a) / (Mathf.Pow(value, a) Mathf.Pow(b - b * value, a));
}
CodePudding user response:
Use the distance from the center of the grid as the parameter to calculate the falloff value.
/// value - The calculated value to process
/// radius - The distance from center to calculate falloff distance
/// x - The x-coordinate of the value position
/// y - The y-coordinate of the value position
/// cx - The x-coordinate of the center position
/// cy - The y-coordinate of the center position
public float RadialFallOff(float value, float radius, int x, int y, float cx, float cy)
{
float dx = cx - x;
float dy = cy - y;
float distSqr = dx * dx dy * dy;
float radSqr = radius * radius;
if (distSqr > radSqr) return 0f;
return value;
}
This will result in a hard cutoff at radius
. If you want a softer transition along the edges, you can use an innerRadius
and an outerRadius
to produce a feathered effect:
/// value - The calculated value to process
/// innerRadius - The distance from center to start feathering
/// outerRadius - The distance from center to fully fall off
/// x - The x-coordinate of the value position
/// y - The y-coordinate of the value position
/// cx - The x-coordinate of the center position
/// cy - The y-coordinate of the center position
public float FeatheredRadialFallOff(float value, float innerRadius, float outerRadius, int x, int y, float cx, float cy)
{
float dx = cx - x;
float dy = cy - y;
float distSqr = dx * dx dy * dy;
float iRadSqr = innerRadius * innerRadius;
float oRadSqr = outerRadius * outerRadius;
if (distSqr >= oRadSqr) return 0f;
if (distSqr <= iRadSqr) return value;
float dist = Mathf.Sqr(distSqr);
float t = Mathf.InverseLerp(innerRadius, outerRadius, dist);
return value * t;
}
You can use it like such:
float value = Mathf.Max(Mathf.Abs(fallOff_A), Mathf.Abs(fallOff_B));
value = Evaluate(value)
fallOffMap[x,y] = RadialFalloff(value, someRadius, x, y, mapSize / 2f, mapSize / 2f);
// or
fallOffMap[x,y] = FeatheredRadialFalloff(value, someInnerRadius, someOuterRadius, x, y, mapSize / 2f, mapSize / 2f);