In [56]:
import numpy as np
import matplotlib.pyplot as plt
import noise
import perlin
%matplotlib inline
We need a function ${f}$ that, given values ${v_0}$ and ${v_1}$ and some interval ${t}$ where $0 \le {t} \le 1$, returns an interpolated value between ${v_0}$ and ${v_1}$.
The best way to start is with linear interpolation and that's what the lerp
function does.
Let's assume we have to values ${v_0}$ and ${v_1}$:
In [2]:
v0 = 2
v1 = 5
In [3]:
plt.plot([0, 1], [2, 5], '--')
t = 1.0 / 3
vt = noise.lerp(2, 5, t)
plt.plot(t, vt, 'ro')
Out[3]:
In [4]:
x = np.linspace(0, 1.0)
y1 = noise.ss3(x)
y2 = noise.ss5(x)
plt.plot(x, y1, label="smooth")
plt.plot(x, y2, label="smoother")
plt.legend(loc=2)
Out[4]:
In [5]:
class Vector:
def __init__(self, *components):
self.components = np.array(components)
def mag(self):
return np.sqrt(sum(self.components**2))
def __len__(self):
return len(self.components)
def __iter__(self):
for c in self.components:
yield c
In [6]:
np.random.ranf((2,3,2,2)) # seed in n-dimensions
Out[6]:
In [7]:
c4 = noise.Field(d=(8,8,8,8), seed = 5)
We can plot any course through this field, for example:
In [8]:
q = np.arange(0, 8)
x = [c4(x, 0, 0, 0) for x in q]
y = [c4(0, y, 0, 0) for y in q]
plt.plot(q, x, 'bo')
plt.plot(q, y, 'ro')
Out[8]:
We could render a graph but that would be like cheating. We would be using the matplotlib
linear interpolation instead of our own:
In [9]:
# a one-dimensional noise field of 8 samples
c1 = noise.Field(d=(8,))
x = np.linspace(0, 7, 8)
y = [c1(x) for x in x]
# this will use matplotlib interpolation and not ours
plt.plot(x, y)
Out[9]:
We can do better though by using one of the smoothstep functions. Instead of calculating ${v_t}$ directly we can do some tricks on ${t}$ to modify the outcome.
For convience let's start with the ss3
function and plot it so we know what it looks like:
In [10]:
x = np.linspace(0, 1.0, 100)
y = noise.ss3(x)
plt.plot(x, y)
Out[10]:
Now we setup a noise field and define a helper function noise1
in order to get our coherent noise.
In [34]:
samples = 32
gen = noise.Field(d=(samples,))
def noise1(x, curve = lambda x: x):
xi = int(x)
xmin = xi % samples
xmax = 0 if xmin == (samples - 1) else xmin + 1
t = x - xi
return noise.lerp(gen(xmin), gen(xmax), curve(t))
x = np.linspace(0, 10, 100)
y1 = [noise1(x) for x in x]
y2 = [noise1(x, noise.ss5) for x in x]
plt.plot(x, y1, '--')
plt.plot(x, y2)
Out[34]:
In [57]:
x = np.linspace(0, 4, 100)
y1 = [perlin.noise2d(x, 0) for x in x]
y2 = [0.5 * perlin.noise2d(x * 2, 0) for x in x]
y3 = [0.25 * perlin.noise2d(x * 4, 0) for x in x]
y4 = [0.125 * perlin.noise2d(x * 8, 0) for x in x]
plt.plot(x, y1)
plt.plot(x, y2)
plt.plot(x, y3)
plt.plot(x, y4)
Out[57]:
In [58]:
x = np.linspace(0, 10, 100)
y = [perlin.fbm(x, 0) for x in x]
plt.plot(x, y)
In [ ]: