xxxxxxxxxx
150
/*
* Animated worley noise
* Uses spatial grid to reduce the number distance checks
* (Might cause some artifacts when there's no point in a cell)
* Can add points by clicking inside the sketch
*
*/
const NUM_POINTS = 12;
const CELL_SIZE = 100;
let grid_w, grid_h;
let debugText = false;
let drawPoints = false;
let maxDist = 16000;
let grid = [];
let points = [];
let dirs = [];
let density = null;
let widthD, heightD;
function setup() {
createCanvas(400, 400);
noStroke();
density = pixelDensity();
widthD = width * density;
heightD = height * density;
grid_w = ceil(width / CELL_SIZE);
grid_h = ceil(height / CELL_SIZE);
for (let i = 0; i < grid_w * grid_h; i++) {
grid.push([]);
}
for (let i = 0; i < NUM_POINTS; i++) {
let p = createVector(Math.random() * width,
Math.random() * height);
points.push(p);
dirs.push(createVector(random(), random()));
grid[floor(p.x / CELL_SIZE) +
floor(p.y / CELL_SIZE) * grid_w].push(p);
}
createDiv('Click inside to add points');
createDiv('Max distance');
let maxDistSlider = createSlider(1, 50000, maxDist, 100);
maxDistSlider.changed(function() {
maxDist = this.value();
});
}
function draw() {
let startTime = millis();
background(150);
loadPixels();
for (let x = 0; x < width; x++) {
let gx = Math.floor(x / CELL_SIZE);
let xp = x * density;
for (let y = 0; y < height; y++) {
let dist = maxDist;
let gy = Math.floor(y / CELL_SIZE);
for (let x0 = gx - 1; x0 <= gx + 1; x0++) {
for (let y0 = gy - 1; y0 <= gy + 1; y0++) {
if (x0 < 0 || x0 >= grid_w ||
y0 < 0 || y0 >= grid_h)
continue;
let cell = grid[x0 + y0 * grid_w];
for (let i = 0; i < cell.length; i++)
dist = Math.min(dist,
distSq(x, y, cell[i].x, cell[i].y));
}
}
let pcolor = map(dist, 0, maxDist, 0, 255);
let yp = y * density;
for (let i = 0; i < density; i++) {
for (let j = 0; j < density; j++) {
let index = (xp + i + (yp + j) * widthD) * 4;
pixels[index] = pcolor + y/2;
pixels[index + 1] = pcolor + x;
pixels[index + 2] = pcolor + y;
pixels[index + 3] = 255;
}
}
}
}
updatePixels();
for (let i = 0; i < grid.length; i++)
grid[i] = [];
for (let i = 0; i < points.length; i++) {
let p = points[i];
p.add(dirs[i]);
if (p.x < 0)
p.x += width;
else if (p.x >= width)
p.x -= width;
if (p.y < 0)
p.y += height;
else if (p.y >= height)
p.y -= height;
grid[Math.floor(p.x / CELL_SIZE) +
Math.floor(p.y / CELL_SIZE) * grid_w].push(p);
}
if (drawPoints) {
for (let i = 0; i < points.length; i++) {
fill(255, 255, 0);
circle(points[i].x, points[i].y, 5);
}
}
if (debugText) {
text('Drawing took: ' +
(millis() - startTime) +
' ms', 10, 10);
text(frameRate(), 10, 24);
}
}
function mousePressed() {
if (mouseX < 0 || mouseX >= width || mouseY < 0 || mouseY >= height)
return;
let p = createVector(mouseX, mouseY);
points.push(p);
grid[Math.floor(p.x / CELL_SIZE) +
Math.floor(p.y / CELL_SIZE) * grid_w].push(p);
}
function distSq(x0, y0, x1, y1) {
let dx = (x1 - x0);
let dy = (y1 - y0);
return dx * dx + dy * dy;
}
function manhattanDist(x0, y0, x1, y1) {
return Math.abs(x1 - x0) + Math.abs(y1 - y0);
}