|
|
@@ -8,7 +8,7 @@ namespace MineCase.Algorithm.Noise
|
|
|
/// <summary>
|
|
|
/// Implementation for Improved Perlin Noise (http://mrl.nyu.edu/~perlin/noise/)
|
|
|
/// </summary>
|
|
|
- public class PerlinNoise : NoiseBase, INoise
|
|
|
+ public class PerlinNoise : INoise
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// Permutation
|
|
|
@@ -26,7 +26,7 @@ namespace MineCase.Algorithm.Noise
|
|
|
_p[i + 256] = _p[i] = random.Next(0, 256);
|
|
|
}
|
|
|
|
|
|
- public override double Noise(double x, double y, double z)
|
|
|
+ public float Noise(float x, float y, float z)
|
|
|
{
|
|
|
var xcoord = Split(x);
|
|
|
var ycoord = Split(y);
|
|
|
@@ -36,54 +36,174 @@ namespace MineCase.Algorithm.Noise
|
|
|
var v = Fade(ycoord.remainder);
|
|
|
var w = Fade(zcoord.remainder);
|
|
|
|
|
|
- int aaa, aba, aab, abb, baa, bba, bab, bbb;
|
|
|
- aaa = _p[_p[_p[xcoord.integer] + ycoord.integer] + zcoord.integer];
|
|
|
- aba = _p[_p[_p[xcoord.integer] + ycoord.integer + 1] + zcoord.integer];
|
|
|
- aab = _p[_p[_p[xcoord.integer] + ycoord.integer] + zcoord.integer + 1];
|
|
|
- abb = _p[_p[_p[xcoord.integer] + ycoord.integer + 1] + zcoord.integer + 1];
|
|
|
- baa = _p[_p[_p[xcoord.integer + 1] + ycoord.integer] + zcoord.integer];
|
|
|
- bba = _p[_p[_p[xcoord.integer + 1] + ycoord.integer + 1] + zcoord.integer];
|
|
|
- bab = _p[_p[_p[xcoord.integer + 1] + ycoord.integer] + zcoord.integer + 1];
|
|
|
- bbb = _p[_p[_p[xcoord.integer + 1] + ycoord.integer + 1] + zcoord.integer + 1];
|
|
|
-
|
|
|
- double x1, x2, y1, y2;
|
|
|
- x1 = Lerp(
|
|
|
+ int a = _p[xcoord.integer];
|
|
|
+ int b = _p[xcoord.integer + 1];
|
|
|
+ int aa = _p[a + ycoord.integer];
|
|
|
+ int ab = _p[a + ycoord.integer + 1];
|
|
|
+ int ba = _p[b + ycoord.integer];
|
|
|
+ int bb = _p[b + ycoord.integer + 1];
|
|
|
+
|
|
|
+ int aaa = _p[aa + zcoord.integer];
|
|
|
+ int aba = _p[ab + zcoord.integer];
|
|
|
+ int aab = _p[aa + zcoord.integer + 1];
|
|
|
+ int abb = _p[ab + zcoord.integer + 1];
|
|
|
+ int baa = _p[ba + zcoord.integer];
|
|
|
+ int bba = _p[bb + zcoord.integer];
|
|
|
+ int bab = _p[ba + zcoord.integer + 1];
|
|
|
+ int bbb = _p[bb + zcoord.integer + 1];
|
|
|
+
|
|
|
+ var xa = new Vector4(
|
|
|
Grad(aaa, xcoord.remainder, ycoord.remainder, zcoord.remainder),
|
|
|
- Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
|
|
|
- u);
|
|
|
- x2 = Lerp(
|
|
|
Grad(aba, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder),
|
|
|
- Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
|
|
|
- u);
|
|
|
- y1 = Lerp(x1, x2, v);
|
|
|
-
|
|
|
- x1 = Lerp(
|
|
|
Grad(aab, xcoord.remainder, ycoord.remainder, zcoord.remainder - 1),
|
|
|
+ Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1));
|
|
|
+ var xb = new Vector4(
|
|
|
+ Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
|
|
|
+ Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
|
|
|
Grad(bab, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder - 1),
|
|
|
- u);
|
|
|
- x2 = Lerp(
|
|
|
- Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1),
|
|
|
- Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1),
|
|
|
- u);
|
|
|
- y2 = Lerp(x1, x2, v);
|
|
|
-
|
|
|
- return (Lerp(y1, y2, w) + 1) / 2;
|
|
|
+ Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1));
|
|
|
+ var xl = Vector4.Lerp(xa, xb, u);
|
|
|
+ var ya = new Vector2(xl.X, xl.Z);
|
|
|
+ var yb = new Vector2(xl.Y, xl.W);
|
|
|
+ var yl = Vector2.Lerp(ya, yb, v);
|
|
|
+
|
|
|
+ return (Lerp(yl.X, yl.Y, w) + 1) / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Noise(float[,,] noise, Vector3 offset, Vector3 scale)
|
|
|
+ {
|
|
|
+ var xExtent = noise.GetUpperBound(0) + 1;
|
|
|
+ var yExtent = noise.GetUpperBound(1) + 1;
|
|
|
+ var zExtent = noise.GetUpperBound(2) + 1;
|
|
|
+
|
|
|
+ for (int x = 0; x < xExtent; x++)
|
|
|
+ {
|
|
|
+ var xOffset = offset.X + x * scale.X;
|
|
|
+ var xcoord = Split(xOffset);
|
|
|
+ var u = Fade(xcoord.remainder);
|
|
|
+
|
|
|
+ int a = _p[xcoord.integer];
|
|
|
+ int b = _p[xcoord.integer + 1];
|
|
|
+ for (int y = 0; y < yExtent; y++)
|
|
|
+ {
|
|
|
+ var yOffset = offset.Y + y * scale.Y;
|
|
|
+ var ycoord = Split(yOffset);
|
|
|
+ var v = Fade(ycoord.remainder);
|
|
|
+
|
|
|
+ int aa = _p[a + ycoord.integer];
|
|
|
+ int ab = _p[a + ycoord.integer + 1];
|
|
|
+ int ba = _p[b + ycoord.integer];
|
|
|
+ int bb = _p[b + ycoord.integer + 1];
|
|
|
+ for (int z = 0; z < zExtent; z++)
|
|
|
+ {
|
|
|
+ var zOffset = offset.Z + z * scale.Z;
|
|
|
+ var zcoord = Split(zOffset);
|
|
|
+ var w = Fade(zcoord.remainder);
|
|
|
+
|
|
|
+ int aaa = _p[aa + zcoord.integer];
|
|
|
+ int aba = _p[ab + zcoord.integer];
|
|
|
+ int aab = _p[aa + zcoord.integer + 1];
|
|
|
+ int abb = _p[ab + zcoord.integer + 1];
|
|
|
+ int baa = _p[ba + zcoord.integer];
|
|
|
+ int bba = _p[bb + zcoord.integer];
|
|
|
+ int bab = _p[ba + zcoord.integer + 1];
|
|
|
+ int bbb = _p[bb + zcoord.integer + 1];
|
|
|
+
|
|
|
+ var xa = new Vector4(
|
|
|
+ Grad(aaa, xcoord.remainder, ycoord.remainder, zcoord.remainder),
|
|
|
+ Grad(aba, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder),
|
|
|
+ Grad(aab, xcoord.remainder, ycoord.remainder, zcoord.remainder - 1),
|
|
|
+ Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1));
|
|
|
+ var xb = new Vector4(
|
|
|
+ Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
|
|
|
+ Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
|
|
|
+ Grad(bab, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder - 1),
|
|
|
+ Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1));
|
|
|
+ var xl = Vector4.Lerp(xa, xb, u);
|
|
|
+ var ya = new Vector2(xl.X, xl.Z);
|
|
|
+ var yb = new Vector2(xl.Y, xl.W);
|
|
|
+ var yl = Vector2.Lerp(ya, yb, v);
|
|
|
+
|
|
|
+ noise[x, y, z] = (Lerp(yl.X, yl.Y, w) + 1) / 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AddNoise(float[,,] noise, Vector3 offset, Vector3 scale, float noiseScale)
|
|
|
+ {
|
|
|
+ var xExtent = noise.GetUpperBound(0) + 1;
|
|
|
+ var yExtent = noise.GetUpperBound(1) + 1;
|
|
|
+ var zExtent = noise.GetUpperBound(2) + 1;
|
|
|
+
|
|
|
+ for (int x = 0; x < xExtent; x++)
|
|
|
+ {
|
|
|
+ var xOffset = offset.X + x * scale.X;
|
|
|
+ var xcoord = Split(xOffset);
|
|
|
+ var u = Fade(xcoord.remainder);
|
|
|
+
|
|
|
+ int a = _p[xcoord.integer];
|
|
|
+ int b = _p[xcoord.integer + 1];
|
|
|
+ for (int y = 0; y < yExtent; y++)
|
|
|
+ {
|
|
|
+ var yOffset = offset.Y + y * scale.Y;
|
|
|
+ var ycoord = Split(yOffset);
|
|
|
+ var v = Fade(ycoord.remainder);
|
|
|
+
|
|
|
+ int aa = _p[a + ycoord.integer];
|
|
|
+ int ab = _p[a + ycoord.integer + 1];
|
|
|
+ int ba = _p[b + ycoord.integer];
|
|
|
+ int bb = _p[b + ycoord.integer + 1];
|
|
|
+ for (int z = 0; z < zExtent; z++)
|
|
|
+ {
|
|
|
+ var zOffset = offset.Z + z * scale.Z;
|
|
|
+ var zcoord = Split(zOffset);
|
|
|
+ var w = Fade(zcoord.remainder);
|
|
|
+
|
|
|
+ int aaa = _p[aa + zcoord.integer];
|
|
|
+ int aba = _p[ab + zcoord.integer];
|
|
|
+ int aab = _p[aa + zcoord.integer + 1];
|
|
|
+ int abb = _p[ab + zcoord.integer + 1];
|
|
|
+ int baa = _p[ba + zcoord.integer];
|
|
|
+ int bba = _p[bb + zcoord.integer];
|
|
|
+ int bab = _p[ba + zcoord.integer + 1];
|
|
|
+ int bbb = _p[bb + zcoord.integer + 1];
|
|
|
+
|
|
|
+ var xa = new Vector4(
|
|
|
+ Grad(aaa, xcoord.remainder, ycoord.remainder, zcoord.remainder),
|
|
|
+ Grad(aba, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder),
|
|
|
+ Grad(aab, xcoord.remainder, ycoord.remainder, zcoord.remainder - 1),
|
|
|
+ Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1));
|
|
|
+ var xb = new Vector4(
|
|
|
+ Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
|
|
|
+ Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
|
|
|
+ Grad(bab, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder - 1),
|
|
|
+ Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1));
|
|
|
+ var xl = Vector4.Lerp(xa, xb, u);
|
|
|
+ var ya = new Vector2(xl.X, xl.Z);
|
|
|
+ var yb = new Vector2(xl.Y, xl.W);
|
|
|
+ var yl = Vector2.Lerp(ya, yb, v);
|
|
|
+
|
|
|
+ noise[x, y, z] += (Lerp(yl.X, yl.Y, w) + 1) / 2 * noiseScale;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private static (int integer, double remainder) Split(double value)
|
|
|
+ private static (int integer, float remainder) Split(float value)
|
|
|
{
|
|
|
var integer = (int)value;
|
|
|
return (integer % 256, value - integer);
|
|
|
}
|
|
|
|
|
|
- private static double Fade(double t)
|
|
|
+ private static float Fade(float t)
|
|
|
{
|
|
|
// 6t^5 - 15t^4 + 10t^3
|
|
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
|
}
|
|
|
|
|
|
// Source: http://riven8192.blogspot.com/2010/08/calculate-perlinnoise-twice-as-fast.html
|
|
|
- public static double Grad(int hash, double x, double y, double z)
|
|
|
+ public static float Grad(int hash, float x, float y, float z)
|
|
|
{
|
|
|
switch (hash & 0xF)
|
|
|
{
|
|
|
@@ -107,7 +227,7 @@ namespace MineCase.Algorithm.Noise
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public static double Lerp(double a, double b, double x) =>
|
|
|
+ public static float Lerp(float a, float b, float x) =>
|
|
|
a + x * (b - a);
|
|
|
}
|
|
|
}
|