int SX = 200, SY = 200, SZ = 200; float a = 0, da = 0.01; int time = 0; Array stems; void setup() { size(325, 365); rectMode(CENTER_DIAMETER); ellipseMode(CENTER_DIAMETER); stems = new Array(300); //smooth(); } void loop() { if (time % 20 == 0) { //for (int i = 0; i < 5; i++) { float x = random(SX) - SX/2; float y = random(SY) - SY/2; stems.insert(new Stem(x, y, -SZ/2, x, y, -SZ/4, 100)); } } time++; background(255); translate(width/2, height/2); rotateY(a); a += da; //rotateY((float)mouseX/width * TWO_PI); //rotateZ((float)mouseY/height * TWO_PI / 5); push(); rotateX(PI/2); //scale(0.5); push(); translate(0, 0, -100); stroke(64, 128, 64, 128); fill(64, 128, 64, 16); rect(0, 0, 200, 200); pop(); // Run stems for (stems.pointer_reset(); !stems.pointer_atend(); stems.pointer_next()) { Stem item = (Stem)stems.pointer_get(); if (item != null) { if (item.die()) stems.pointer_delete(); else { item.step(); item.draw(); } } } pop(); } class Stem { int time, maxtime; boolean dead; float px1, py1, pz1, px2, py2, pz2; Stem(float px1, float py1, float pz1, float px2, float py2, float pz2, int maxtime) { this.px1 = px1; this.py1 = py1; this.pz1 = pz1; this.px2 = px2; this.py2 = py2; this.pz2 = pz2; time = 0; this.maxtime = maxtime; dead = false; } boolean die() { return dead; } void draw() { push(); stroke(32, 64, 32, 128); beginShape(LINE_STRIP); vertex(px1, py1, pz1); vertex(scaled(px1, px2), scaled(py1, py2), scaled(pz1, pz2)); endShape(); pop(); } float scaled(float p1, float p2) { if ((float)time < (float)maxtime/8.0) // grow return (8.0 * (float)time/(float)maxtime) * (p2 - p1) + p1; if ((float)time > (15.0 * (float)maxtime/16.0)) // die off return ( 1.0 - 16.0 * ( (float)time - 15.0 * (float)maxtime / 16.0 ) / (float)maxtime ) * (p2 - p1) + p1; else // stay return p2; } void step() { time++; if (random(1) < 0.15 && (float)time < (float)maxtime/8.0) { float x, y, z, x1, y1, z1; x = scaled(px1, px2); y = scaled(py1, py2); z = scaled(pz1, pz2); x1 = x + random(50) - 25; y1 = y + random(50) - 25; z1 = z + random(50); int lifetime = (int)((float)maxtime - (float)time - ((float)time/2.0)); stems.insert(new Stem(x, y, z, x1, y1, z1, lifetime)); } if (time > maxtime) dead = true; } } class Array { int n, pointer; Object[] array; boolean atend; Array(int num) { n = num; array = new Object[num]; for (int i = 0; i < num; i++) array[i] = null; pointer_reset(); } boolean insert(Object item) { for (int i = 0; i < n; i++) if (array[i] == null) { array[i] = item; return true; } return false; } void pointer_reset() { pointer = 0; atend = false; } void pointer_next() { if (!atend) { pointer++; while (pointer < n && array[pointer] == null) pointer++; if (pointer == n) atend = true; } } boolean pointer_atend() { return atend; } Object pointer_get() { if (!atend) return array[pointer]; else return null; } void pointer_delete() { if (!atend) array[pointer] = null; } }