Turtle t; LSystem lsys; String lstring; void setup() { size(200, 200); t = new Turtle(); lsys = new LSystem(); lsys.SetAxiom("A"); lsys.AddRule('A', "F[-A][^A]"); lstring = lsys.Produce(10); } void loop() { background(255); translate(width/2, height/2); rotateY(TWO_PI * (float)mouseX/width); rotateX(TWO_PI * (float)mouseY/height); t.Draw(lstring); } void keyPressed() { if (key == '<') t.initialState.turn -= PI/100; if (key == '>') t.initialState.turn += PI/100; if (key == '-') t.initialState.forwardstep--; if (key == '+') t.initialState.forwardstep++; } /* LSystem The LSystem object performs Lindenmayer system string expansion. */ class LSystem { String axiom; String[] rules; LSystem() { rules = new String[256]; for (int i = 0; i < 256; i++) rules[i] = null; } // Sets the LSystem axiom void SetAxiom(String a) { axiom = a; } // Sets a rule to be associated with the character void AddRule(char c, String r) { rules[(int)c] = r; } // Returns the LSystem string for a number of iterations String Produce(int iterations) { String last = new String(); last = axiom; for (int iter = 0; iter < iterations; iter++) { StringBuffer result = new StringBuffer(1000); for (int i = 0; i < last.length(); i++) { if (rules[(int)last.charAt(i)] != null) result.append(rules[(int)last.charAt(i)]); else result.append(last.charAt(i)); } last = result.toString(); } return last; } } /* Turtle The Turtle object draws figures in 3D from a String Commands: f Move the turtle forward F Move the turtle forward and leave a line < Roll around the Z axis > Roll around the Z axis - Roll around the Y axis + Roll around the Y axis _ Roll around the X axis ^ Roll around the X axis [ Push the current drawing context onto the stack ] Pop a drawing context from the stack */ class Turtle { TurtleState initialState; Stack stateStack; Turtle() { initialState = new TurtleState(0, 10, PI/4); stateStack = new Stack(1000); } // Draw the given String void Draw(String instructions) { TurtleState current = initialState.Copy(); for (int i = 0; i < instructions.length(); i++) { stroke(0); switch (instructions.charAt(i)) { case 'f': translate(0, 0, current.forwardstep); break; case 'F': beginShape(LINE_STRIP); vertex(0, 0, 0); vertex(0, 0, current.forwardstep); endShape(); translate(0, 0, current.forwardstep); break; case '<': rotateZ(-current.turn); break; case '>': rotateZ(current.turn); break; case '-': rotateY(-current.turn); break; case '+': rotateY(current.turn); break; case '_': rotateX(-current.turn); break; case '^': rotateX(current.turn); break; case '[': push(); stateStack.push((Object)current.Copy()); break; case ']': pop(); current = (TurtleState)stateStack.pop(); if (current == null) return; break; } } } } class TurtleState { TurtleState(int c, float forward, float turn) { this.c = c; this.forwardstep = forward; this.turn = turn; } TurtleState Copy() { TurtleState s = new TurtleState(c, forwardstep, turn); return s; } color c; float forwardstep, turn; } class Stack { Object[] s; int place, sz; Stack(int n) { sz = n; s = new Object[sz]; place = -1; } void push(Object o) { if (place < sz - 1) { place++; s[place] = o; } } Object pop() { if (place >= 0) { place--; return s[place + 1]; } else return null; } }