作者 主题: p1222a_2012_cinderTutorialCh5Rewrite  (阅读 3842 次)

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
p1222a_2012_cinderTutorialCh5Rewrite
« 于: 十二月 23, 2012, 01:39:08 下午 »
前两天通读了Cinder 官网上前五章内容,然后用P5 重写了Robert Hodgin 超赞的例子。Tour 中原始的C++ 代码中包含很多的Magic Number,而Hodgin 本人也未在第五章内详细解释其中的一些,所以俺在Processing 代码中也保留了这些Magic Number。

此外,由于俺依然在使用1.5 版的Processing,所以有些地方写得比较累赘,而在新的2.0 beta 版中有很多内部已定义好的函数来取代俺很多累赘的代码。举其中的一个例子:

程序代码
float randRadiansLoc = random(2*PI);
PVector initLocOffset = new PVector(cos(randRadiansLoc)*5,sin(randRadiansLoc)*5);

上述代码的功能仅仅是为了得到一个随机的二维单位向量,之后乘以模数5。而在2.0 beta 版中则可以使用random2D() http://processing.org/reference/PVector_random2D_.html 来达成类似的效果。


via OpenP5

http://www.openprocessing.org/sketch/84094



程序代码
//Original code and idea by Robert Hodgin (http://roberthodgin.com/)
//Rewritten by Raven Kwok (aka Guo Ruiwen) in Processing
//p1222a_2012_cinderTutorialCh5Rewrite
/*
 
raystain@gmail.com
flickr.com/ravenkwok
vimeo.com/ravenkwok
weibo.com/ravenkwok
the-moor.blogbus.com
 
I read through the first five chapters of Cinder tutorial(http://libcinder.org/docs/v0.8.4/hello_cinder_chapter1.html) in the past two days, and rewrote Hodgin's amazing example of particle system in Processing.
*/
 
ParticleController pc;
boolean mouseDown;
PVector mouseLoc,mousePLoc,mouseVel;
PImage pattern;
 
void setup(){
  size(600,600);
  smooth();
  frameRate(30);
   
  stroke(255);
  ellipseMode(RADIUS);
   
  pattern = loadImage("bunny.jpg");
   
  pc = new ParticleController();
  mouseLoc = new PVector(0,0,0);
  mousePLoc = new PVector(0,0,0);
  mouseVel = new PVector(0,0,0);
}
 
void draw(){
  background(0);
  if(mouseDown) pc.addParticles(10,mouseLoc,mouseVel);
  pc.repulse();
  pc.update(pattern);
  pc.display();
}
 
void mouseDragged(){
  mouseMoved();
}
 
void mousePressed(){
  mouseDown = true;
}
 
void mouseReleased(){
  mouseDown = false;
}
 
void mouseMoved(){
  mousePLoc.set(pmouseX,pmouseY,0);
  mouseLoc.set(mouseX,mouseY,0);
  mouseVel = PVector.sub(mouseLoc,mousePLoc);
}

class Particle{
  PVector loc;
  PVector vel;
  PVector acc;
   
  float mass;
  float decay;
  float r;
  float rDest;
   
  Particle(PVector initLoc, PVector initVel){
    loc = initLoc;
    vel = initVel;
    acc = new PVector(0,0);
     
    decay = random(0.9,0.95);
    rDest = 5;
    r = 3;
    mass = sq(r)*0.0001+0.01;
  }
   
  void update(PImage pattern){
    vel.add(acc);
     
    float maxVel = r+0.0025;
    float velLength = sq(vel.mag())+0.1;
    if(velLength>sq(maxVel)){
      vel.normalize();
      vel.mult(maxVel);
    }
     
    loc.add(vel);
    vel.mult(decay);
    acc.set(0,0,0);
     
    if(loc.x>0 && loc.x<width-1 && loc.y>0 && loc.y<height-1){
      int index = floor(loc.x) + floor(loc.y)*pattern.width;
      rDest = brightness(pattern.pixels[index])/float(255)*3+0.5;
    }else{
      rDest = 0.1;
    }
     
    r = lerp(r,rDest,0.1);
    mass = sq(r)*0.0001+0.01;
  }
   
  void display(){
    strokeWeight(r*2);
    point(loc.x,loc.y);
  }
   
}

class ParticleController{
  ArrayList particles;
  int initialRandMag = 5;
   
  ParticleController(){
    particles = new ArrayList();
  }
   
  void addParticles(int amt, PVector mouseLoc, PVector mouseVel){
    for(int i=0;i<amt;i++){
      float randRadiansLoc = random(2*PI);
      PVector initLocOffset = new PVector(cos(randRadiansLoc)*5,sin(randRadiansLoc)*5);
      float randRadiansVel = random(2*PI);
      float randMagVel = random(1,5);
      PVector initVelOffset = new PVector(cos(randRadiansLoc)*randMagVel,sin(randRadiansLoc)*randMagVel);
       
      PVector initLoc = PVector.add(initLocOffset, mouseLoc);
      PVector initVel = PVector.add(initVelOffset, mouseVel);
       
      Particle additionalParticle = new Particle(initLoc, initVel);
      particles.add(additionalParticle);
    }
  }
   
  void repulse(){
    for(int i=0;i<particles.size();i++){
      Particle targetParticle1 = (Particle) particles.get(i);
      for(int j=i+1;j<particles.size();j++){
        Particle targetParticle2 = (Particle) particles.get(j);
        PVector dir = PVector.sub(targetParticle1.loc,targetParticle2.loc);
        float thres = (targetParticle1.r+targetParticle2.r)*5;
        if( dir.x > -thres && dir.x < thres && dir.y > -thres && dir.y < thres ){
          float magnitude = dir.mag();
          float distSqrd = pow(magnitude,3);
          if(distSqrd>0){
            float pushingForce = 1/distSqrd;
            dir.normalize();
            dir.mult(pushingForce);
            PVector accOffset1 = PVector.div(dir,targetParticle1.mass);
            PVector accOffset2 = PVector.div(dir,targetParticle2.mass);
            targetParticle1.acc.add(accOffset1);
            targetParticle2.acc.sub(accOffset2);
          }
        }
      }
    }
  }
   
  void update(PImage pattern){
    for(int i=0;i<particles.size();i++){
      Particle targetParticle = (Particle) particles.get(i);
      targetParticle.update(pattern);
    }
  }
   
  void display(){
    for(int i=0;i<particles.size();i++){
      Particle targetParticle = (Particle) particles.get(i);
      targetParticle.display();
    }
  }
}
« 最后编辑时间: 十二月 23, 2012, 01:42:44 下午 作者 RavenKwok »