Animazioni in Processing

Animazione in Processing

Di base, il linguaggio è molto semplice, consente di concentrare l’attenzione esclusivamente sulla grafica e sugli algoritmi da implementare.

Si parte da una schermata in cui l’origine degli assi è il vertice in alto a sinistra (l’asse delle ordinate e rivolto verso il basso). Tale sistema di riferimento può essere traslato e ruotato:

translate(x,y,y); //sposta l'origine degli assi in (x,y,z);

rotateX(a);//ruota il pino perpendicolare all'asse X di "a" radianti
rotateY(b);//ruota il pino perpendicolare all'asse Y di "b" radianti
rotateZ(c);//ruota il pino perpendicolare all'asse Z di "c" radianti
//n.b. rotazione antioraria

Una volta modificato il riferimento è possibile disegnare gli oggetti tramite parametri e coordinate.

Se si è interessati alla creazione di gif animate è sufficiente “prelevare” dei fotoframe in sequenza. La seguente funzione crea uno “screenshot” della schermata e la salva nella cartella ove è salvato lo sketch in questione:

saveFrame("Nome_immagine"+contatore+".jpg");

A seguire una carrellata di alcune animazioni. Carrellata “casuale”, ovvero tale articolo verrà aggiornato costantemente ogni volta che mi capita di creare qualche piccola animazione.

Elisse

Equazione ellisse con centro Xc e Yc:

\frac{(x-x_{c})^2}{a^2}+\frac{(Y-Y_{c})^2}{b^2} = 1

Parametrizzando le coordinate x e y si ha:

x = x_{C}+a cos(\theta)
y = y_{C}+b sin(\theta)

Si nota subito che se si volesse tracciare una circonferenza basta porre uguali l’asse maggiore e l’asse minore ( “a” e “b” in questo caso sono metà asse ), entrambi uguali al raggio.

Codice Processing:

float xc,yc,x,y;//centro ellisse
int a = 60,b=100;//parametri ellisse
float theta = 0; //parametro
float r = 20;//raggio pallina

void setup() {
  size(300,300);
  xc = width/2;//coordinata centro
  yc= height/2;//coordinata centro
}

void draw() {
  background(155);
  noFill();
  ellipse(xc, yc, 2*a,2*b);//disegna ellisse
  x = xc+a*cos(theta);
  y = yc+b*sin(theta);
  theta = theta+0.1;//incremento parametro 
  fill(0,0,100);
  circle(x,y,r);//disegna pallina
}

MOTO DELLA TERRA

Quello che segue è un esempio di ellisse in tre dimensioni (3D), che potrebbe rappresentare, ad esempio, un orbita. Infatti, ci si propone di “simulare” il moto relativo tra Terra e Luna.

nota: le proporzioni tra Terra e Luna non sono rispettate, come i rapporti tra le velocità angolari, per questioni di licenza artistica….

float x,y; //coordinate Luna

float theta = 0; //parametro
float rt = 60,rl =10;//raggio Terra e Luna
float dist = 100;//distanza Terra-Luna

PImage terra,luna,universo;
PShape mondo,moon;

void setup() {
  size(600,309,P3D);
  //creazione universo!!!!!!!!!
  universo = loadImage("universo.jpg");
  //creazione del Mondo!!!!!!!!!!!!!!!!!!!!!! XD
  noStroke();
  terra = loadImage("mondo.jpg");
  mondo = createShape(SPHERE, rt);//creazione shape "Mondo"
  mondo.setTexture(terra);
  //creazione Luna
  luna = loadImage("full_moon.jpg");
  moon = createShape(SPHERE, rl);//creazione shape "Luna"
  moon.setTexture(luna);
  
}

void draw() {
  background(universo);
  translate(width/2,height/2);//sposta l'origine degli assi al centro 

  rotateZ(PI/10);
  rotateY(theta);
  shape(mondo);//disegna la Terra
  //line(0,height,0,0,-height,0);//asse terrestre
  rotateY(-theta);
  theta = theta+0.03;//tempo 
  x = dist*cos(-4*theta);
  y = dist*sin(-4*theta);
  rotateX(PI/2);
  translate(x,y);
  rotateZ(theta);
  shape(moon);//disegna la Luna
  delay(70);
}

SPIRALE

Essendo il raggio della spirale parametrizzabile come segue:

r( \theta) = a + b \theta

Pertanto le coordinate saranno:

x = (a + b \theta )cos(\theta)
y = (a + b \theta )sin(\theta)
\theta > -\frac{a}{b}

float a=1,b=1,theta = 10;
float x,y;
float rs = 40;

float step = 0.3;
PShape pallina;

void setup() {
  size(400,400,P3D);
  pallina = createShape(SPHERE,rs);//crea oggetto pallina
}

void draw() {
  background(155);
  //sposta al centro il sistema di riferimento:
  translate(width/2,height/2); 
  //Equazioni parametriche della spirale:
  x = (a + theta*b)*cos(theta);
  y = (a + theta*b)*sin(theta);
  theta = theta +step;//incremento parametro 
  //sposta il sistema di riferimento in (x,y):
  translate(x,y);
  shape(pallina);//disegna la pallina
  //sposta il sistema di riferimento "nella parte opposta":
  translate(-2*x,-2*y);
  shape(pallina);//disegna la pallina  
}

