12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- using Beefy.geom;
- using System;
- namespace Mercury
- {
- class Perlin
- {
- Vector2[,] mGradient ~ delete _;
- public this(int w, int h, int seed = -1)
- {
- Random rand;
- if (seed == -1)
- {
- rand = stack Random();
- }
- else
- {
- rand = stack Random(seed);
- }
- mGradient = new Vector2[h, w];
- for (int y < h)
- {
- for (int x < w)
- {
- float ang = (float)(rand.NextDouble() * Math.PI * 2);
- mGradient[y, x] = Vector2((float)Math.Cos(ang), (float)Math.Sin(ang));
- }
- }
- }
- float DotGridGradient(int ix, int iy, float x, float y)
- {
- // Precomputed (or otherwise) gradient vectors at each grid node
- // Compute the distance vector
- float dx = x - (float)ix;
- float dy = y - (float)iy;
- // Compute the dot-product
- return (dx * mGradient[iy, ix].mX + dy * mGradient[iy, ix].mY);
- }
- // Compute Perlin noise at coordinates x, y
- public float Get(float x, float y)
- {
- // Determine grid cell coordinates
- int x0 = ((x > 0.0) ? (int)x : (int)x - 1);
- int x1 = x0 + 1;
- int y0 = ((y > 0.0) ? (int)y : (int)y - 1);
- int y1 = y0 + 1;
- // Determine interpolation weights
- // Could also use higher order polynomial/s-curve here
- float sx = x - (float)x0;
- float sy = y - (float)y0;
- // Interpolate between grid point gradients
- float n0, n1, ix0, ix1, value;
- n0 = DotGridGradient(x0, y0, x, y);
- n1 = DotGridGradient(x1, y0, x, y);
- ix0 = Math.Lerp(n0, n1, sx);
- n0 = DotGridGradient(x0, y1, x, y);
- n1 = DotGridGradient(x1, y1, x, y);
- ix1 = Math.Lerp(n0, n1, sx);
- value = Math.Lerp(ix0, ix1, sy);
- return value;
- }
- public float GetF(float pctX, float pctY)
- {
- return Get(pctX * mGradient.GetLength(1), pctY * mGradient.GetLength(0));
- }
- }
- }
|