processingで新体操のリボン

f:id:peroon:20090804203318j:image
Auther: hTaka様のコードです。
私が理解用のコメントを加えています。


フォントを加えれば動くコードは以下の通りです。

//コメント
//text( string, x, y, z )で空間に文字を書くのはおもしろそう。
//online変数
//screen.width変数
//key = ' ' => space
//ArrayList
//beginShape(QUAD_STRIP);
//nf()



import processing.opengl.*;

/**
Strip<br />
Auther: hTaka<br />
<br />
mouse move and draw strips!
<br />
Made for Processing 118
*/

float worldRotY = 0;
Strip s;
float targetX,targetY;
PFont font;
boolean pointIndex = false;
boolean polyFill = true;

//static public void main(String args[]) {
//  PApplet.main(new String[] { "--present", "--display=1", "strip_OPENGL" });
//}

void setup(){
  size( 800, 800*9/16, OPENGL );
  //size(screen.width,(screen.width)*9/16,OPENGL);
  //size(800,450,OPENGL);
  background(255);
  frameRate(60);
  textMode(MODEL);//default
  textAlign(LEFT);
  font = loadFont("Georgia-24.vlw");
  textFont(font,5);
  camera(0,0,500,0,0,0,0,1,0);
  s = new Strip(1500);
}

//ok
void draw(){
  background(255);  //毎回白に塗りつぶしている!
  rotateX(PI/180*(targetY-height/2)*0.1);
  rotateZ(PI/180*(targetX-width/2)*0.05);
  rotateY(PI/180*worldRotY);
  stroke(128);
  line(0,100,0,0,-100,0);  //x,y,z軸で回転させた後に、回転軸(黒)を描く
  worldRotY +=2;
  if(worldRotY >= 360){
    worldRotY = 0;
  }
  targetX += (mouseX - targetX)/10;  //減衰しながらmouse(x,y)に向かう
  targetY += (mouseY - targetY)/10;
  s.update();
  s.draw();
}

//ok
void keyPressed(){
  if(!online){//not on web-browser
    if(key == ' '){
      String outTifName ="strip"+"_"+nf(year(),4)+nf(month(),2)+nf(day(),2)+"_"+nf(hour(),2)+nf(minute(),2)+nf(second(),2)+".jpg";
      save(outTifName);
    }
  }
  //true, falseのスイッチングの書き方
  if(key == 'p'){
    if(pointIndex){
      pointIndex = false;
    }else{
      pointIndex = true;
    }
  }
  if(key == 'f'){
    if(polyFill){
      polyFill = false;
    }else{
      polyFill = true;
    }
  }
}


class Strip{
  int numOfParticles;
  ArrayList particles;  //dynamic object array
  Strip(int num){
    this.numOfParticles = num;
    particles = new ArrayList();
  }

  void update(){
    if(particles.size()<numOfParticles){
      particles.add(new Particle(
                                 (targetX-width/2)*cos(PI/180*worldRotY), //中心から離れるほど大きな円運動
                                  targetY-height/2,
                                 (targetX-width/2)*sin(PI/180*worldRotY)));
    }else{
      particles.remove(0);
      particles.add(new Particle(
                                 (targetX-width/2)*cos(PI/180*worldRotY),
                                  targetY-height/2,
                                 (targetX-width/2)*sin(PI/180*worldRotY)));
    }
  }
  
  void draw(){
    if(polyFill){
      noStroke();
    }else{
      stroke(0);
      noFill();
    }
    
      beginShape(QUAD_STRIP);
      for(int i=0;i<particles.size();i++){
        Particle p = (Particle) particles.get(i);
        if(polyFill){
          fill(0,80,100,255*i/particles.size());  //古いparticleほど薄く
        }
        vertex(p.x,p.y,p.z);
        vertex(p.xw,p.yw,p.zw);
      }
      endShape();
      
      //ok
      if(pointIndex){
        fill(0,80,100);
        for(int i=0;i<particles.size();i++){
          Particle p = (Particle) particles.get(i);
          pushMatrix();
          translate(p.x,p.y,p.z);
          rotateY(-1*PI/180*worldRotY);  //text faces to me
          text(i,0,0,0);  //(0,0,0) is coordinate
          popMatrix();
        }
      }
  }
}

class Particle{
  float x,y,z;
  float xw,yw,zw;//width?
  Particle(float x,float y,float z){
    this.x = x;
    this.y = y;
    this.z = z;
    this.xw = 5 * cos(PI/180*worldRotY) + this.x;
    this.zw = 5 * sin(PI/180*worldRotY) + this.z;
    this.yw = 5 + this.y;
  }
}