Advertisement
Guest User

Perlin

a guest
Dec 6th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.28 KB | None | 0 0
  1. from itertools import product
  2. import math
  3. import random
  4.  
  5. def smooth(t):
  6. return t * t * (3. - 2. *t)
  7.  
  8. def lerp(t, x, y):
  9. return x + t * (y - x)
  10.  
  11. class PerlinNoise(object):
  12. def __init__(self, dimension, octaves=1, tile=(), unbias=False):
  13. self.dimension = dimension
  14. self.octaves = octaves
  15. self.tile = tile + (0,) * dimension
  16. self.unbias = unbias
  17. self.scale_factor = 2 * dimension ** -0.5
  18. self.gradient = {}
  19.  
  20. def _generate_gradient(self):
  21. if self.dimension == 1:
  22. return (random.uniform(1, -1),)
  23. random_point = [random_gauss(0, 1) for _ in range(self.dimension)]
  24. scale = sum(n * n for n in random_point) ** -0.5
  25. return tuple(coord * scale for coord in random_point)
  26.  
  27.  
  28. def get_plain_noise(self, *point):
  29. if len(point) != self.dimension:
  30. raise ValueError("Expected {} values, got{}".format(self.dimension, len(point)))
  31.  
  32. grid_coords = []
  33. for coord in point:
  34. min_coord = math.floor(coord)
  35. max_coord = min_coord + 1
  36. grid_coords.append((min_coord, max_coord))
  37.  
  38. dots = []
  39. for grid_point in product(*grid_coords):
  40. if grid_point not in self.gradient:
  41. self.gradient[grid_point] = self._generate_gradient
  42. gradient = self.gradient[grid_point]
  43. dot = 0
  44. for i in range(self.dimension):
  45. dot += gradient[i]* (point[i] - grid_point[i])
  46. dots.append(dot)
  47.  
  48. dim = self.dimension
  49. while len(dots) > 1:
  50. dim -= 1
  51. s = smooth(point[dim] - grid_coords[dim][0])
  52. next_dots = []
  53. while dots:
  54. next_dots.append(lerp(s, dots.pop(0), dots.pop(0)))
  55.  
  56. dots = next_dots
  57. return dots[0] * self.scale_factor
  58.  
  59. def __call__(self, *point):
  60. ret = 0
  61. for o in range(self.octaves):
  62. o2 = 1<< o
  63. new_point = []
  64. for i, coord in enumerate(point):
  65. coord *= o2
  66. if self.tile[i]:
  67. coord %= self.tile[i] * o2
  68. new_point.append(coord)
  69. ret += self.get_plain_noise(*new_point) / o2
  70. ret /= 2 - 2**(1 - self.octaves)
  71. if self.unbias:
  72. r = (ret + 1) / 2
  73. for _ in range(int(self.octaves / 2 + 0.5)):
  74. r = smooth(r)
  75. ret = r * 2 - 1
  76. return ret
  77.  
  78. noise = []
  79. frameSize = int(input("Size: "))
  80. PNFactory = PerlinNoise(frameSize)
  81. for i in range(frameSize):
  82. noise.append([])
  83. for j in range(frameSize ):
  84. noise[i].append([])
  85. print(PNFactory(i + 1, j + 1))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement