class Line { // the Line object contains an array of Balls // and methods to addBalls, to moveBalls (spring), to drawBalls and generic run method Target t; Vector3D startLoc ; Vector3D target; int ballCount; ArrayList ballArray = new ArrayList(); // resizeable array boolean grow; Spring s = new Spring (0.1, .92, 9.9);// stiffness, damping, mass Spring ts = new Spring (0.1, .98, 8); int parentLinePos; int parentBallNum; float lineWidth ;//15;//.1; float maxWidth ;//= random (30) + 6; float lineExpandAmount;// = maxWidth / 100;//0.08; Attributes lineType; // store the attributes of the line // ////////////////////////////////////////////////////////////////////////// float blurInc;// = t.plantType.blurAmount; // distance between each shape float blurFraction; float _alpha;// = 280;//220;//180;//100;//180;//120; color fillColor; /// 'spin' controls the angle at which the line is drawn. 90 = flat (relative to the screen) float spin; float spinInc; float spinIncTarget;// =random (20);//7;// 7;// random (-6, 2); // target for unfolding lines //////////////////////////////////////////// float sineStart; float minWidth; float magDistort_top, magDistort_base; // elements to distort the top and base of the line float myAliveTime; // time allocated before decay starts ///////////////////////////////////////////////////////////////////// Line (Attributes atts, Target t_, int currentLine, int parentLine) { lineType = atts; t = t_; startLoc = new Vector3D (t.loc.x, t.loc.y); ballArray.add (new Ball (startLoc)); target = new Vector3D (t.loc.x, t.loc.y); grow = true; findParents (parentLine); //////// use Attributes lineType to define width and colour //// maxWidth = lineType.maxW;///// lineWidth = maxWidth*.8; // start the width as a fraction of the maxWithd lineExpandAmount = maxWidth / 500;//500;// set a speed to expand leaf // \ ////// SET COLOUR OF LINE //////// if (lineType.followParentColor) { fillColor = lineType.fillColor; // THIS IS AN ALTERNATIVE: TO BE ABLE TO MAKE LINE FOLLOW IT'S PARENT /// } else { fillColor = lineType.colorBlend (lineType.c1, lineType.c2, random (1)); // EACH LINE HAS IT'S OWN RANDOM VALUE/// } //////////////////////////////////////////////////// _alpha = t.plantType._alpha; blurInc = t.plantType.blurAmount; // distance between each shape blurFraction = t.plantType.blurAlphaFraction; setTargets(); ///////////////////////// sineStart = atts.sineStart; minWidth = atts.minWidth; magDistort_top = random (atts.shapeNoise);// random (maxWidth / 5); magDistort_base = 0;// random (atts.mChange); // set to 0 (base distortion not needed) /// myAliveTime = t.plantType.aliveTime; //myAliveTime = atts.aliveTime; } //////////////////////////////////////////////// void findParents (int parent) { // store the posistion of parent line in the line array. parentLinePos = parent; // save number of ball when line has been added if (parentLinePos > 0){ parentBallNum = l[parentLinePos].ballCount; } ///////////////////////////////////////////////////////// } void setTargets () { // set spin value // spinInc (segments of line) and spin (whole line) if (lineType.type == "petal") { //// SET DEVIATION TO A SET VALUE FOR ENTIRE FLOWER OR SET INDIVIDUALLTY FOR EACH PETAL spinIncTarget = lineType.parent.flowerDeviation; // DEVIATE ENTIRE FLOWER spinIncTarget += random (lineType.deviation); // DEVIATE INDIVIDUAL PETALS spinInc = 50;// amount by which each part of the petal is translated //spin = 90;//random (40, 90);//90;//50;// 90 angle (relative to screen) at which the petal is drawn (90 == 'flat') } ///////////////////////////////////////////// if (lineType.type == "leaf") { spinIncTarget = random (lineType.deviation); spinInc = spinIncTarget; //spin = 90; } /////////////////////////// if (lineType.type != "leaf" && lineType.type != "petal") { /// a stem or something else spinIncTarget = 0;//random (6); spinInc = 0; //spin = 90;// random (40, 100); // 90 } spin = lineType.angle; /// get the angle value from the Attributes and apply as spin (angle) 90 == 'flat' } ////////////////////////////// void run () { updateTarget (); makeAllBallsSpringy(); doIdecay(); if (grow == true) { addBalls (calcDist()); } if (parentLinePos > 0) { //print root co-ordiates // to check where the movement is.. ///CHECK IF THE BALL ARRAY OF THE PARENT IS BIGGER THAN THE PARENT BALL NUM // I.E. CHECK THAT THE PARENT BALL STILL EXISTS: IT HAS NOT BEEN REMOVED // if (parentBallNum < l[parentLinePos].ballArray.size()) { Ball pb = (Ball) l[parentLinePos].ballArray.get (parentBallNum); float px = pb.t.x; float py = pb.t.y; } } /////// CALL UNFURL () METHOD FOR CERTAIN 'TYPES' OF LINES if (lineType.type == "petal") { unfurl (); // rotate line around it's axis // does this slow the whole thing down ?? } /////////////////////////////////// calcBallWidth(); calcForces(); //////////////////////////////////// pushMatrix (); drawBalls (_alpha, 0); popMatrix (); // draw two petals (blur effect) // if (lineType.blur) { for (int i=1; i<=t.plantType.blurNum; i++) { pushMatrix (); drawBalls (_alpha*blurFraction*i, blurInc*i); // alpha and blur amount popMatrix(); } } ///////////////////////////////// } /////////////////////////////////// void updateTarget () { target.setXY (t.loc.x, t.loc.y); if (t.isAlive != true) { grow = false; } } /////////////////////////////////// Vector3D calcDist ( ) { // returns the distance between the target and the last ball Ball b = (Ball) ballArray.get (ballCount); Vector3D d = target.sub (target, b.loc); return d; } /////////////////////////////////// void addBalls (Vector3D d) { float totalDist = d.magnitude (); //// ADD BALLS //////// if (totalDist > MAX_DIST) { //// add a point and decrease totalDist ///// while (totalDist > MAX_DIST) { /// calculate the new position for new balls to be set at - based on angle // new ball to be postioned MaxDist from previous ball... float a = d.heading2D (); Ball b = (Ball) ballArray.get (ballCount); float x = (cos (a) * MAX_DIST) + b.loc.x; float y = (sin (a) * MAX_DIST) + b.loc.y; ballCount ++; ballArray.add ( new Ball (new Vector3D (x, y))); totalDist -= MAX_DIST; } } } /////////////////////////////////////////////////// void removeBall (Ball b) { ballArray.remove (b); } ///////////////////////////////////////////////// void removeLine () { // this does not remove the line from the array // just the balls from the line //// for (int i=ballCount-1; i>=0; i--) { Ball b = (Ball) ballArray.get (i); removeBall (b); ballCount--; } //if (parentLinePos == 0) { //addLine (); //} } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// void calcBallWidth () { // use the number of balls in the array to calculate each one's widht float w = sineStart; //SINESTART // this is the starting point of the sine curve (90 = the peak, 0 = the bottom) float magnitude_top = lineWidth; // reset magnitude for sine curve (top of leaf shape) float magnitude_base = lineWidth; // magnitude for base of line ////////////////////////////// for (int i=0; i<=ballCount; i++) { // when calculating widthInc CONVERT 'ballCount' into a FLOAT // so that the result is also a float // not an int // float widthInc = (lineType.sineLength / float (ballCount)); Ball b = (Ball) ballArray.get (i); /// CREATE A WIDTH FOR THE TOP AND THE BASE OF THE LINE (NON SYMETRICAL) b.w_top = (sin (radians (w))*magnitude_top)+minWidth;// this end value is important /// random (-1.5, 1.5); // add a 'pulse'// b.w_base = (sin (radians (w))*magnitude_base)+minWidth;// w += widthInc; ///// DISTORT THE SHAPE OF THE SINE CURVE //// for top edge and for base edge /// magnitude_top -= magDistort_top; /// DON'T NEED TO DISTORT TOP AND BASE (too much) // magnitude_base -= magDistort_base; //////////////////////////////////////////////// } ////////////////////////////////////////////////////////// if (lineWidth <= maxWidth) { grow ( ); } //if (lineWidth > maxWidth) { //if (t.plantType.decay) { // decay (); //spinIncTarget += t.plantType.refurlRate; // make it re- unfurl ! // } //spinIncTarget += t.plantType.refurlRate; // make it re- unfurl ! //} } //////////////////////////////////////////////// void grow () { lineWidth+= lineExpandAmount; // expand line } //////////////////////////////////////////// void decay () { spinIncTarget += t.plantType.refurlRate; // make it re- unfurl ! blurInc += t.plantType.blurRate; _alpha -= t.plantType.decayRate; //.8;//1.8 ;//.4; ///////////////////// if (_alpha < 0) { removeLine (); } } ////////////////////////// void doIdecay () { //t.plantType.aliveTime --; myAliveTime --; if (myAliveTime < 0 && t.plantType.decay) { decay (); } } ///////////////////////////////////////////// void calcForces () { // add a force to each of the balls.. // find a better way to add a force for each ball (relative to mouse position??? ) //Vector3D force = new Vector3D (0.1, 0.1, 0); //Vector3D mouse = new Vector3D (mouseX, mouseY, 0); if (inputSource == "CAMERA") { ////////////////////////////////////////////////////////////// //// create an array of forces //////////////////////////// Vector3D forceArray []; float accArray []; forceArray = new Vector3D [b.theBlobDetection.getBlobNb()]; accArray = new float [b.theBlobDetection.getBlobNb()]; //println ("force array length = " + forceArray.length); ////// fill the force array with vectors based on the soundsquare boxArray.. for (int i=0; i 2) { //Ball firstball = (Ball) ballArray.get (0); //firstball.drawBall(); Ball lastball = (Ball) ballArray.get (ballCount); lastball.drawBall (); } ///////////// } //////////////////////////////////////////// void makeAllBallsSpringy() { // cycle through of all of the balls (ballCount) in the arrayList (ballArray); // appy a tension between themm // create a one 'off' to make the apply a spring between the first ball and it's 'parent' if (parentLinePos > 0){ ///CHECK IF THE BALL ARRAY OF THE PARENT IS BIGGER THAN THE PARENT BALL NUM // I.E. CHECK THAT THE PARENT BALL STILL EXISTS: IT HAS NOT BEEN REMOVED // if (parentBallNum < l[parentLinePos].ballArray.size()) { Ball parent = (Ball) l[parentLinePos].ballArray.get (parentBallNum); Ball root = (Ball) ballArray.get (0); s.applySpring (root, parent, true); } } ////////////////////// for (int i=1 ; i<=ballCount; i++) { Ball b = (Ball) ballArray.get (i); Ball prevB = (Ball) ballArray.get (i-1); s.applySpring (b, prevB, true); // s.applySpring (prevB, b, true); Ball targetBall = new Ball (new Vector3D (b.t.x, b.t.y)); ts.applySpring (b, targetBall, false); } } }