Drawing lines between two different perlin noise functions overlayed on top of each other
Log in to post a comment.
// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);
// Global code will be evaluated once.
const turtle = new Turtle();
let seed = 1000; // min=1 max=1000000 step=1
const bits = 20;
const samples = 150000;
const mod = 1<<bits;
const x_gap = 10; // min = 0 max = 30 step = 1
const y_gap = 10; // min = 0 max = 30 step = 1
const perlin_magnitude = 7; // min = 1 max = 20 step = 1
const perlin_size_1 = 10; // min = 1 max = 20 step = 1
const perlin_size_2 = 5; // min = 1 max = 20 step = 1
////////////////////////////////////////////////////////////////
// Pseudorandom number generator. Created by Reinder Nijhoff 2024
// https://turtletoy.net/turtle/a2274fd1fe
////////////////////////////////////////////////////////////////
function random() { // returns a number [0, 1[
let r = 1103515245 * (((seed+=12345) >> 1) ^ seed);
r = 1103515245 * (r ^ (r >> 3));
r = r ^ (r >> 16);
return (r % mod) / mod;
}
////////////////////////////////////////////////////////////////
// Perlin noise field generator. Taken from turtle below
// https://turtletoy.net/turtle/04036becc3
////////////////////////////////////////////////////////////////
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 = 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_1 = new Perlin(100, perlin_size_1);
let perlin_2 = new Perlin(100, perlin_size_2);
for(let i = -100 + x_gap; i < 100 - x_gap; i += 1) {
for(let j = -100 + y_gap; j < 100 - y_gap; j+= 1) {
turtle.penup();
if(true) {
perlin_mod = perlin_1.get(i,j);
} else {
perlin_mod = perlin_2.get(i,j);
}
turtle.goto(i, j + perlin_mod * perlin_magnitude);
turtle.pendown();
if(false) {
perlin_mod = perlin_1.get(i+1,j);
} else {
perlin_mod = perlin_2.get(i+1,j);
}
turtle.goto(i + 1, j + perlin_mod * perlin_magnitude);
}
}