Perlin noise
import numpy
import PIL
import math
img = []
grid = []
size = (50,50)
res = None
class Pixel:
def __init__(self, x, y, color=(0,0,0)):
self.x = x
self.y = y
self.color = color
class Node:
def __init__(self,x,y):
self.x=x
self.y=y
class Vector2: # a*b <- a dot b
def __init__(self,x,y):
self.x = x
self.y = y
self.length = math.sqrt(self.x**2+self.y**2)
def dot_product(self, other):
return (self.x*other.x + self.y * other.y)
def __str__(self):
return f"Vector2(x: {self.x:.3f}, y: {self.y:.3f})"
def __mul__(self, other):
if type(other)!=type(self):
raise TypeError("Dot operand is not a vector")
return (self.x*other.x + self.y * other.y)
def generateRandomUnitVector2(x,y, seed=0):
if seed == 0:
hash_code = abs(hash(f"{x},{y}"))
else:
hash_code = abs(hash(f"{x},{y},{seed}"))
hash_length = len(str(hash_code))
truncatedHash = round(hash_code/int("1"+(hash_length-3)*"0"))/1000
angle=math.pi*2*truncatedHash
return Vector2(math.sin(angle),math.cos(angle))
def initialize(Size, Res):
global grid
global size
global res
size = Size
res = Res
for y in range(size[1]*Res):
row = []
for x in range(size[0]*Res):
row.append(Pixel(x,y))
img.append(row)
for y in range(size[1]):
row = []
for x in range(size[0]):
row.append(0)
grid.append(row)
def interpolate(a0, a1, w):
return (a1-a0)*(3-w*2)*w*w+a0
def dotGridGradient(ix, iy, x, y, seed = 0):
gradient = generateRandomUnitVector2(ix, iy, seed)
dx = x - ix
dy = y - iy
distance = Vector2(dx, dy)
return gradient*distance
def perlin(x, y, seed=0):
x0 = int(x)
y0 = int(y)
x1 = x0 + 1
y1 = y0 + 1
sx = x - x0
sy = y - y0
n0 = dotGridGradient(x0, y0, x, y, seed)
n1 = dotGridGradient(x1, y0, x, y, seed)
ix0 = interpolate(n0,n1, sx)
n0 = dotGridGradient(x0, y1, x, y, seed)
n1 = dotGridGradient(x1, y1, x, y, seed)
ix1 = interpolate(n0,n1, sx)
value = interpolate(ix0, ix1, sy)
return value
def makeTexture(numOfOctaves=1, seed=0):
ampl = 1
freq = 1
for o in range(numOfOctaves):
for y in range(size[1]*res):
for x in range(size[0]*res):
value = ampl*(perlin((x/res)*freq, (y/res)*freq, seed)+1)/2
img[y][x].color = (min(img[y][x].color[0]+value, 1), min(img[y][x].color[1]+value, 1), min(img[y][x].color[2]+value, 1))
ampl/=4
freq*=2
def makePicture():
data = numpy.zeros((size[0]*res,size[1]*res, 3), dtype=numpy.uint8)
for y in range(size[1]*res):
for x in range(size[0]*res):
data[y, x] = [255*img[y][x].color[0], 255*img[y][x].color[1], 255*img[y][x].color[2]]
image = PIL.Image.fromarray(data)
image.show()
initialize((10,10), 40)
makeTexture(7, 12)
makePicture()