119 lines
4.2 KiB
Plaintext
119 lines
4.2 KiB
Plaintext
final float distMult = 40f;
|
|
final int ballAmount = 10;
|
|
final float minVelocity = 1f;
|
|
final float maxVelocity = 5f;
|
|
final float minRadius = 10f;
|
|
final float maxRadius = 50f;
|
|
final int columns = 320 + 1;
|
|
final int rows = 180 + 1;
|
|
|
|
float[][] grid;
|
|
float cellWidth, cellHeight;
|
|
|
|
Metaball[] metaballs;
|
|
|
|
void setup() {
|
|
fullScreen();
|
|
|
|
grid = new float[columns][rows];
|
|
cellWidth = (float)width / (columns-1);
|
|
cellHeight = (float)height / (rows-1);
|
|
|
|
metaballs = new Metaball[ballAmount];
|
|
for (int i = 0; i < ballAmount; i++)
|
|
metaballs[i] = new Metaball();
|
|
}
|
|
|
|
void draw() {
|
|
background(0);
|
|
|
|
// Update and display all metaballs
|
|
stroke(255);
|
|
noFill();
|
|
for (int i = 0; i < ballAmount; i++) {
|
|
Metaball current = metaballs[i];
|
|
current.position.add(current.velocity);
|
|
if (current.position.x >= width) {
|
|
current.position.x = width;
|
|
current.velocity.x *= -1;
|
|
} else if (current.position.x <= 0) {
|
|
current.position.x = 0;
|
|
current.velocity.x *= -1;
|
|
}
|
|
if (current.position.y >= height) {
|
|
current.position.y = height;
|
|
current.velocity.y *= -1;
|
|
} else if (current.position.y <= 0) {
|
|
current.position.y = 0;
|
|
current.velocity.y *= -1;
|
|
}
|
|
// PVector pos = current.position;
|
|
// float rad = current.radius;
|
|
// ellipse(pos.x, pos.y, rad*2, rad*2);
|
|
}
|
|
|
|
// Calculate value of cells in 'grid' as distance from any given metaball in 'metaballs'
|
|
for (int i = 0; i < columns; i++)
|
|
for (int j = 0; j < rows; j++) {
|
|
PVector current = new PVector(i*cellWidth, j*cellHeight);
|
|
float value = 0f;
|
|
int ballCount = 0;
|
|
for (int k = 0; k < ballAmount; k++) {
|
|
Metaball ball = metaballs[k];
|
|
// Magic trickery that i made up to convert a distance to a brightness value
|
|
float d = max(255-(float)Math.cbrt((PVector.dist(current, ball.position)-ball.radius)*distMult*1000), 0);
|
|
if (d > 0f) {
|
|
value += d;
|
|
ballCount++;
|
|
}
|
|
}
|
|
// Value should be downscaled somehow in order to not exceed the brightness of a single metaball whenever any others come too close
|
|
// value = min(255, value);
|
|
grid[i][j] = map(value, 0, 255, -1, 1);
|
|
}
|
|
|
|
// Display all cells in 'grid' with a greyscale value color
|
|
noStroke();
|
|
for (int i = 0; i < columns; i++)
|
|
for (int j = 0; j < rows; j++) {
|
|
fill(grid[i][j]*255);
|
|
rect(i*cellWidth, j*cellHeight, cellWidth, cellHeight);
|
|
}
|
|
|
|
// Display outlines for all cells. Values will be mapped from 255-0 to 1-0
|
|
stroke(255);
|
|
for (int i = 0; i < columns-1; i++)
|
|
for (int j = 0; j < rows-1; j++) {
|
|
float x = i*cellWidth;
|
|
float y = j*cellHeight;
|
|
PVector a = new PVector(x + cellWidth / 2, y );
|
|
PVector b = new PVector(x + cellWidth , y + cellHeight / 2);
|
|
PVector c = new PVector(x + cellWidth / 2, y + cellHeight );
|
|
PVector d = new PVector(x , y + cellHeight / 2);
|
|
int value = ceil(grid[i][j])*8 + ceil(grid[i+1][j])*4 + ceil(grid[i+1][j+1])*2 + ceil(grid[i][j+1]);
|
|
if (value == 1 || value == 10 || value == 14)
|
|
line(c.x, c.y, d.x, d.y);
|
|
if (value == 2 || value == 5 || value == 13)
|
|
line(b.x, b.y, c.x, c.y);
|
|
if (value == 3 || value == 12)
|
|
line(b.x, b.y, d.x, d.y);
|
|
if (value == 4 || value == 10 || value == 11)
|
|
line(a.x, a.y, b.x, b.y);
|
|
if (value == 5 || value == 7 || value == 8)
|
|
line(a.x, a.y, d.x, d.y);
|
|
if (value == 6 || value == 9)
|
|
line(a.x, a.y, c.x, c.y);
|
|
}
|
|
}
|
|
|
|
class Metaball {
|
|
PVector position, velocity;
|
|
float radius;
|
|
|
|
Metaball() {
|
|
position = new PVector(random(width), random(height));
|
|
velocity = PVector.random2D();
|
|
velocity.setMag(random(minVelocity, maxVelocity));
|
|
radius = random(minRadius, maxRadius);
|
|
}
|
|
} |