Week06: Midterm Project

 

I developed my previous assignment for my midterm project. This time, I made particles consist more complicated form – human face – and applied the same repeller and recovering force.
I downloaded the following picture from the internet, modified it to a greyscale image and used it for making the particle system.

The code for this sketch is like below:

[sketch.js]

let den = [1, 2, 4, 5, 8, 10];
let denIdx = 2;
let img;
let ps;
let repeller;

//let particles = [];

function preload() {
 img = loadImage('test.png');
}

function setup() {
  createCanvas(680, 520);
  pixelDensity(1);
  
  
  image(img, 0, 0);
  
  ps = new ParticleSystem(den[denIdx]);
  repeller = new Repeller(width, height);

}

function draw() {
  background(255);

  ps.applyRepeller(repeller);
  ps.applyRecover();
  
  repeller.update();
  
  ps.display();
  ps.update();
                       
                       
}

[particlesystem.js]

class ParticleSystem {
  
  constructor(den) {
    
    this.d = den;
    this.particles = [];
    
    loadPixels();
  
    for(let y=0; y<height; y+=this.d) {
      for(let x=0; x<width; x+=this.d) {

        let idx = [];

        for(let i=0; i<(this.d*this.d); i+=this.d) {

          idx[i] = 4*(x+(y+this.d)*width);

          for(let j=1; j<this.d; j++) {
            idx[i+j] = idx[i]+4*j;
          }

        }

        let avgCol=0;

        for(let i=0; i<idx.length; i++) {
          avgCol += pixels[idx[i]];
        }
        avgCol = avgCol/idx.length;

        if(avgCol<255) {
          this.particles.push(new Particle(x, y, avgCol, this.d));
        }

      }
    }

    console.log(this.particles.length);
    
  }
  
  display() {
    
    for(let particle of this.particles) {
      particle.display();
    }
    
  }
  
  // A function to apply a force to all Particles
  applyForce(f) {
    for(let particle of this.particles){
      particle.applyForce(f);
    }
  }

  applyRepeller(r) {
    for(let particle of this.particles){
      
      let force = r.repel(particle);
      particle.applyForce(force);
    }
  }
  
  applyRecover() {
    for(let particle of this.particles) {
      particle.recover();
    }
  }
  
  update() {
    for (let particle of this.particles) {
      particle.update();
    }
  }
}

[particle.js]

class Particle {
  
  constructor(x, y, c, d) {
    
    this.acceleration = createVector();
    this.velocity = createVector()
    this.velocity.mult(0.5);
    this.position = createVector(x, y);
    this.origin = createVector(x, y);

    this.c = c;
    this.d = d;
  }
  
  applyForce(force) {
    this.acceleration.add(force);
  }
  
  // Method to update position
  update() {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
    this.acceleration.mult(0);
    this.velocity.mult(0.95);
  }

  recover() {
    let dir = p5.Vector.sub(this.origin, this.position);
    let m = dir.mag();
    
    if(m>2) {
      dir.normalize();
      dir.mult(2*(m/40));
      this.position.add(dir);
    }
    else {
      this.position = this.origin.copy();
    }
  }
  
  display() {
    noStroke();
    fill(this.c);
    rect(this.position.x, this.position.y, this.d/2, this.d/2);
  }
  
}

[repeller.js]

class Repeller {
  
  constructor(x, y) {
    this.power = 100;
    this.position = createVector(x, y);
  }
  
  update() {
  	this.position.x = mouseX;
    this.position.y = mouseY;
  }
  
  repel(p) {
    let dir = p5.Vector.sub(this.position, p.position);
    let dm = dir.mag();
    dir.normalize();
    if(dm < 100) {
      let force = -1 * this.power / (dm*dm);
      force = constrain(force, -20, -1);
      dir.mult(force);
      return dir;
    }
    else return 0;
  }
    

}

Since the sketch gets too slow when a particle’s size is 1×1, I set the default particle size as 4×4. However, users can change it by pressing   ↑ and ↓ arrow keys: ↑ key for increasing the resolution and ↓ key for decreasing it.

Following is the result:

Leave a Reply

Your email address will not be published. Required fields are marked *