class Leaf { // Node management Particle rootNode; int nodeCount = 4; Particle[] fixedNodes; Particle[] springNodes; Spring[] connections; // between fixed & spring nodes // Position management float baseX; float baseY; boolean isLeft; // Miscellaneous float nodeDistance = random(40, 120); float rootSize = 24; Point[] polygon; // Constructors /////////////////////////////////////////////////////////////// Leaf() { this((random(1) > 0.5) ? 0 : width, random(height / 4, 3 * height / 4)); } Leaf(float x, float y) { baseX = x; baseY = y; // Create the fixed root node rootNode = ps.makeParticle(5, baseX, baseY, 0); rootNode.makeFixed(); // Create the other nodes: // - FixedNodes, which are the 'base' node position, and // - SpringNodes, which are the movable bits. // Tie the fixed and spring nodes together with springs. // Join the nodes together using springs again. float deltaX; isLeft = baseX < width / 2; if (isLeft) { deltaX = nodeDistance; } else { deltaX = -nodeDistance; } fixedNodes = new Particle[nodeCount]; springNodes = new Particle[nodeCount]; connections = new Spring[nodeCount]; float u = 4; float v = 0.1; for (int i = 0; i < nodeCount; i++) { fixedNodes[i] = ps.makeParticle(2, baseX + (deltaX * (i + 1)) + random(-u, u), baseY + ((abs(deltaX) / 6) * (i + 1)) + random(-u/2, u/2), 0); fixedNodes[i].makeFixed(); springNodes[i] = ps.makeParticle(nodeCount - i + 2, fixedNodes[i].position().x(), fixedNodes[i].position().y(), 0); connections[i] = ps.makeSpring(fixedNodes[i], springNodes[i], 0.4 + random(-v, v), 0.1 + random(-v/6, v/6), 0.0); } // Tie the particles in a line float w = sqrt(sqr(rootNode.position().x() - springNodes[0].position().x()) + sqr(rootNode.position().y() - springNodes[0].position().y())); ps.makeSpring(rootNode, springNodes[0], 1, 0.1, w); for (int i = 1; i < nodeCount; i++) { w = sqrt(sqr(springNodes[i-1].position().x() - springNodes[i].position().x()) + sqr(springNodes[i-1].position().y() - springNodes[i].position().y())); ps.makeSpring(springNodes[i-1], springNodes[i], 0.1, 0.1, w); } } // Workings /////////////////////////////////////////////////////////////////// void update() { // This is where we'll draw the leaf and update the polygon. polygon = new Point[2 + 2 * nodeCount]; fill(1, 90, 1); stroke(1, 90, 1, 40); strokeWeight(8); float n; int j = 0; beginShape(); // Root node -- top n = rootSize; curveVertex(rootNode.position().x(), rootNode.position().y() - n); curveVertex(rootNode.position().x(), rootNode.position().y() - n); polygon[j] = new Point(rootNode.position().x(), rootNode.position().y() - n); j++; // Nodes -- top for (int i = 0; i < nodeCount; i++) { n = ((nodeCount - i) * rootSize) / nodeCount; curveVertex(springNodes[i].position().x(), springNodes[i].position().y() - n); polygon[j] = new Point(springNodes[i].position().x(), springNodes[i].position().y() - n); j++; } // Nodes -- bottom for (int i = nodeCount - 1; i >= 0; i--) { n = ((nodeCount - i) * rootSize) / nodeCount; curveVertex(springNodes[i].position().x(), springNodes[i].position().y() + n); polygon[j] = new Point(springNodes[i].position().x(), springNodes[i].position().y() + n); j++; } // Root node -- bottom n = rootSize; curveVertex(rootNode.position().x(), rootNode.position().y() + n); polygon[j] = new Point(rootNode.position().x(), rootNode.position().y() + n); // Finish it off curveVertex(rootNode.position().x(), rootNode.position().y() - n); endShape(); fill(51, 153, 0); stroke(51, 153, 0, 40); strokeWeight(6); beginShape(); // Root node -- top n = rootSize; curveVertex(rootNode.position().x(), rootNode.position().y() - n); curveVertex(rootNode.position().x(), rootNode.position().y() - n); // Nodes -- top for (int i = 0; i < nodeCount; i++) { n = ((nodeCount - i) * rootSize) / nodeCount; curveVertex(springNodes[i].position().x(), springNodes[i].position().y() - n); } // Nodes -- middle for (int i = nodeCount - 1; i >= 0; i--) { curveVertex(springNodes[i].position().x(), springNodes[i].position().y()); } // Root node -- middle curveVertex(rootNode.position().x(), rootNode.position().y()); // Finish it off curveVertex(rootNode.position().x(), rootNode.position().y()); endShape(); /*stroke(0, 255, 0); strokeWeight(3); for (int i = 1; i < polygon.length; i++) { line(polygon[i - 1].x, polygon[i - 1].y, polygon[i].x, polygon[i].y); }*/ } void jiggle() { for (int i = 0; i < nodeCount; i++) { float n = 8; //springNodes[i].moveBy(random(-n, n), random(-n, n) * i, 0); springNodes[i].moveBy(random(-0.5, 0.5), (i + 1) * random(0, n), 0); } } void wind(float w) { for (int i = 0; i < nodeCount; i++) { //springNodes[i].addVelocity(w * random(1.7, 2.4), w * random(1.7, 2.4), 0); springNodes[i].moveBy(random(0, w), (i + 1) * random(0, w * 4), 0); } } void bump(float m) { for (int i = 0; i < nodeCount; i++) { springNodes[i].moveBy(random(0, m / 8), (i + 1) * random(0, m / 8), 0); } } void addMass() { int n = int(random(0, nodeCount - 1)); springNodes[n].setMass(springNodes[n].mass() * 2.0); connections[n].setStrength(connections[n].strength() / 1.2); } }