SEGA CIRCOLARE

Si possono creare degli oggetti e dei gruppi di oggetti per poi semplificare la scrittura del codice, richiamandoli come oggetti unici:

PShape oggetto_1, oggetto_2, complessivo; 

Void setup(){
  size(450,450,P3D);
  oggetto_1 = createShape(); //creazione
  oggetto_1.beginShape(TRIANGLES); //inizio creazione (TRIANGOLO)
  oggetto_1.vertex(a,b,c); //vertici (per coordinate)
  oggetto_1.vertex(e,f,g);
  oggetto_1.vertex(h,i,l);
  oggetto_1.endShape();// fine creazione 

  oggetto_2 = createShape(); //creazione
  oggetto_2.beginShape(TRIANGLES); //inizio creazione (TRIANGOLO)
  oggetto_2.vertex(a2,b2,c2); //vertici (per coordinate)
  oggetto_2.vertex(e2,f2,g2);
  oggetto_2.vertex(h2,i2,l2);
  oggetto_2.endShape();// fine creazione 

 complessivo ==createShape(GROUP); //creazione gruppo di oggetti 
 complessivo.addChild(oggetto_1); //aggiungi ogetto_1 al "complessivo"
 complessivo.addChild(oggetto_2); //aggiungi ogetto_2 al "complessivo"

}


void draw(){
shape(complessivo); //disegna l'oggetto "complessivo"
}

Ecco un esempio:

PShape dente_sega,a,b,c,d; 

float L = 70,K = 40;;
float H = 40;
float M = 60;

int count =0;
int num_denti = 20;
float R;//raggio del disco 
float step=0;
void setup(){
  size(450,450,P3D);
  
  //CREAZIONE "DENTE DI SEGA" 
  a = createShape(); 
  a.beginShape(TRIANGLES);
  a.vertex(-L/2,0,-H/2);
  a.vertex(-L/2,0,H/2);
  a.vertex(L/2,0,0);
  a.endShape();
  
  b = createShape(); 
  b.beginShape(TRIANGLES);
  b.vertex(-L/2,0,-H/2);
  b.vertex(-L/2,0,H/2);
  b.vertex(-L/2,-M,0);
  b.endShape();
  
  c = createShape(); 
  c.beginShape(TRIANGLES);
  c.vertex(-L/2,0,-H/2);
  c.vertex(-L/2,-M,0);
  c.vertex(L/2,0,0);
  c.endShape();
  
  d = createShape(); 
  d.beginShape(TRIANGLES);
  d.vertex(-L/2,-M,0);
  d.vertex(L/2,0,0);
  d.vertex(-L/2,0,H/2);
  d.endShape();
   
  dente_sega =createShape(GROUP);
  dente_sega.addChild(a);
  dente_sega.addChild(b);
  dente_sega.addChild(c);
  dente_sega.addChild(d);
    
  R = K/((2*PI)/num_denti);//calcolo del raggio in funzione del
  //numero di denti
}


void draw(){
  background(155);
  translate(width/2,height/2);

  rotateX(PI/5);
  rotateY(step);
  rotateZ(-2*step);
  
  if (step >2*PI){
    step=0;
   //periodicità 2*PI
  }
  else{
    step = step + 0.1;
  }
  
  //CICLO FOR PER DISEGNARE LA CORONA DENTATA
  for (int i =1 ; i < num_denti +1; i = i+1) {
    rotateZ((2*PI)/num_denti);
    shape(dente_sega,0,-R);
   }
  
  delay(100);
}

SONAR

Quando viene tracciata una linea è possibile settarne alcuni parametri grafici, come spessore, colore ecc.

Il colore viene imposto tramite il modello RGB:

stroke(Reed,Green,Blue,opacità);

I parametri Red, Green e Blue (che vanno da 0 e 255), rappresentano la “quantità” di quel colore nel colore finale che si vuole ottenere. Esistono apposite tabelle che mostrano i valori di tali parametri sulla base del colore che si vuole ottenere.

float R,x,y,t = 0;
float alpha=255;
//int cont =0;
void setup() {
  size (400, 400); 
  R = 0.8*height;
}

void draw() {
  background(0);
  translate(width/2,height/2);
  stroke(98,245,31,alpha);
  noFill();
  strokeWeight(3);
  ellipse(0,0,R,R);
  ellipse(0,0,0.8*R,0.8*R);
  ellipse(0,0,0.6*R,0.6*R);
  ellipse(0,0,0.4*R,0.4*R);
  ellipse(0,0,0.2*R,0.2*R);
  line(0,R, 0,-R);
  line(R,R,-R,-R);
  line(-R,0,R,0);
  line(R,-R,-R,R);
  t = t + 0.09;
  strokeWeight(1);
  for (int i = 0; i <alpha; i = i+1) {
  x = 0.55*R*cos(t-i*0.01);
  y = 0.55*R*sin(t-i*0.01);
  stroke(98,245,31,alpha-i);
  line(0,0, x,y);
}
  //saveFrame("sonar"+cont+".jpg");
  //cont = cont+1;
  delay(20);
 
}

Matteo Gentileschi

Lascia un commento