Skip to content

Commit 986ef4e

Browse files
committed
Add perlin3d.py
1 parent d775f3c commit 986ef4e

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

perlin3d.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import numpy as np
2+
3+
def generate_perlin_noise_3d(shape, res):
4+
def f(t):
5+
return 6*t**5 - 15*t**4 + 10*t**3
6+
7+
delta = (res[0] / shape[0], res[1] / shape[1], res[2] / shape[2])
8+
d = (shape[0] // res[0], shape[1] // res[1], shape[2] // res[2])
9+
grid = np.mgrid[0:res[0]:delta[0],0:res[1]:delta[1],0:res[2]:delta[2]]
10+
grid = grid.transpose(1, 2, 3, 0) % 1
11+
# Gradients
12+
theta = 2*np.pi*np.random.rand(res[0]+1, res[1]+1, res[2]+1)
13+
phi = 2*np.pi*np.random.rand(res[0]+1, res[1]+1, res[2]+1)
14+
gradients = np.stack((np.sin(phi)*np.cos(theta), np.sin(phi)*np.sin(theta), np.cos(phi)), axis=3)
15+
g000 = gradients[0:-1,0:-1,0:-1].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
16+
g100 = gradients[1: ,0:-1,0:-1].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
17+
g010 = gradients[0:-1,1: ,0:-1].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
18+
g110 = gradients[1: ,1: ,0:-1].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
19+
g001 = gradients[0:-1,0:-1,1: ].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
20+
g101 = gradients[1: ,0:-1,1: ].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
21+
g011 = gradients[0:-1,1: ,1: ].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
22+
g111 = gradients[1: ,1: ,1: ].repeat(d[0], 0).repeat(d[1], 1).repeat(d[2], 2)
23+
# Ramps
24+
n000 = np.sum(np.stack((grid[:,:,:,0] , grid[:,:,:,1] , grid[:,:,:,2] ), axis=3) * g000, 3)
25+
n100 = np.sum(np.stack((grid[:,:,:,0]-1, grid[:,:,:,1] , grid[:,:,:,2] ), axis=3) * g100, 3)
26+
n010 = np.sum(np.stack((grid[:,:,:,0] , grid[:,:,:,1]-1, grid[:,:,:,2] ), axis=3) * g010, 3)
27+
n110 = np.sum(np.stack((grid[:,:,:,0]-1, grid[:,:,:,1]-1, grid[:,:,:,2] ), axis=3) * g110, 3)
28+
n001 = np.sum(np.stack((grid[:,:,:,0] , grid[:,:,:,1] , grid[:,:,:,2]-1), axis=3) * g001, 3)
29+
n101 = np.sum(np.stack((grid[:,:,:,0]-1, grid[:,:,:,1] , grid[:,:,:,2]-1), axis=3) * g101, 3)
30+
n011 = np.sum(np.stack((grid[:,:,:,0] , grid[:,:,:,1]-1, grid[:,:,:,2]-1), axis=3) * g011, 3)
31+
n111 = np.sum(np.stack((grid[:,:,:,0]-1, grid[:,:,:,1]-1, grid[:,:,:,2]-1), axis=3) * g111, 3)
32+
# Interpolation
33+
t = f(grid)
34+
n00 = n000*(1-t[:,:,:,0]) + t[:,:,:,0]*n100
35+
n10 = n010*(1-t[:,:,:,0]) + t[:,:,:,0]*n110
36+
n01 = n001*(1-t[:,:,:,0]) + t[:,:,:,0]*n101
37+
n11 = n011*(1-t[:,:,:,0]) + t[:,:,:,0]*n111
38+
n0 = (1-t[:,:,:,1])*n00 + t[:,:,:,1]*n10
39+
n1 = (1-t[:,:,:,1])*n01 + t[:,:,:,1]*n11
40+
return ((1-t[:,:,:,2])*n0 + t[:,:,:,2]*n1)
41+
42+
def generate_fractal_noise_3d(shape, res, octaves=1, persistence=0.5):
43+
noise = np.zeros(shape)
44+
frequency = 1
45+
amplitude = 1
46+
for _ in range(octaves):
47+
noise += amplitude * generate_perlin_noise_3d(shape, (frequency*res[0], frequency*res[1], frequency*res[2]))
48+
frequency *= 2
49+
amplitude *= persistence
50+
return noise
51+
52+
if __name__ == '__main__':
53+
import matplotlib.pyplot as plt
54+
import matplotlib.animation as animation
55+
56+
np.random.seed(0)
57+
noise = generate_fractal_noise_3d((32, 256, 256), (1, 4, 4), 4)
58+
59+
fig = plt.figure()
60+
images = [[plt.imshow(layer, cmap='gray', interpolation='lanczos', animated=True)] for layer in noise]
61+
animation = animation.ArtistAnimation(fig, images, interval=50, blit=True)
62+
plt.show()

0 commit comments

Comments
 (0)