# SiNoise Part2

Read the first part here

So now I've come to the implementing the actual thing. And yes I have a name for it, which should be apparent by now- SiNoise.

I'll be explaining the simplex approach here, perlin is pretty simple compared to that and I'll leave a link to the code.

The full code for Simplex approach is here and Perlin approach is here.

For brevity, here's the relevant function-

``````    public float noiseWrapper(int x, int y, float xCenter, float yCenter, float minDistance, float maxDistance) {
Vector2f relative = new Vector2f((float) x - xCenter, (float) y - yCenter);
if (relative.equals(Vector2f.zero())) {
return 1.0f;
}
float scaledAngle = (((float) Math.atan2(relative.y, relative.x) + (float) Math.PI) * ((float) gridSize * simplexMagicNumber)) / (2.0f * (float) Math.PI);

float b = 1.0f / minDistance;
float a = 1.0f / maxDistance - b;

float adjustedNoise = (a * ((tileableNoise.noise(scaledAngle, scaledAngle) + 1.0f) / 2.0f) + b) * relative.length();

return 1.0f - TeraMath.clamp(adjustedNoise);
}
``````

`x`,`y` being the coordinates for which noise in required, `xCenter`,`yCenter` being the geometric centre of the area reserved. and `minDistance`,`maxDistance` being the minimum and maximum distance a peripheral point can have from the centre.

Walkthrough time

``````return 1.0f - TeraMath.clamp(adjustedNoise);
``````

Wait... this is the last line. But yeah the thing is notice here that noise values are being flipped over here i.e. before this `adjustedNoise = 1` on peripheri and `adjustedNoise = 0` at centre. This makes things easier to comprehend as you'll see later.

``````Vector2f relative = new Vector2f((float) x - xCenter, (float) y - yCenter);
``````

Save the coordinates in a vector, so I can spare calculating the distance by hand.

``````if (relative.equals(Vector2f.zero())) {
return 1.0f;
}
``````

This is a corner case as we can't really have an angle defined for the centre and the noise value of `1.0` signifies that this is the centre.

``````float scaledAngle = (((float) Math.atan2(relative.y, relative.x) + (float) Math.PI) * ((float) gridSize * simplexMagicNumber)) / (2.0f * (float) Math.PI);
``````

`((float) Math.atan2(relative.y, relative.x) + (float) Math.PI)` gets the angle for the point and shift it from [-π,π] to [0, 2π]. `/ (2.0f * (float) Math.PI)` map to [0,1]. `* ((float) gridSize * simplexMagicNumber)` map to [0, edgeOfDiagonal](hint: read last post).

``````float b = 1.0f / minDistance;
float a = 1.0f / maxDistance - b;
``````

This is to impose the new constraints of `minDistance` and `maxDistance`. The idea of `maxDistance` was introduced in the last post but now there's `minDistance` as well, so, consider this- `f(θ, distance) = (a * Noise(θ) + b) * distance` `Noise(θ) ∈ [0,1]`, so lets have a look at the extreme conditions and apply the constraints there. When `Noise(θ) == 0`, `f == 1` for `distance == minDistance` Similarly, When `Noise(θ) == 1`, `f == 1` for `distance == maxDistance` 2 equations, 2 variables, solve it and you'll get the values I got.

``````float adjustedNoise = (a * ((tileableNoise.noise(scaledAngle, scaledAngle) + 1.0f) / 2.0f) + b) * relative.length();
``````

¯\_(ツ)_/¯

Now to show you some results-

Perlin with `gridSize = 4`, `minDistance = 20`, `maxDistance = 50` Perlin with `gridSize = 20`, rest same Now you dhould be able to appreciate the control over `gridSize` :)

Next up... Volcano!!!

#procgen #proceduralgeneration #noise #perlin #simplex #volcano

- 1 toasts