• fullscreen
  • Img2Spring.pde
  • ShapeSpringVII.pde
  • SpringClass.pde
  • SpringShapes.pde
  • class Vert
    {
      PVector pos;
      boolean used=false;
      Vert(float x, float y){pos = new PVector(x,y);}
    }
    
    Spring Img2Spring(PImage img, int startVertex,boolean makeClosed, int everyNth)
    {
      // create ArrayList of black pixels
      int count=0;
       Vert V;
       ArrayList Points,sorted;
       img.loadPixels();
       Points = new ArrayList();
       for(int j=0;j<img.height;j++) for (int i=0;i<img.width;i++)
       {
         if (img.pixels[j*img.width+i]==color(0))         Points.add(new Vert(i,j));
       }
      sorted = new ArrayList();
      sorted = SortVert(Points,startVertex);
      Spring S;
      S = new Spring();
      PVector center=new PVector(mouseX-img.width/2,mouseY-img.height/2);
        
      V = (Vert) sorted.get(0);
      S.firstPoint(PVector.add(center,V.pos));
      for (int i=1;i<sorted.size()-1;i++)
      {
        V = (Vert) sorted.get(i);
        if(i%everyNth==0) S.addPoint(PVector.add(center,V.pos));
      }
      V = (Vert) sorted.get(sorted.size()-1);
      S.lastPoint(PVector.add(center,V.pos),makeClosed);
      return S;
    }
    
    ArrayList SortVert(ArrayList Unsorted, int start)
      {
        Vert V,VT,BV;
        ArrayList Sorted;
        float mind,d;
        Sorted = new ArrayList();
        V = (Vert) Unsorted.get(start);
        Sorted.add(V);
        V.used=true;
        while (Sorted.size()<Unsorted.size())
          {
            mind=100000000;
            V=(Vert) Sorted.get(Sorted.size()-1);
            BV=V;
            for (int i=0;i<Unsorted.size();i++)
              {
                VT = (Vert) Unsorted.get(i);
                if (!VT.used)
                  {
                    d = V.pos.dist(VT.pos);
                    if (d<mind)
                      {
                        mind=d;
                        BV=VT;
                      }
                  }
              }
             BV.used=true;
             Sorted.add(BV);
          }
        return Sorted;
      }
    
    // Base scirpt and Spring-Physics 
    // By Asher Salomon 2010
    // AsherSalomon@gmail.com
    // see openprocessing.com
    
    // The script was then modified by Bejoscha to allow collisions.
    
    int num = 2000;          // Biggest number of Points per Spring
    
    int whichOnes;
    ArrayList sprs;
    Spring S;
    PGraphics buffer;
    int count=0;
    boolean showBuffer=false;
    boolean collide=true;
    boolean drawFill=true;
    boolean pause=false;
    boolean useGravity=true;
    
    float step=0.01;
    
    void setup() {
      size(500, 400,JAVA2D);
      sprs = new ArrayList();
      smooth();
      buffer = createGraphics(width,height,JAVA2D);
      //buffer.smooth();
      buffer.background(0);
    }
    
    void draw() 
    {
      background(230);
      if (!pause)
        {
        if (sprs.size()>0){
          if (drawing) whichOnes=sprs.size()-1;
          else         whichOnes=sprs.size();
           for (int j=0; j<whichOnes; j++)
            {
              S = ( Spring ) sprs.get(j);
              if (collide)  S.drawBuffer(S.VertexDraw,S.LineDraw,drawFill,true);
              S.Tick();
              if (collide)  S.drawBuffer(S.VertexDraw,S.LineDraw,drawFill,false);
            }
          }
        }
      buffer.beginDraw();
      buffer.background(0);
      if (sprs.size()>0){
        for (int j=0; j<sprs.size(); j++){
           S = ( Spring ) sprs.get(j);
           S.draw(S.VertexDraw,S.LineDraw,drawFill);
        }
        if (collide)   for (int j=0; j<sprs.size(); j++)
                      {
                         S = ( Spring ) sprs.get(j);
                         S.drawBuffer(S.VertexDraw,S.LineDraw,drawFill,false);
                      }
      }
      buffer.endDraw();
      if (showBuffer) set(0,0,buffer);
    }
    
    boolean drawing = false;
    void mousePressed() {
      if (drawing == false){
        if (mouseButton == LEFT){
            S = new Spring(color(10+random(245),10+random(245),10+random(245)));
            if (!useGravity) S.gravity=0;
            sprs.add( S );
            S.firstPoint(new PVector(mouseX,mouseY));
            drawing = true;
          }
        }
        if (mouseButton == RIGHT){
          if (sprs.size()>0){
            for (int j=0; j<sprs.size(); j++){
              S = ( Spring ) sprs.get(j);
              S.testGrab();
            }
          }
        }
    }
    void mouseDragged() {
      if (drawing) 
      {
        S = ( Spring ) sprs.get(sprs.size()-1);
        S.addPoint(new PVector(mouseX,mouseY));
      }
    }
    
    boolean cleared = true;
    void mouseReleased() {
      if (mouseButton == LEFT){
        if (drawing) {
          S = ( Spring ) sprs.get(sprs.size()-1);
          S.lastPoint(new PVector(mouseX,mouseY),false);
          S.CloseGap(10);
          drawing = false;
        }
      }
      if (mouseButton == RIGHT){
        if (sprs.size()>0){
          for (int j=0; j<sprs.size(); j++){
          S = ( Spring ) sprs.get(j);
          S.hold = false;
          }
        }
      }
    }
    
    void keyReleased(){
      Spring S2;
      PImage img;
      int len,wid,wind;
      switch (key)
      {
        case ' ':
        sprs = new ArrayList();
        break;
        case 'c':
        collide=!collide;
        break;
        case 'p':
        pause=!pause;
        break;
        case '1':   
        S2 = makeCircle(50,80);
        S = makeCircle(50,40);
        S.CopyToStore();
        S.dX=S2.dX;
        S.CopyToNew();
        S.warping=true;
        sprs.add(S);
        break;
        case '2':
        len = round ( random(50,200) );
        wid = round ( random(10,40) );
        wind = round (random(4,20) );
        S2 = makeSpringSpring(new PVector(mouseX,mouseY),new PVector(mouseX,mouseY+len),wind,wid,10);
        S =   makeSpringSpring(new PVector(mouseX,mouseY),new PVector(mouseX,mouseY+len/3),wind,wid,10);
       // S2 = makeSpringSpring(new PVector(mouseX,mouseY),new PVector(mouseX,mouseY+150),10,25,10);
       // S =   makeSpringSpring(new PVector(mouseX,mouseY),new PVector(mouseX,mouseY+30),10,25,10);
        S.CopyToNew();
        S.dX=S2.dX;
        S.CopyToStore();
        S.warping=true;
        sprs.add(S);
        break;
        
        case '3':
          img = loadImage("H.gif");
          S = Img2Spring(img,0,true,3);
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          S.Shift(-85,5);
          S.warping=true;
          S.warplevel=1;
          sprs.add(S);
          img = loadImage("A.gif");
          S = Img2Spring(img,0,true,3);
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          S.warping=true;
          S.warplevel=1;
          sprs.add(S);
          img = loadImage("P.gif");
          S = Img2Spring(img,0,true,3);
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          S.Shift(80,5);
          S.warping=true;
          S.warplevel=1;
          sprs.add(S);
          S = Img2Spring(img,0,true,3);
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          S.Shift(155,5);
          S.warping=true;
          S.warplevel=1;
          sprs.add(S);
          img = loadImage("Y.gif");
          S = Img2Spring(img,0,true,3);
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          S.Shift(225,5);
          S.warping=true;
          S.warplevel=1;
          sprs.add(S);
        break;
        case '4':
        
          collide=false;
          img = loadImage("Happy.gif");
          S = Img2Spring(img,100,false,5);
          S.Scale(0.8);
          S.VertexDraw=2;
          S.LineDraw=1;
          S.lineCol=color(230);
          S.gravity=0;
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          sprs.add(S);
          img = loadImage("Birthday.gif");
          S = Img2Spring(img,20,false,3);
          S.Shift(0,100);
          S.gravity=0;
          S.Scale(0.8);
          S.VertexDraw=2;
          S.LineDraw=1;
          S.lineCol=color(230);
          S.CopyToNew();
          S2 = makeCircle(S.numUsed,35);
          S.dX=S2.dX;
          S.CopyToStore();
          sprs.add(S);
        break;
        
        case 'a':
          for (int j=0; j<sprs.size(); j++){
          S = ( Spring ) sprs.get(j);
          if (S.hold)
             {
             S.anchored=!S.anchored;
             S.anchorID=S.held;
             S.anchor=new PVector(mouseX,mouseY);
             }
          }
        break;
        case '+':
          for (int j=0; j<sprs.size(); j++)
          {
            S = ( Spring ) sprs.get(j);
            if (S.hold)S.Scale(1.1);
          }
        break;
        case '-':
          for (int j=0; j<sprs.size(); j++)
          {
            S = ( Spring ) sprs.get(j);
            if (S.hold)S.Scale(0.9);
          }
        break;
        case 'f':
          for (int j=0; j<sprs.size(); j++)
          {
            S = ( Spring ) sprs.get(j);
            if (S.hold)S.FreezeToNew();
          }
        break;
        case 'x':
        for (int i=0;i<sprs.size();i++)
          {
            S = (Spring) sprs.get(i);
            S.warping=true;
            if (S.warplevel==0) S.warplevel=1;
            else S.warplevel=0;
          }
        break;
        case 'g':
          useGravity=!useGravity;
          for (int j=0; j<sprs.size(); j++)
          {
          S = ( Spring ) sprs.get(j);
          if (useGravity) S.gravity = 0.00001;
          else S.gravity=0;
          }
        break;
        case 's':
          for (int j=0; j<sprs.size(); j++)
          {
          S = ( Spring ) sprs.get(j);
          if (S.hold) if (!S.closed) S.straighten=!S.straighten;
          }
        break;
      }
    }
    
    class Spring{
      int pCount=0;
      float k = 0.025;
      float c = 0.2;
      float I = 100;
      float kw = 20.0;
      float cw = 0.02;
      float damp=0.5;
      float gravity = 0.00001;
      int VertexDraw=0;
      int LineDraw=1;
      
      int iterations = 175;
      int numUsed = 0;
      PVector[] X = new PVector[num];
      PVector[] dX = new PVector[num];
      PVector[] dXold = new PVector[num];
      PVector[] dXnew = new PVector[num];
      PVector[] V = new PVector[num];
      PVector[] F = new PVector[num];
      float[] phi = new float[num];
      float[] omega = new float[num];
      float[] tork = new float[num];
      boolean closed = false;
      boolean straighten=false;
      boolean warping=false;
      boolean anchored=false;
      int anchorID=0;
      PVector anchor;
      float warplevel=0;
      color fillCol;
      color vertCol;
      color lineCol;
      color idCol;
      void CreateSpring(color IDc){
        idCol = IDc;
        for (int i=0; i<num; i++) {
          X[i] = new PVector();
          V[i] = new PVector();
          F[i] = new PVector();
          dX[i] = new PVector();
          dXold[i]= new PVector();
          dXnew[i]= new PVector();
        }
        fillCol = color(int(random(0,255)),
                    int(random(0,255)),
                    int(random(0,255)));
        vertCol = color(255,0,0);
        lineCol = color(0,0,0);
        anchor=new PVector(0,0);
      }
      boolean hold = false;
      int held;
      Spring(){CreateSpring(color(255,random(0,255),random(0,255)));}
      Spring(color IN){CreateSpring(IN);}
      
      void physics() {
    
          for (int i=0; i<=numUsed; i++) {
            F[i].y += gravity;
          }
          int ione = 1;
          if (closed==true){ione=0;}
          for (int i=ione; i<=numUsed; i++) {
            int linked = i-1;
            if (i==0){linked=numUsed;}
            PVector io = new PVector(cos(phi[i]), sin(phi[i]));
            PVector jo = new PVector(-sin(phi[i]), cos(phi[i]));
            PVector delta = PVector.sub(X[i], X[linked]);
            PVector deltaPrime = new PVector();
            deltaPrime.x = delta.x * io.x + delta.y * io.y;
            deltaPrime.y = delta.x * jo.x + delta.y * jo.y;
            PVector ddX = PVector.sub(deltaPrime, dX[linked]);
            PVector GPrime = PVector.mult(ddX, -k);
            PVector G = new PVector();
            G.x = GPrime.x * io.x + GPrime.y * jo.x;
            G.y = GPrime.x * io.y + GPrime.y * jo.y;
            G.sub(PVector.mult(PVector.sub(V[i], V[linked]), c));
            F[i].add(G);
            F[linked].sub(G);
            // The principal of equivilent systems
            // may be helpfull for this model.
            PVector curl = delta.cross(G);
            float Gw = (phi[i] - phi[linked]) * kw;
            float dW = (omega[i] - omega[linked]) * cw;
            tork[i] -= Gw + curl.z - dW;
            tork[linked] += Gw - curl.z - dW;
          }
          // BoarderCollsion
          for (int i=0; i<=numUsed; i++) 
          {
            if (X[i].x < 0) {
              F[i].x += (-X[i].x) * k - V[i].x * c;
              F[i].y -= V[i].y * c /3;
            }
            if (X[i].x > width) {
              F[i].x -= (X[i].x - width) * k + V[i].x * c;
              F[i].y -= V[i].y * c /3;
            }
            if (X[i].y < 0) {
              F[i].y += (-X[i].y) * k - V[i].y * c;
              F[i].x -= V[i].x * c /3;
            }
            if (X[i].y > height-1) {
              F[i].y -= (X[i].y - height+1) * k + V[i].y * c;
              F[i].x -= V[i].x * c /3;
            }
          }
            // BufferCollision
            
            for (int i=0; i<=numUsed; i++) 
                {
                PVector PV = new PVector(round(X[i].x+V[i].x+F[i].x),round(X[i].y+V[i].y+F[i].y));
                color testCol = buffer.get(round(PV.x),round(PV.y));
                if ((testCol!=idCol)&&(testCol!=color(0))&&(PV.x>=0)&&(PV.y>=0)&&(PV.x<width)&&(PV.y<height))
                {   
                  // find collision spring
                  Spring CS=this;
                   for (int j=0; j<sprs.size(); j++)
                       {
                        CS = ( Spring ) sprs.get(j);
                        if (CS.CheckSpringCol(testCol)) break;
                       }
                  // find closest 2 vertices of collision spring
                  int j[]=CS.FindClosestVertex(PV,2);
                  // calculate collision direction vectors
                  PVector C1 = PVector.sub(CS.X[j[0]],PV);
                  PVector C2 = PVector.sub(CS.X[j[1]],PV);
                  C1.normalize();
                  C2.normalize();
                  // calculate transferred velocity vectors
                  float strength=C1.dot(V[i]);
                  C1.mult(strength*damp);
                  strength=C2.dot(V[i]);
                  C2.mult(strength*damp);
                  
                  
                  V[i].mult(-1*damp);  
                  CS.V[j[0]].add(C1);
                  CS.V[j[1]].add(C2);
                  F[i].mult(-1*damp);
                }
               }
               
          if (hold) {
            PVector M = new PVector();
            M.x = mouseX;
            M.y = mouseY;
            PVector fromMouse = PVector.sub(X[held], M);
            F[held].sub(PVector.mult(fromMouse, k));
            F[held].sub(PVector.mult(V[held], c));
          }
          if (anchored) 
            {
            PVector fromA = PVector.sub(X[anchorID], anchor);
            F[anchorID].sub(PVector.mult(fromA, k));
            F[anchorID].sub(PVector.mult(V[anchorID], c));
            }
            
          for (int i=0; i<=numUsed; i++) {
            V[i].add(F[i]);
            
            F[i].x = 0;
            F[i].y = 0;
            X[i].add(V[i]);
            omega[i] += tork[i] / I;
            tork[i] = 0;
            phi[i] += omega[i];
            omega[i] *= 0.999;
            if (i>0) {phi[i] = constrain(phi[i],
                                         phi[i-1] - PI / 2,
                                         phi[i-1] + PI / 2);}
            omega[i] = constrain(omega[i], -PI/256, PI/256);
          }
        }
      void Tick()
        {
            
          for (int ic=0;ic<iterations;ic++) this.physics();
          if (warping)
            {
              for (int i=0; i<=numUsed; i++) 
                {
                  dX[i].x=lerp(dXold[i].x,dXnew[i].x,warplevel);      // WORK HERE
                  dX[i].y=lerp(dXold[i].y,dXnew[i].y,warplevel);
                }
            }
          if (straighten) for (int i=1; i<=numUsed; i++) 
            {
              PVector Old = new PVector(dX[i].x,dX[i].y);
              PVector DD = new PVector(dX[i-1].x,dX[i-1].y);
              DD.normalize();
              float P = abs(PVector.dot(DD,dX[i]));
              if (P<=0.1) P=0.1;
              float L = dX[i].mag();
              DD.mult(P);
              dX[i].sub(DD);
              if (dX[i].mag()>P/100) dX[i].mult(0.7);
              dX[i].add(DD);
              dX[i].normalize();
              dX[i].mult(L);
              dXnew[i]=new PVector(dX[i].x,dX[i].y);
            }
    
        }
      
      int[] FindClosestVertex(PVector pos,int rank)
        {
          float d=width*height;
          float d2;
          int[] best;
          best = new int[rank];
          for (int j=0;j<rank;j++) best[j]=0;
          for (int i=0; i<=numUsed; i++) 
            {
              d2=PVector.dist(X[i],pos);
              if (d2<=d)
                {
                  for (int j=rank-1;j>0;j--)
                    {
                      best[j]=best[j-1];
                    }
                  d=d2;
                  best[0]=i;
                }
            }
          return best;
        }
      
    
     
      boolean CheckSpringCol(color in)
        {
          if (in==idCol) return true;
          else return false;
        }
      void CopyToStore()
        {
          for (int i=0; i<=numUsed; i++) 
          {
            dXold[i].x = dX[i].x;
            dXold[i].y = dX[i].y;
          }
        }
      void CopyToNew()
        {
          for (int i=1; i<=numUsed; i++)
           {
             dXnew[i].x = dX[i].x;
             dXnew[i].y = dX[i].y;
           }
        }  
      void Scale(float sc)
      {
        for (int i=0; i<=numUsed; i++) dX[i].mult(sc);
        CopyToNew();
        warplevel=1;
        warping=true;
       }
      void FreezeToNew()
        {
          for (int i=1; i<=numUsed; i++)
             dXnew[i-1] = PVector.sub(X[i],X[i-1]);
        }
      void CopyFromStore()
        {
          for (int i=0; i<=numUsed; i++) 
          {
            dX[i].x = dXold[i].x;
            dX[i].y = dXold[i].y;
          }
        }
      void CopyFromNew()
        {
          for (int i=1; i<=numUsed; i++)
           {
             dX[i].x = dXnew[i].x;
             dX[i].y = dXnew[i].y;
           }
        }
        
      void draw(int drawPointsStr, int drawConnectStr, boolean drawFill)
      {    
        if ((closed)&&(drawFill)) fill(fillCol, 150);
        else noFill();
        if (drawConnectStr>0)
        {
          stroke(lineCol);
          if (hold) strokeWeight(drawConnectStr*3);
          else strokeWeight(drawConnectStr);
          beginShape();
          for (int i=0; i<=numUsed; i++) {
            vertex(X[i].x, X[i].y);
          }
          if (closed==false){
            endShape();
          }else{
            endShape(CLOSE);
          }
          strokeWeight(1);
        }
        if (drawPointsStr>0)
        {
          stroke(vertCol);
          strokeWeight(drawPointsStr);
          for (int i=0; i<=numUsed; i++)  point(X[i].x, X[i].y);
          strokeWeight(1);
        }
      }
      void drawBuffer(int drawPointsStr, int drawConnectStr, boolean drawFill, boolean Clear)
      {    
        color c;
        if (Clear) c=color(0);
        else c=color(idCol);
        if ((closed)&&(drawFill)) buffer.fill(c);
        else buffer.noFill();
        if (drawConnectStr>0)
        {
          buffer.stroke(c);
          buffer.strokeWeight(drawConnectStr);
          buffer.beginShape();
          for (int i=0; i<=numUsed; i++) {
            buffer.vertex(X[i].x, X[i].y);
          }
          if (closed==false){
            buffer.endShape();
          }else{
            buffer.endShape(CLOSE);
          }
          buffer.strokeWeight(1);
        }
        if (drawPointsStr>0)
        {
          buffer.stroke(c);
          buffer.strokeWeight(drawPointsStr);
          for (int i=0; i<=numUsed; i++)  buffer.point(X[i].x, X[i].y);
          buffer.strokeWeight(1);
        }
      }
    
      void firstPoint(PVector NewPoint)
        {
          numUsed = 0;
          X[numUsed] = NewPoint;
          V[numUsed].x = 0;
          V[numUsed].y = 0;
        }
      void addPoint(PVector NewPoint)
      {
        if (numUsed < num-1) {
          numUsed++;
          X[numUsed] = NewPoint;
          V[numUsed].x = 0;
          V[numUsed].y = 0;
          dX[numUsed-1] = PVector.sub(X[numUsed], X[numUsed-1]);
        }
      }
      void lastPoint(PVector NewPoint, boolean Makeclosed){ 
        addPoint(NewPoint);
        dX[numUsed] = PVector.sub(X[0], X[numUsed]);
        closed = Makeclosed;
        drawing = false;
        cleared = false;
        CopyToStore();
        CopyToNew();
      } 
    
      void Shift(PVector SVec)
        {
        for (int i=0; i<=numUsed; i++) X[i].add(SVec);
        }
    
      void Shift(float x,float y)
        {
        Shift(new PVector(x,y));
        }
        
      void CloseGap(int MaxGap)
      {
        if (dX[numUsed].mag()<MaxGap) closed = true;
        else closed=false;
      }
      
      boolean testGrab(){
        for (int i=0; i<=numUsed; i++) {
          PVector M = new PVector();
          M.x = mouseX;
          M.y = mouseY;
          PVector fromMouse = PVector.sub(X[i], M);
          if (fromMouse.mag() < 5) {
            hold = true;
            held = i;
          }
        }
        boolean val = false;
        if (hold==true){val = true;}
        return val;
      }
    }
    
    Spring makeSpringSpring(PVector SpringStart, PVector SpringEnd, int Windings,int len, int joints)
    {
       Spring S;
       PVector AddVec;
       float angle;
       float rotAngle;
       int Points = Windings*joints;
       S = new Spring();
       PVector Point=SpringStart;
       // Calculate Spring geometry defined by vector Start->End, the number of windings, and the length of windings
         AddVec = PVector.sub(SpringEnd,SpringStart);
         float h = AddVec.mag()/Windings;
         angle = degrees(atan(abs(h)/len));
         rotAngle= PVector.angleBetween(AddVec,new PVector(1,0));
         if (AddVec.y>0) rotAngle=TWO_PI-rotAngle;  
         
         
       AddVec = new PVector(len*cos(radians(angle)),(-1)*len*sin(radians(angle)));  //-1 because y is defined DOWNWARDS on the screen!    
       
       for (int i=0;i<Points;i+=joints) 
       {
                 AddVec.normalize();
            AddVec.mult(len/joints);
         for(int j=1;j<=joints;j++)
         {
            Point = new PVector(Point.x-AddVec.x*sin(rotAngle)-AddVec.y*cos(rotAngle),Point.y+AddVec.y*sin(rotAngle)-AddVec.x*cos(rotAngle)); 
            if ((i!=0) || (j>(joints/2))) S.addPoint(Point);
            else    S.firstPoint(Point);
         }
         AddVec.x*=-1;
       }
       AddVec.normalize();
       AddVec.mult(len/joints);
       for(int j=1;j<joints/2;j++)
         {
            Point = new PVector(Point.x-AddVec.x*sin(rotAngle)-AddVec.y*cos(rotAngle),Point.y+AddVec.y*sin(rotAngle)-AddVec.x*cos(rotAngle)); 
            S.addPoint(Point);
         }
            Point = new PVector(Point.x-AddVec.x*sin(rotAngle)-AddVec.y*cos(rotAngle),Point.y+AddVec.y*sin(rotAngle)-AddVec.x*cos(rotAngle)); 
       S.lastPoint(Point,false);
       return S;
    }
    
    Spring makeRandomSpring(int Points)
      {
        Spring S;
        Points = max(3,Points);
        S = new Spring();
        PVector Point = new PVector(mouseX,mouseY);
        S.firstPoint(Point);
        PVector AddVec= new PVector(random(0,5),random(0,5));
        for (int i=1;i<Points-1;i++)
          {
            S.addPoint(Point);
            float len = AddVec.mag();
            AddVec.normalize();
            float angle;
            angle= PVector.angleBetween(AddVec,new PVector(1,0)); 
            if (AddVec.y>0) angle=TWO_PI-angle;  
            angle+=random(0,PI/(Points*0.3));
            AddVec = new PVector(len*cos(angle),(-1)*len*sin(angle));  //-1 because y is defined DOWNWARDS on the screen!      
            Point = new PVector(Point.x+AddVec.x,Point.y+AddVec.y);   
          }
        S.lastPoint(Point,false);
        S.CloseGap(10);
        return S;
      }
      
    Spring makeCircle(int Points, float radius)
      {
        Spring S;
        S = new Spring();
        PVector center=new PVector(mouseX,mouseY);
        PVector R=new PVector(1,0);
        
        S.firstPoint(PVector.add(center,PVector.mult(R,radius)));
        for (int i=1;i<Points;i++) 
          {
            R=new PVector(cos(i*TWO_PI/Points),sin(i*TWO_PI/Points));
            if (i<Points-1) S.addPoint(PVector.add(center,PVector.mult(R,radius)));
            else S.lastPoint(PVector.add(center,PVector.mult(R,radius)),false);
          }
        S.closed=true;
        return S;
      }
    
    

    code

    tweaks (0)

    about this sketch

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

    license

    advertisement

    bejoscha

    Shape Spring V

    Add to Faves Me Likey@! 12
    You must login/register to add this sketch to your favorites.

    A further development of the Shape Spring sketch now featuring better colissions, shape-warping and image recognition.

    bejoscha
    16 Apr 2010
    This sketch is a futher development based on the script of Asher Salomon. I have now improved collisions such that some momentum is transferred to the other particle. It is still a "fudged" collision-model and not real physics, but it works okay most of the time.
    I've also implemented a method of turning black-white images into spring-shapes. In this demo it is used to create letter-shaped springs. It works (obviously) best with line-drawings.
    I've also added the possibilty to warp spring-shapes between two of their shapes, and I've added some pre-shaped spring objects.
    bejoscha
    16 Apr 2010
    Controlls:
    - left mouse drag: draw new springs
    - right click drag: modify/select springs (indicated by thicker outline)

    &lt;c&gt; - turn collision mode on/off
    &lt;space&gt; - clear screen
    &lt;p&gt; - pause/unpause
    &lt;a&gt; - "anchor/release" selected spring at given mouse position
    &lt;+&gt; - enlarge selected spring
    &lt;-&gt; - shrink selected spring
    &lt;g&gt; - turn gravity on/off
    &lt;s&gt; - make (non-closed) spring straighten itself
    &lt;x&gt; - swap between two spring-shapes

    &lt;1&gt; - add a ball
    &lt;2&gt; - add a 'spring'
    &lt;3&gt; - Add H A P P Y springs
    &lt;4&gt; - Add Happy Birthday springs (turns collisions off)
    bejoscha
    16 Apr 2010
    Some fun things to try out:

    -&gt; Fill the box with several "balls" (pressing &lt;1&gt;) and then let them become "big" by pressing &lt;x&gt; to swap to their second shape.

    -&gt; Fill the screen with "Happy" letters and swap them with &lt;x&gt;

    -&gt; create some springs with &lt;2&gt; and let them expand/shrink with &lt;x&gt;

    -&gt; create a ball or any shape and right click drag it to "deform" it. While still selected, press &lt;F&gt; to freeze it's current shape. Change the spring's shape by pressing &lt;x&gt;

    -&gt; create a non- closed spring, select it (drag with right mouse button) and press &lt;s&gt; to have it stretch itself straight. Use the &lt;x&gt; key to toggle the shape. This works very well with the "Happy Birthday" springs created by &lt;4&gt;

    dotlassie
    17 Apr 2010
    It's getting better and better :)
    bitcraft
    17 Apr 2010
    welcome to wobble world :-)
    TweakingKnobs
    23 Apr 2010
    Awesome !!


    Huwuuuuuuuuuuuuuu!!!
    TweakingKnobs
    23 Apr 2010
    hey , it wont run on my mac, it says

    syntax error, maybe missing a semi colon at his part :

    Spring Img2Spring(PImage img, int startVertex,boolean makeClosed, int everyNth)

    but even if i put a semicolon at the end of that line it still says the same.

    any ideas ?


    thanx !
    bejoscha
    25 Apr 2010
    Not really, sorry. I'm using Processing 1.1 on a Vista machine, but what you've described sounds rather like a cop&paste parsing error than something in the actual code...
    Asher Salomon
    25 Apr 2010
    I created a collision detection algorithm which made it possible to do spring collisions. Very fast and well behaved. Check it out.
    wow, awesome!

    But, I've got one little problem... I downloaded the sketch and tried to but my own images inside... Somehow there appears an error:
    IndexOutOfBoundsException: Index: 0, Size: 0
    (I am kinda' new with processing)

    I've got no idea how i can fix this problem...
    I tried different kind of images with filled or outlined fonts, also different data files or sizes...

    Maybe you could help me out... ?

    thx a lot!
    bejoscha
    7 Jan 2011
    How did you try to put your images inside? The images have to be black-white (monochrome) so that the algorithm can pick up the pixels. The error you get indicated that "no" pixel has been detected (thus the array of pixels has the size 0 and the sketch crashes at a later point because I'm not checking against this case.)
    Eduardo Obieta
    22 Mar 2012
    wow nice¡¡¡¡
    bejoscha
    22 Mar 2012
    Thanks.
    You need to login/register to comment.