• fullscreen
  • FlagSim.pde
  • collision.pde
  • subs.pde
  • surfaceForces.pde
  • windForces.pde
  • int numa = 40;
    int numb = 21;
    int elementWidth = 10;
    PVector[][] X = new PVector[numa][numb];
    PVector[][] V = new PVector[numa][numb];
    PVector[][] F = new PVector[numa][numb];
    float k = 0.1;
    float c = 0.01;
    float gravity = 0.01;
    float wind = 0.01;
    PVector[] constraint = new PVector[numb];
    boolean flagBool = false;
    PImage flag;
    void setup(){
      size(520,400,P3D);
      flag = loadImage("flag (2).jpg");
      reset();
      setupConstraint();
    }
    void draw(){
      background(0);
      physics();
      lights();
      drawSheet();
    }
    void keyPressed(){
      if (key==' '){
        if (flagBool == false){
          flag = loadImage("flag (3).jpg");
          flagBool = true;
        }else{
          flag = loadImage("flag (2).jpg");
          flagBool = false;
        }
      }
    }
    
    int[][] slate = new int[numa*numb][2];
    int nodeCount = 0;
    void collisionSetup(){
      for (int i=0; i<numa; i++){
        for (int j=0; j<numb; j++){
          slate[nodeCount][0] = i;
          slate[nodeCount][1] = j;
          nodeCount++;
        }
      }
    }
    boolean hasBeen = false;
    void collide(){
      float bumpRad = elementWidth * 1.5;
      if (hasBeen == false){
        collisionSetup();
        hasBeen = true;
      }
      for (int i=1; i<nodeCount; i++){
        for (int j=0; j<i; j++){
          if (testAdjacency(i,j)){
            PVector dx = PVector.sub(X[slate[j][0]][slate[j][1]],
                                     X[slate[i][0]][slate[i][1]]);
            if (abs(dx.x)<bumpRad){
              if (abs(dx.y)<bumpRad){
                if (abs(dx.z)<bumpRad){
                  if (dx.mag()<bumpRad){
                    float delta = (bumpRad - dx.mag()) * k;
                    dx.normalize();
                    F[slate[j][0]][slate[j][1]].add(PVector.mult(
                                                      dx,delta));
                    F[slate[i][0]][slate[i][1]].sub(PVector.mult(
                                                      dx,delta));
                  }
                }
              }
            }
          }
        }
      }
    }
    boolean testAdjacency(int i,int j){
      int a = slate[i][0];
      int b = slate[i][1];
      int c = slate[j][0];
      int d = slate[j][1];
      boolean val = false;
      if (((abs(a-c)<2)&&(abs(b-d)<2))==false){
        val = true;
      }
      return val;
    }
    
    void reset(){
      for (int i=0; i<numa; i++){
        for (int j=0; j<numb; j++){
          X[i][j] = new PVector(elementWidth * (i)+width/8,
                                elementWidth * (j)+height/8,
                                random(-0.1,0.1));
          V[i][j] = new PVector();
        }
      }
    }
    void physics(){
      for (int i=0; i<numa; i++){
        for (int j=0; j<numb; j++){
          F[i][j] = new PVector(0.0,gravity,0.0);
        }
      }
      for (int i=0; i<numa; i++){
        for (int j=0; j<numb; j++){
          normalForce(i,j);
          windForce(i,j);
        }
      }
      collide();
      for (int i=0; i<numa; i++){
        for (int j=0; j<numb; j++){
          V[i][j].add(F[i][j]);
          X[i][j].add(V[i][j]);
        }
      }
      useConstraint();
    }
    void drawSheet(){
      noStroke();
      for (int j=0; j<numb-1; j++){
        beginShape(TRIANGLE_STRIP);
        texture(flag);
        float xtweek = 1.02;
        float ytweek = 1.05;
        for (int i=0; i<numa; i++){
          vertex(X[i][j].x, X[i][j].y, X[i][j].z,
                 elementWidth*i*xtweek, elementWidth*j*ytweek);
          vertex(X[i][j+1].x, X[i][j+1].y, X[i][j+1].z,
                 elementWidth*i*xtweek, elementWidth*(j+1)*ytweek);      
        }
        endShape();
      }
    }
    void setupConstraint(){
      for (int j=0; j<numb; j++){
        constraint[j] = new PVector(X[0][j].x,
                                    X[0][j].y,
                                    X[0][j].z);
      }
    }
    void useConstraint(){
      for (int j=0; j<numb; j++){
        X[0][j] = new PVector(constraint[j].x,
                              constraint[j].y,
                              constraint[j].z);
        V[0][j] = new PVector();
      }
    }
    
    void normalForce(int i, int j){
      int a = i+1;
      int b = j;
      force2(i,j,a,b,1);
      a = i-1;
      b = j;
      force2(i,j,a,b,1);
      a = i;
      b = j+1;
      force2(i,j,a,b,1);
      a = i;
      b = j-1;
      force2(i,j,a,b,1);
      a = i+1;
      b = j+1;
      force2(i,j,a,b,pow(2,0.5));
      a = i-1;
      b = j+1;
      force2(i,j,a,b,pow(2,0.5));
      a = i+1;
      b = j-1;
      force2(i,j,a,b,pow(2,0.5));
      a = i-1;
      b = j-1;
      force2(i,j,a,b,pow(2,0.5));
      boolean jump = true;
      if (jump == true){
        int jumper = 2;
        a = i+jumper;
        b = j;
        force2(i,j,a,b,jumper);
        a = i-jumper;
        b = j;
        force2(i,j,a,b,jumper);
        a = i;
        b = j+jumper;
        force2(i,j,a,b,jumper);
        a = i;
        b = j-jumper;
        force2(i,j,a,b,jumper);
        a = i+jumper;
        b = j+jumper;
        force2(i,j,a,b,jumper*pow(2,0.5));
        a = i-jumper;
        b = j+jumper;
        force2(i,j,a,b,jumper*pow(2,0.5));
        a = i+jumper;
        b = j-jumper;
        force2(i,j,a,b,jumper*pow(2,0.5));
        a = i-jumper;
        b = j-jumper;
        force2(i,j,a,b,jumper*pow(2,0.5));
      }
    }
    void force2(int i,int j,int a,int b,float distMult){
      float eW2 = elementWidth * distMult;
      if ((a>=0)&&(b>=0)&&(a<numa)&&(b<numb)){
        PVector dx = PVector.sub(X[a][b], X[i][j]);
        float bufferWidth = 0.01 * elementWidth;
        float delta = 0;
        if ((dx.mag() < eW2 - bufferWidth/2)||
            (dx.mag() > eW2 + bufferWidth/2)){
          delta = abs(dx.mag() - eW2)
                       - bufferWidth/2;
        }
        int sighn = 0;
        if (dx.mag() < eW2 - bufferWidth/2){
          sighn = -1;
        }else if (dx.mag() > eW2 + bufferWidth/2){
          sighn = +1;
        }
        dx.normalize();
        float v1 = dx.dot(V[i][j]);
        float v2 = dx.dot(V[a][b]);
        float dv = v2 - v1;
        float fmag = k * delta * sighn + c * dv;
        PVector df = PVector.mult(dx,fmag);
        F[i][j].add(df);
        F[a][b].sub(df);
      }
    }
    
    void windForce(int i,int j){
      // NOTE: vector selected based on right hand rule
      int a = i+1;
      int b = j;
      int c = i;
      int d = j+1;
      wind2(i,j,a,b,c,d);
      a = i;
      b = j+1;
      c = i-1;
      d = j;
      wind2(i,j,a,b,c,d);
      a = i-1;
      b = j;
      c = i;
      d = j-1;
      wind2(i,j,a,b,c,d);
      a = i;
      b = j-1;
      c = i+1;
      d = j;
      wind2(i,j,a,b,c,d);
    }
    void wind2(int i,int j,int a,int b,int c,int d){
      PVector windV = new PVector(wind,0.0,0.0);
      if ((a>=0)&&(b>=0)&&(a<numa)&&(b<numb)){
        if ((c>=0)&&(d>=0)&&(c<numa)&&(d<numb)){
          PVector ab = PVector.sub(X[a][b], X[i][j]);
          PVector cd = PVector.sub(X[c][d], X[i][j]);
          PVector un = ab.cross(cd);
          un.normalize();
          float fmag = un.dot(windV);
          F[i][j].add(PVector.mult(un,fmag));
        }
      }
    }
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement


    Asher Salomon
    bejoscha
    6 Apr 2010
    Nice. Thanks for sharing.
    Axel Duch
    19 Aug 2010
    This is... flagberghasting.
    Where are you from? If you don't mind me asking...
    You need to login/register to comment.