Segment[] segs; float[] start={400,400,0}; int numSegs=20; int segW=50; int segH=15; int segsDampMax=200; int segsDampInc=segsDampMax/numSegs; float[][][] segCoordsL; //segs, side (L,R), corner(top, bottom), x/y float[][][] segCoordsR; //segs, side (L,R), corner(top, bottom), x/y void setup(){ size(800,800); background(50); buildSegs(); } void buildSegs(){ float[] start={400,400,0}; segs=new Segment[numSegs]; segCoordsL=new float[numSegs][2][2]; segCoordsR=new float[numSegs][2][2]; segs[0]=new Segment(segW,segH,100,true); segs[0].setStart((int)start[0], (int)start[1], start[2]); start=segs[0].getEnd(); for (int i=1; i=0; i--){ b=segs[i].rotateS(a); a=b; } } void mouseDragged(){ if (mouseXpmouseX) propegate(-PI/35); } /* This bit trakcs the current pressed mouse position calculates the angle from the current trunk end, and then calulats the difference from its own angle. It attempt to converge on this angle over time (dampened) and passes that target up to other segments with steadily more dampening. *************************************************/ void mouseMoved(){ float[] last={0,0,0}; float a; float b; last=segs[segs.length-1].getEnd(); for (int i=segs.length-1; i>=0; i--){ a=segs[i].getAngle((int)last[0], (int)last[1],mouseX, mouseY); //if(isInsideTrunk()) a=a+PI; b=segs[i].angleDiff(a); segs[i].rotateS((b-PI/2)/((segs.length-i)*segsDampInc+segsDampInc)); segCoordsL[i]=segs[i].getLeftSide(); segCoordsR[i]=segs[i].getRightSide(); } } boolean isInsideTrunk(){ float[] xya=segs[0].getStart(); float[] xya2=segs[segs.length-1].getEnd(); float hypTrunk=sqrt(pow(xya2[0]-xya[0],2)+pow(xya2[1]-xya[1],2)); float hypMouse=sqrt(pow(mouseX-xya[0],2)+pow(mouseY-xya[1],2)); return hypMousethis.maxFlexA){ excess=this.flexA-this.maxFlexA; this.flexA=maxFlexA; } if(this.flexA<-this.maxFlexA){ excess=this.flexA+this.maxFlexA; this.flexA=-maxFlexA; } } return excess; } float getAngle(int sx, int sy, int ex, int ey){ return atan2(ey-sy,ex-sx); } float angleDiff(float ang){ return ang-(startA+flexA); } }