Perlin noise creating intricate, organic patterns
Log in to post a comment.
Canvas.setpenopacity(1); const size = 90; // min=10 max=100 step=5 const perlinSize = 3; // min=1 max=50 step=1 const drawBoth = 2; // min=0 max=2 step=1, (no, yes, middle) const stepSize = 0.1; // min=0.01 max=1 step=0.01 Step size for each movement const directionChange = 360; // min=90 max=360 step=10 Direction change factor const noiseAmplitude = 1; // min=0.1 max=2 step=0.1 Noise amplitude factor // Global code will be evaluated once. const turtle = new Turtle(); class Perlin { constructor(size, gridSize) { this.size = size; this.gridSize = gridSize; this.grid = []; for (let i = 0; i <= gridSize; i++) { let table = []; for (let j = 0; j <= gridSize; j++) { let angle = Math.random() * 2 * Math.PI; let x = Math.cos(angle); let y = Math.sin(angle); table.push([x, y]); } this.grid.push(table); } } get(x, y) { x = x / 2 + this.size / 2; y = y / 2 + this.size / 2; if (x < 0) x = 0; if (x >= this.size) x = this.size - 0.01; if (y < 0) y = 0; if (y >= this.size) y = this.size - 0.01; let posx = x * this.gridSize / this.size; let posy = y * this.gridSize / this.size; let x1 = Math.floor(posx); let x2 = x1 + 1; let y1 = Math.floor(posy); let y2 = y1 + 1; let scal = []; scal.push(this.scalar(posx, posy, x1, y1)); scal.push(this.scalar(posx, posy, x2, y1)); scal.push(this.scalar(posx, posy, x1, y2)); scal.push(this.scalar(posx, posy, x2, y2)); let int1 = this.interpolate(posx - x1, scal[0], scal[1]); let int2 = this.interpolate(posx - x1, scal[2], scal[3]); return this.interpolate(posy - y1, int1, int2); } scalar(x, y, vx, vy) { x -= vx; y -= vy; return x * this.grid[vx][vy][0] + y * this.grid[vx][vy][1]; } smooth(v) { if (v < 0) v = 0; if (v > 1) v = 1; return v ** 2 * (3 - 2 * v); } interpolate(x, a, b) { return a + (b - a) * this.smooth(x); } } let perlin = new Perlin(size, perlinSize); let posx = 2 * size; let posy = 0; let step = 0; let start = -size; let direction = 180; function walk(i) { if (Math.abs(posx) > size || Math.abs(posy) > size) { step++; posx = drawBoth === 2 ? 0 : start; posy = step - size; turtle.jump(posx, posy); if (posy > size) { if (drawBoth === 0) return false; if (start > 0) return false; start = size; step = 0; direction = 0; } } let amp = perlin.get(posx, posy); amp = (amp + 1) / 2 * noiseAmplitude; turtle.seth(amp * directionChange + direction); turtle.forward(stepSize); posx = turtle.x(); posy = turtle.y(); return true; }