lmas / opensimplex

This repo has been migrated to https://code.larus.se/lmas/opensimplex
MIT License
241 stars 29 forks source link

Limited documentation / example code. Trying to understand how to use numpy arrays efficiently. #30

Closed LyfeOnEdge closed 2 years ago

LyfeOnEdge commented 2 years ago
from opensimplex import OpenSimplex
import numpy as np

class TerrainGenerator:
    def __init__(self, game):
        self.game = game
        print(f"Using seed {self.game.seed}")
        self.generator = OpenSimplex(seed=(self.game.seed)).noise2

    def get_heightmap(self,x,z):
        height = self.generator(x,z)
        return height

    def get_array_heightmap(self,x,width,z,depth):
        out = np.zeros((width, depth), dtype=float)
        gen = OpenSimplex(seed=self.game.seed).noise2array #(arr, arr)
        z_values = np.arange(depth) + z
        x_values = np.full((width), x, dtype=float)
        for w in range(width):
            out[w, : ] = gen(z_values, x_values)
            if not w == width - 1:
                x_values = x_values + 1
        return out

    # def get_array_heightmap(self,x,width,z,depth): #Slower
    #   # out = np.zeros((width, depth), dtype=float)
    #   gen = OpenSimplex(seed=self.game.seed).noise2array #(arr, arr)
    #   z_values = np.arange(z, depth+z)
    #   z_values = np.repeat(z_values,width,axis=0)
    #   x_values = np.arange(x, width+x)
    #   x_values = np.resize(x_values,width*width)
    #   # x_values = np.hstack((x_values, ) * depth)
    #   out = gen(x_values,z_values).reshape(width,depth)
    #   return out

if __name__ == "__main__":
    from time import perf_counter

    class dummy_game:
        def __init__(self):
            self.seed = 10

    SIZE = 100

    generator = TerrainGenerator(dummy_game()) #20 seconds
    print("Using old method")
    arr = np.zeros((SIZE,SIZE), dtype=float)
    t1 = perf_counter()
    for x in range(SIZE):
        for z in range(SIZE):
            arr[z][x] = generator.get_heightmap(x,z)
    t2 = perf_counter()
    print(len(arr), len(arr[0]))
    print(arr[:4,:4])
    print("Old method took - ", t2-t1)  #~0.19 #Faster weirdly... 

    print("Using new method")
    t1 = perf_counter()
    x,z = 0,0
    arr = generator.get_array_heightmap(x,SIZE,z,SIZE)
    t2 = perf_counter()
    print(len(arr), len(arr[0]))
    print(arr[:4,:4])
    print("New method took - ", t2-t1)  #~0.28

I am having a very hard time understanding how to implement the noise2array more efficiently than the standard noise2 method. I have tried several different ways to populate the numpy arrays, my goal is to generate terrain in 100x100 unit chunks using the noise as a heightmap. Improved documentation / sample code in the repository would likely be appreciated by a number of users.

lmas commented 2 years ago

Hi, yes I know the docs are lacking and it's on my TODO. Am swamped with uni work unfortunately and had to prioritise working with incoming pull requests instead. (I really appreciate PR!)

With that said, there's docstrings in the pkg and tests that shows how to use it. The input arrays needs to contain the coords you want noise for, which looked like you already understood (quickly looked at your code).

Then you only need to call the array func only once and it will return a new array populated with the noise (in the shape of the inputs). No need to loop, make your own output array or anything else.

Example: https://github.com/lmas/opensimplex/blob/72fb4b09fdea89c0bb7fcec1f3257971069f0eb9/tests/test_opensimplex.py#L64

ix contains 11 random coords, iy contains 7 random coords (both are arrays). The returned n2 array contains the noise (as an array with the shape of iy.size rows and ix.size columns).

I hope this explains it better.

On 17 February 2022 08:09:45 UTC, "Andrew (LyfeOnEdge) (ArcticGentoo)" @.***> wrote:

I am having a very hard time understanding how to implement the noise2array more efficiently than the standard noise2 method. I have tried several different ways to populate the numpy arrays, my goal is to generate terrain in 100x100 unit chunks using the noise as a heightmap. Improved documentation / sample code in the repository would likely be appreciated by a number of users.

lmas commented 2 years ago

related to #22

lmas commented 2 years ago

I started updating the docs in #32, do you mind taking a look at that one and see if it explains things better for you? Or simply take a look at the examples in the new README.

lmas commented 2 years ago

Closing due to inactivity and updated docs, feel free to reopen if you have further questions.