xxxxxxxxxx
// --- Interfaccia Parametri ---
// Modifica i parametri qui sotto per cambiare l'animazione:
const params = {
canvasWidth: 960, // Larghezza della finestra
canvasHeight: 960, // Altezza della finestra
nodeAmount: 5, // Numero totale di particelle dinamiche
nodeSize: 3, // Dimensione delle particelle dinamiche
logoNodeSize: 2, // Dimensione delle particelle del logo
logoDensity: 10, // Densità delle particelle nel logo (più basso = più nodi)
friction: 0.3, // Attrito (valore tra 0.5 e 1 per equilibrio)
minSpeed: 20, // Velocità minima delle particelle
maxSpeed: 80, // Velocità massima delle particelle
forceMultiplier: 0.015, // Intensità della forza tra nodi nel grafo Gabriel
connectionThreshold: 390, // Distanza massima per connettere i nodi nel grafo
connectionMinDistance: 30, // Distanza minima per connettere i nodi nel grafo
lineThickness: 0.1, // Spessore delle linee del grafo
nodeColors: ["rgb(193,255,0)", "rgb(193,255,0)"], // Colori disponibili per i nodi dinamici
gravityOptions: [ // Gravità per ogni tipo di particella
{ x: 0, y: 0 }, // Nessuna gravità
{ x: 0, y: -0.45 }, // Gravità verso l'alto
],
backgroundColor: "rgb(0,0,0)", // Colore dello sfondo
graphLineColor: "rgb(255,255,255)", // Colore delle linee nel grafo Gabriel
seed: 5, // Numero per generare configurazioni casuali
};
// --- Fine Interfaccia Parametri ---
let nodeArray = [];
const logoNodes = [];
let logoImage;
function preload() {
logoImage = loadImage("unolab-logo-png.png"); // Sostituisci con il nome della tua PNG
}
function setup() {
randomSeed(params.seed); // Inizializza il seed per generare configurazioni casuali
createCanvas(params.canvasWidth, params.canvasHeight);
// Estrai particelle dal logo
extractLogoParticles();
// Genera le particelle dinamiche
while (nodeArray.length < params.nodeAmount) {
nodeArray.push(node());
}
}
function draw() {
background(params.backgroundColor);
// Aggiorna e disegna le particelle dinamiche
nodeArray.forEach((node) => {
node.update();
node.handleEdge();
});
// Aggiorna e disegna le particelle del logo
logoNodes.forEach((node) => {
node.update();
node.show();
});
// Disegna il grafo di Gabriel
gabrielGraph();
// Mostra le particelle dinamiche
nodeArray.forEach((node) => node.show());
}
function extractLogoParticles() {
logoImage.loadPixels();
for (let y = 0; y < logoImage.height; y += params.logoDensity) {
for (let x = 0; x < logoImage.width; x += params.logoDensity) {
const index = (x + y * logoImage.width) * 4;
const r = logoImage.pixels[index];
const g = logoImage.pixels[index + 1];
const b = logoImage.pixels[index + 2];
const alpha = logoImage.pixels[index + 30];
if (r < 50 && g < 50 && b < 50 && alpha > 0) {
const pos = createVector(
map(x, 0, logoImage.width, 0, width),
map(y, 0, logoImage.height, 0, height)
);
logoNodes.push(logoNode(pos));
}
}
}
}
function logoNode(anchorPos) {
const pos = anchorPos.copy();
const vel = createVector(0, 0);
const acc = createVector(0, 0);
const update = () => {
const springForce = p5.Vector.sub(anchorPos, pos).mult(0.05);
acc.add(springForce);
vel.add(acc);
vel.mult(params.friction);
pos.add(vel);
acc.set(0, 0);
};
const show = () => {
noStroke();
fill(params.nodeColors[0]);
ellipse(pos.x, pos.y, params.logoNodeSize);
};
return {
pos,
update,
show,
};
}
function node() {
const pos = createVector(random(width), random(height));
let vel = createVector(
random(-params.maxSpeed, params.maxSpeed),
random(-params.maxSpeed, params.maxSpeed)
);
// Assicuriamoci che la velocità sia sempre almeno pari a minSpeed
if (vel.mag() < params.minSpeed) {
vel = vel.normalize().mult(random(params.minSpeed, params.maxSpeed));
}
const acc = createVector(0, 0);
const type = random(params.gravityOptions);
const handleEdge = () => {
if (pos.x < 0) {
pos.x = width;
pos.y = random(height);
} else if (pos.x > width) {
pos.x = 0;
pos.y = random(height);
}
if (pos.y < 0) {
pos.y = height;
pos.x = random(width);
} else if (pos.y > height) {
pos.y = 0;
pos.x = random(width);
}
};
const update = () => {
vel.add(acc);
vel.limit(params.maxSpeed);
pos.add(vel);
vel.mult(params.friction);
acc.set(type.x, type.y);
};
const show = () => {
noStroke();
fill(random(params.nodeColors));
ellipse(pos.x, pos.y, params.nodeSize);
};
return {
pos,
acc,
type,
handleEdge,
update,
show,
};
}
const gabrielGraph = () => {
stroke(params.graphLineColor);
strokeWeight(params.lineThickness); // Regola lo spessore delle linee
nodeArray.forEach((dynamicNode) => {
logoNodes.forEach((logoNode) => {
const difference = dynamicNode.pos.copy().sub(logoNode.pos);
const distance = difference.mag(); // Calcola la distanza
// Connetti solo se la distanza è tra il minimo e il massimo
if (
distance > params.connectionMinDistance &&
distance < params.connectionThreshold
) {
line(dynamicNode.pos.x, dynamicNode.pos.y, logoNode.pos.x, logoNode.pos.y);
}
});
});
};