Last active
April 12, 2025 21:06
-
-
Save attic-stuff/ab907b28dde0f5dba6a5b70e47e0780c to your computer and use it in GitHub Desktop.
generate an array of points using a blue noise distribution.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * generates an array of blue noise points using poisson discs | |
| * @param {real} width the width of the region of points | |
| * @param {real} height the height of the region of points | |
| * @param {real} radius the poisson disc radius, or space between each point | |
| * @param {real} rejections the number of attempts made to generate a point before moving on | |
| */ | |
| function bluenoise(width, height, radius = 4, rejections = 30) constructor { | |
| static sample = function(x, y) constructor { | |
| self.x = x; | |
| self.y = y; | |
| static draw = function(c) { | |
| draw_point_color(x, y, c); | |
| } | |
| } | |
| cell = radius / sqrt(2); | |
| columns = ceil(width / cell); | |
| rows = ceil(height / cell); | |
| noise = array_create(columns * rows, noone); | |
| self.rejections = rejections; | |
| self.width = width; | |
| self.height = height; | |
| self.radius = radius; | |
| var point = new sample(random(width), random(height)); | |
| list = [point]; | |
| noise[floor(point.x / cell) + floor(point.y / cell) * columns] = point; | |
| //if you want to generate all points at one do like | |
| // while (array_length(noise.list) > 0) { | |
| // noise.step(1); | |
| // } | |
| static step = function(n) { | |
| repeat (n) { | |
| if (array_length(list) > 0) { | |
| var i = irandom(array_length(list) - 1); | |
| var index = list[i]; | |
| var valid = false; | |
| repeat (rejections) { | |
| var dir = irandom(360); | |
| var length = radius + irandom(radius); | |
| var px = index.x + lengthdir_x(length, dir); | |
| var py = index.y + lengthdir_y(length, dir); | |
| if (point_in_rectangle(px, py, 0, 0, width, height) == false) { | |
| break; | |
| } | |
| var point = new sample(px, py); | |
| var column = floor(px / cell); | |
| var row = floor(py / cell); | |
| var check = true; | |
| for (var j = -2; j < 3; j++) { | |
| if (check == false) { | |
| break; | |
| } | |
| for (var k = -2; k < 3; k++) { | |
| var c = column + j; | |
| var r = row + k; | |
| if (point_in_rectangle(c, r, 0, 0, columns - 1, rows - 1) == true) { | |
| var neighbor = noise[c + r * columns]; | |
| if (neighbor != noone) { | |
| if (point_distance(px, py, neighbor.x, neighbor.y) < radius) { | |
| check = false; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (check == true) { | |
| noise[column + row * columns] = point; | |
| array_push(list, point); | |
| valid = true; | |
| break; | |
| } | |
| } | |
| if (valid == false) { | |
| array_delete(list, i, 1); | |
| } | |
| } else { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment