Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perlin noise #88

Closed
ytgui opened this issue Aug 21, 2019 · 2 comments
Closed

perlin noise #88

ytgui opened this issue Aug 21, 2019 · 2 comments

Comments

@ytgui
Copy link
Owner

ytgui commented Aug 21, 2019

https://en.wikipedia.org/wiki/Perlin_noise/
https://www.scratchapixel.com/

@ytgui
Copy link
Owner Author

ytgui commented Aug 21, 2019

Figure_1
Figure_2
Figure_3

@ytgui
Copy link
Owner Author

ytgui commented Aug 21, 2019

import math
import random
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


def hermite(t):
    return t * t * (3 - 2 * t)


def quintic(t):
    return t * t * t * (t * (t * 6 - 15) + 10)


def lerp(t, a, b):
    assert(0.0 <= t <= 1.0)
    t = hermite(t)
    return a + t * (b - a)


def normalize(v):
    v = np.array(v)
    norm = np.linalg.norm(v)
    if norm == 0: 
       return v
    return v / norm


class PerlinNoise2D:
    def __init__(self, h, w, stride):
        self.h = h
        self.w = w
        self.stride = stride
        self.permutation = np.zeros(shape=[h // stride + 1, w // stride + 1, 2])
        for iy in range(h // stride + 1):
            for ix in range(w // stride + 1):
                self.permutation[iy, ix] = normalize(np.random.randn(2))
    
    def __call__(self, x, y):
        #
        ix0 = x // self.stride
        ix1 = (x // self.stride) + 1
        iy0 = y // self.stride
        iy1 = (y // self.stride) + 1
        #
        nx0 = self.grid_gradient(ix0, iy0, x, y)
        nx1 = self.grid_gradient(ix1, iy0, x, y)
        value0 = lerp((x - ix0 * self.stride) / self.stride, nx0, nx1)
        #
        nx0 = self.grid_gradient(ix0, iy1, x, y)
        nx1 = self.grid_gradient(ix1, iy1, x, y)
        value1 = lerp((x - ix0 * self.stride) / self.stride, nx0, nx1)
        #
        return lerp((y - iy0 * self.stride) / self.stride, value0, value1)
    
    def grid_gradient(self, ix, iy, x, y):
        dx = (x - ix) / self.stride
        dy = (y - iy) / self.stride
        dx, dy = normalize([dx, dy])
        assert(0.0 <= np.sqrt(dx ** 2 + dy ** 2) <= 1.0 + 1e-3)
        return (dx * self.permutation[iy, ix, 0] + dy * self.permutation[iy, ix, 1])


def main_1():
    step = 256
    h, w = 512, 512

    generator = PerlinNoise2D(h, w, step)
    terrain = np.zeros(shape=[h, w])
    for y in range(h):
        for x in range(w):
            terrain[y, x] = generator(x, y)
    
    plt.imshow(terrain)
    # plt.savefig("perlin/1.png")

    fig = plt.figure()
    ax = fig.gca(projection='3d')

    # Make data.
    X = np.linspace(-1, 1, w)
    Y = np.linspace(-1, 1, h)
    X, Y = np.meshgrid(X, Y)

    # Plot the surface.
    ax.set_zlim(-2.5, 2.5)
    ax.plot_surface(X, Y, terrain, linewidth=0, antialiased=False)

    # plt.savefig("perlin/2.png")
    plt.show()


if __name__ == "__main__":
    main_1()

@ytgui ytgui closed this as completed Aug 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant