Perlin.bf 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using Beefy.geom;
  2. using System;
  3. namespace Mercury
  4. {
  5. class Perlin
  6. {
  7. Vector2[,] mGradient ~ delete _;
  8. public this(int w, int h, int seed = -1)
  9. {
  10. Random rand;
  11. if (seed == -1)
  12. {
  13. rand = stack Random();
  14. }
  15. else
  16. {
  17. rand = stack Random(seed);
  18. }
  19. mGradient = new Vector2[h, w];
  20. for (int y < h)
  21. {
  22. for (int x < w)
  23. {
  24. float ang = (float)(rand.NextDouble() * Math.PI * 2);
  25. mGradient[y, x] = Vector2((float)Math.Cos(ang), (float)Math.Sin(ang));
  26. }
  27. }
  28. }
  29. float DotGridGradient(int ix, int iy, float x, float y)
  30. {
  31. // Precomputed (or otherwise) gradient vectors at each grid node
  32. // Compute the distance vector
  33. float dx = x - (float)ix;
  34. float dy = y - (float)iy;
  35. // Compute the dot-product
  36. return (dx * mGradient[iy, ix].mX + dy * mGradient[iy, ix].mY);
  37. }
  38. // Compute Perlin noise at coordinates x, y
  39. public float Get(float x, float y)
  40. {
  41. // Determine grid cell coordinates
  42. int x0 = ((x > 0.0) ? (int)x : (int)x - 1);
  43. int x1 = x0 + 1;
  44. int y0 = ((y > 0.0) ? (int)y : (int)y - 1);
  45. int y1 = y0 + 1;
  46. // Determine interpolation weights
  47. // Could also use higher order polynomial/s-curve here
  48. float sx = x - (float)x0;
  49. float sy = y - (float)y0;
  50. // Interpolate between grid point gradients
  51. float n0, n1, ix0, ix1, value;
  52. n0 = DotGridGradient(x0, y0, x, y);
  53. n1 = DotGridGradient(x1, y0, x, y);
  54. ix0 = Math.Lerp(n0, n1, sx);
  55. n0 = DotGridGradient(x0, y1, x, y);
  56. n1 = DotGridGradient(x1, y1, x, y);
  57. ix1 = Math.Lerp(n0, n1, sx);
  58. value = Math.Lerp(ix0, ix1, sy);
  59. return value;
  60. }
  61. public float GetF(float pctX, float pctY)
  62. {
  63. return Get(pctX * mGradient.GetLength(1), pctY * mGradient.GetLength(0));
  64. }
  65. }
  66. }