-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
360 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Lenia Particle - B/W</title> | ||
|
||
<link rel="stylesheet" type="text/css" href="style.css"> | ||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js"></script> | ||
</head> | ||
<body> | ||
|
||
|
||
<script src="sketch-b-w.js"></script> | ||
</body> | ||
</html> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Lenia Particle - B/W</title> | ||
|
||
<link rel="stylesheet" type="text/css" href="style.css"> | ||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js"></script> | ||
</head> | ||
<body> | ||
|
||
|
||
<script src="sketch.js"></script> | ||
</body> | ||
</html> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
Based upon this Tutorial by Alexander Mordvintsev: | ||
Particle Lenia from scratch | ||
https://observablehq.com/@znah/particle-lenia-from-scratch | ||
The simulation shows Particle Lenia: the system of | ||
particles that move to minimize local energy of their | ||
interaction, leading to the formation of complex and | ||
diverse structures. | ||
https://arxiv.org/pdf/2305.16706 | ||
This version by Juan Carlos Ponce Campuzano | ||
12/Jul/2024 | ||
https://www.patreon.com/jcponce | ||
*/ | ||
|
||
let params = { | ||
mu_k: 4.0, sigma_k: 1.0, w_k: 0.022, | ||
mu_g: 0.6, sigma_g: 0.15, c_rep: 1.0, | ||
dt: 0.1 | ||
}; | ||
|
||
let point_n = 200; | ||
let points; | ||
let fields; | ||
let steps_per_frame; // Adjust this based on desired speed | ||
let randomCol; | ||
|
||
function setup() { | ||
createCanvas(windowWidth, windowHeight); | ||
points = init(new Float32Array(point_n * 2)); | ||
fields = { | ||
R_val: new Float32Array(point_n), | ||
U_val: new Float32Array(point_n), | ||
R_grad: new Float32Array(point_n * 2), | ||
U_grad: new Float32Array(point_n * 2) | ||
}; | ||
|
||
colorMode(RGB, 200, 200, 200, 200); | ||
fill(90) | ||
stroke(255); | ||
strokeWeight(0.05); | ||
|
||
steps_per_frame = int(random(3, 12)); | ||
|
||
randomCol = random(); | ||
|
||
//console.log(randomCol); | ||
} | ||
|
||
function draw() { | ||
for (let i = 0; i < steps_per_frame; ++i) step(); | ||
background(0, 30); | ||
translate(width / 2, height / 2); | ||
scale(width / 45.0); | ||
|
||
|
||
for (let i = 0; i < point_n; ++i) { | ||
let x = points[i * 2], y = points[i * 2 + 1]; | ||
let r = params.c_rep / (fields.R_val[i] * 5.0); | ||
|
||
ellipse(x, y, r * 2, r * 2); | ||
} | ||
} | ||
|
||
function init(points) { | ||
for (let i = 0; i < point_n; ++i) { | ||
points[i * 2] = (Math.random() - 0.5) * 12; | ||
points[i * 2 + 1] = (Math.random() - 0.5) * 12; | ||
} | ||
return points; | ||
} | ||
|
||
function add_xy(a, i, x, y, c) { | ||
a[i * 2] += x * c; | ||
a[i * 2 + 1] += y * c; | ||
} | ||
|
||
function compute_fields() { | ||
const { R_val, U_val, R_grad, U_grad } = fields; | ||
const { c_rep, mu_k, sigma_k, w_k } = params; | ||
R_val.fill(repulsion_f(0.0, c_rep)[0]); | ||
U_val.fill(peak_f(0.0, mu_k, sigma_k, w_k)[0]); | ||
R_grad.fill(0); | ||
U_grad.fill(0); | ||
|
||
for (let i = 0; i < point_n - 1; ++i) { | ||
for (let j = i + 1; j < point_n; ++j) { | ||
let rx = points[i * 2] - points[j * 2]; | ||
let ry = points[i * 2 + 1] - points[j * 2 + 1]; | ||
const r = Math.sqrt(rx * rx + ry * ry) + 1e-20; | ||
rx /= r; | ||
ry /= r; | ||
|
||
if (r < 1.0) { | ||
const [R, dR] = repulsion_f(r, c_rep); | ||
add_xy(R_grad, i, rx, ry, dR); | ||
add_xy(R_grad, j, rx, ry, -dR); | ||
R_val[i] += R; | ||
R_val[j] += R; | ||
} | ||
const [K, dK] = peak_f(r, mu_k, sigma_k, w_k); | ||
add_xy(U_grad, i, rx, ry, dK); | ||
add_xy(U_grad, j, rx, ry, -dK); | ||
U_val[i] += K; | ||
U_val[j] += K; | ||
} | ||
} | ||
} | ||
|
||
function repulsion_f(x, c_rep) { | ||
const t = Math.max(1.0 - x, 0.0); | ||
return [0.5 * c_rep * t * t, -c_rep * t]; | ||
} | ||
|
||
function fast_exp(x) { | ||
let t = 1.0 + x / 32.0; | ||
t *= t; | ||
t *= t; | ||
t *= t; | ||
t *= t; | ||
t *= t; | ||
return t; | ||
} | ||
|
||
function peak_f(x, mu, sigma, w = 1.0) { | ||
const t = (x - mu) / sigma; | ||
const y = w / fast_exp(t * t); | ||
return [y, -2.0 * t * y / sigma]; | ||
} | ||
|
||
function step() { | ||
const { R_val, U_val, R_grad, U_grad } = fields; | ||
const { mu_g, sigma_g, dt } = params; | ||
compute_fields(); | ||
let total_E = 0.0; | ||
for (let i = 0; i < point_n; ++i) { | ||
const [G, dG] = peak_f(U_val[i], mu_g, sigma_g); | ||
const vx = dG * U_grad[i * 2] - R_grad[i * 2]; | ||
const vy = dG * U_grad[i * 2 + 1] - R_grad[i * 2 + 1]; | ||
add_xy(points, i, vx, vy, dt); | ||
total_E += R_val[i] - G; | ||
} | ||
return total_E / point_n; | ||
} | ||
|
||
function mousePressed() { | ||
params.mu_k = random(1.0, 5.0); | ||
params.sigma_k = random(0.1, 2.0); | ||
params.w_k = random(0.01, 0.07); | ||
params.mu_g = random(0.1, 1.0); | ||
params.sigma_g = random(0.05, 0.3); | ||
params.c_rep = random(0.1, 2.0); | ||
// Debugg | ||
//console.log(params); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/* | ||
Based upon this Tutorial by Alexander Mordvintsev: | ||
Particle Lenia from scratch | ||
https://observablehq.com/@znah/particle-lenia-from-scratch | ||
The simulation shows Particle Lenia: the system of | ||
particles that move to minimize local energy of their | ||
interaction, leading to the formation of complex and | ||
diverse structures. | ||
https://arxiv.org/pdf/2305.16706 | ||
This version by Juan Carlos Ponce Campuzano | ||
12/Jul/2024 | ||
https://www.patreon.com/jcponce | ||
*/ | ||
|
||
let params = { | ||
mu_k: 4.0, sigma_k: 1.0, w_k: 0.022, | ||
mu_g: 0.6, sigma_g: 0.15, c_rep: 1.0, | ||
dt: 0.1 | ||
}; | ||
|
||
let point_n = 200; | ||
let points; | ||
let fields; | ||
let steps_per_frame; // Adjust this based on desired speed | ||
let randomCol; | ||
|
||
function setup() { | ||
createCanvas(windowWidth, windowHeight); | ||
points = init(new Float32Array(point_n * 2)); | ||
fields = { | ||
R_val: new Float32Array(point_n), | ||
U_val: new Float32Array(point_n), | ||
R_grad: new Float32Array(point_n * 2), | ||
U_grad: new Float32Array(point_n * 2) | ||
}; | ||
|
||
colorMode(RGB, 200, 200, 200, 200); | ||
noStroke(); | ||
|
||
steps_per_frame = int(random(3, 12)); | ||
|
||
randomCol = random(); | ||
|
||
//console.log(randomCol); | ||
} | ||
|
||
function draw() { | ||
for (let i = 0; i < steps_per_frame; ++i) step(); | ||
background(0, 30); | ||
translate(width / 2, height / 2); | ||
scale(width / 45.0); | ||
strokeWeight(0.1); | ||
|
||
for (let i = 0; i < point_n; ++i) { | ||
let x = points[i * 2], y = points[i * 2 + 1]; | ||
let r = params.c_rep / (fields.R_val[i] * 5.0); | ||
|
||
if(randomCol < 0.3){ | ||
fill((i)/point_n* 200, 70, 100); | ||
} else if(0.3 <= randomCol && randomCol < 0.6) { | ||
fill(90, 80, (i)/point_n* 200); | ||
} else { | ||
fill(20, (i)/point_n* 200, 180); | ||
} | ||
|
||
ellipse(x, y, r * 2, r * 2); | ||
} | ||
} | ||
|
||
function init(points) { | ||
for (let i = 0; i < point_n; ++i) { | ||
points[i * 2] = (Math.random() - 0.5) * 12; | ||
points[i * 2 + 1] = (Math.random() - 0.5) * 12; | ||
} | ||
return points; | ||
} | ||
|
||
function add_xy(a, i, x, y, c) { | ||
a[i * 2] += x * c; | ||
a[i * 2 + 1] += y * c; | ||
} | ||
|
||
function compute_fields() { | ||
const { R_val, U_val, R_grad, U_grad } = fields; | ||
const { c_rep, mu_k, sigma_k, w_k } = params; | ||
R_val.fill(repulsion_f(0.0, c_rep)[0]); | ||
U_val.fill(peak_f(0.0, mu_k, sigma_k, w_k)[0]); | ||
R_grad.fill(0); | ||
U_grad.fill(0); | ||
|
||
for (let i = 0; i < point_n - 1; ++i) { | ||
for (let j = i + 1; j < point_n; ++j) { | ||
let rx = points[i * 2] - points[j * 2]; | ||
let ry = points[i * 2 + 1] - points[j * 2 + 1]; | ||
const r = Math.sqrt(rx * rx + ry * ry) + 1e-20; | ||
rx /= r; | ||
ry /= r; | ||
|
||
if (r < 1.0) { | ||
const [R, dR] = repulsion_f(r, c_rep); | ||
add_xy(R_grad, i, rx, ry, dR); | ||
add_xy(R_grad, j, rx, ry, -dR); | ||
R_val[i] += R; | ||
R_val[j] += R; | ||
} | ||
const [K, dK] = peak_f(r, mu_k, sigma_k, w_k); | ||
add_xy(U_grad, i, rx, ry, dK); | ||
add_xy(U_grad, j, rx, ry, -dK); | ||
U_val[i] += K; | ||
U_val[j] += K; | ||
} | ||
} | ||
} | ||
|
||
function repulsion_f(x, c_rep) { | ||
const t = Math.max(1.0 - x, 0.0); | ||
return [0.5 * c_rep * t * t, -c_rep * t]; | ||
} | ||
|
||
function fast_exp(x) { | ||
let t = 1.0 + x / 32.0; | ||
t *= t; | ||
t *= t; | ||
t *= t; | ||
t *= t; | ||
t *= t; | ||
return t; | ||
} | ||
|
||
function peak_f(x, mu, sigma, w = 1.0) { | ||
const t = (x - mu) / sigma; | ||
const y = w / fast_exp(t * t); | ||
return [y, -2.0 * t * y / sigma]; | ||
} | ||
|
||
function step() { | ||
const { R_val, U_val, R_grad, U_grad } = fields; | ||
const { mu_g, sigma_g, dt } = params; | ||
compute_fields(); | ||
let total_E = 0.0; | ||
for (let i = 0; i < point_n; ++i) { | ||
const [G, dG] = peak_f(U_val[i], mu_g, sigma_g); | ||
const vx = dG * U_grad[i * 2] - R_grad[i * 2]; | ||
const vy = dG * U_grad[i * 2 + 1] - R_grad[i * 2 + 1]; | ||
add_xy(points, i, vx, vy, dt); | ||
total_E += R_val[i] - G; | ||
} | ||
return total_E / point_n; | ||
} | ||
|
||
function mousePressed() { | ||
params.mu_k = random(1.0, 5.0); | ||
params.sigma_k = random(0.1, 2.0); | ||
params.w_k = random(0.01, 0.07); | ||
params.mu_g = random(0.1, 1.0); | ||
params.sigma_g = random(0.05, 0.3); | ||
params.c_rep = random(0.1, 2.0); | ||
// Debugg | ||
//console.log(params); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
html, | ||
body { | ||
margin: 0; | ||
height: 100%; | ||
overflow: hidden; | ||
} |