From 0b5209ad31baa2bdea13d00989d5e19f90dd683a Mon Sep 17 00:00:00 2001 From: M4YX0R Date: Sat, 11 Dec 2021 10:26:55 +0300 Subject: [PATCH] Better noise than stripes :D --- src/Controllers/EnvironmentController.js | 13 +++---- src/Utils/Perlin.js | 46 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 src/Utils/Perlin.js diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index 2eeb27c..c36571f 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -5,6 +5,7 @@ const CellStates = require("../Organism/Cell/CellStates"); const Neighbors = require("../Grid/Neighbors"); const FossilRecord = require("../Stats/FossilRecord"); const Hyperparams = require("../Hyperparameters"); +const Perlin = require("../Utils/Perlin"); class EnvironmentController extends CanvasController{ constructor(env, canvas) { @@ -55,20 +56,20 @@ class EnvironmentController extends CanvasController{ Iterate over grid from 0,0 to env.num_cols,env.num_rows and create random walls using perlin noise to create a more organic shape. */ randomizeWalls(thickness=1) { - var noise_scale = 0.05; - var noise_offset = 0.5; var noise_threshold = 0.5; - var noise_multiplier = 0.5; - var noise_offset_x = this.env.num_cols/2; - var noise_offset_y = this.env.num_rows/2; + var avg_noise = 0; + for (var r = 0; r < this.env.num_rows; r++) { for (var c = 0; c < this.env.num_cols; c++) { - var noise = noise_multiplier * noise_offset + noise_scale * noise_offset * Math.sin(noise_scale * (c + noise_offset_x) + noise_scale * (r + noise_offset_y)); + var noise = Perlin.get(c, r); + avg_noise += noise/(this.env.num_rows*this.env.num_cols); if (noise > noise_threshold && noise < noise_threshold + thickness/10) { this.dropCellType(c, r, CellStates.wall, true); } } } + + console.log("Average noise: " + avg_noise); } updateMouseLocation(offsetX, offsetY){ diff --git a/src/Utils/Perlin.js b/src/Utils/Perlin.js new file mode 100644 index 0000000..ab9b5ca --- /dev/null +++ b/src/Utils/Perlin.js @@ -0,0 +1,46 @@ +let perlin = { + rand_vect: function(){ + let theta = Math.random() * 2 * Math.PI; + return {x: Math.cos(theta), y: Math.sin(theta)}; + }, + dot_prod_grid: function(x, y, vx, vy){ + let g_vect; + let d_vect = {x: x - vx, y: y - vy}; + if (this.gradients[[vx,vy]]){ + g_vect = this.gradients[[vx,vy]]; + } else { + g_vect = this.rand_vect(); + this.gradients[[vx, vy]] = g_vect; + } + return d_vect.x * g_vect.x + d_vect.y * g_vect.y; + }, + smootherstep: function(x){ + return 6*x**5 - 15*x**4 + 10*x**3; + }, + interp: function(x, a, b){ + return a + this.smootherstep(x) * (b-a); + }, + seed: function(){ + this.gradients = {}; + this.memory = {}; + }, + get: function(x, y) { + if (this.memory.hasOwnProperty([x,y])) + return this.memory[[x,y]]; + let xf = Math.floor(x); + let yf = Math.floor(y); + //interpolate + let tl = this.dot_prod_grid(x, y, xf, yf); + let tr = this.dot_prod_grid(x, y, xf+1, yf); + let bl = this.dot_prod_grid(x, y, xf, yf+1); + let br = this.dot_prod_grid(x, y, xf+1, yf+1); + let xt = this.interp(x-xf, tl, tr); + let xb = this.interp(x-xf, bl, br); + let v = this.interp(y-yf, xt, xb); + this.memory[[x,y]] = v; + return v; + } +} +perlin.seed(); + +module.exports = perlin; \ No newline at end of file