Skip to content

Instantly share code, notes, and snippets.

@monkstone
Created December 19, 2018 11:17
Show Gist options
  • Save monkstone/70d046091229c94322cd984da3adb1f3 to your computer and use it in GitHub Desktop.
Save monkstone/70d046091229c94322cd984da3adb1f3 to your computer and use it in GitHub Desktop.
toxi
/**
* Simple recursive branching system inspired by mycelium growth
*
* This file is part of the SAC 2013 workshop project
* (c) 2013 Karsten Schmidt
* LGPLv3 licensed
*/
import toxi.geom.*;
import toxi.processing.*;
import java.util.*;
// max segments per branch
int MAX_LEN = 100;
// max recursion limit
int MAX_GEN = 3;
// variance angle for growth direction per time step
float THETA = PI/6;
// branch chance per time step
float BRANCH_CHANCE = 0.05;
// branch angle variance
float BRANCH_THETA = PI/3;
ToxiclibsSupport gfx;
Branch root;
// switch to ensure growth remains in window bounds
boolean doWrap = true;
void setup() {
size(1280, 600);
gfx = new ToxiclibsSupport(this);
root = new Branch(new Vec2D(0, height/2), new Vec2D(1, 0), 10, THETA);
}
void draw() {
background(0);
stroke(255);
noFill();
root.grow();
root.draw();
}
class Branch {
Vec2D currPos;
Vec2D dir;
List<Vec2D> path = new ArrayList<Vec2D>();
List<Branch> children = new ArrayList<Branch>();
float speed;
float theta;
Branch(Vec2D p, Vec2D d, float s, float t) {
currPos = p;
dir = d;
speed = s;
theta = t;
path.add(p.copy());
}
void grow() {
if (path.size() < MAX_LEN) {
if (doWrap) {
Vec2D newPos = currPos.add(dir.scale(speed));
if (newPos.x < 0 || newPos.x > width) dir.x *= -1;
if (newPos.y < 0 || newPos.y > height) dir.y *= -1;
}
currPos.addSelf(dir.scale(speed));
dir.rotate(random(-0.5, 0.5) * THETA);
path.add(currPos.copy());
if (children.size() < MAX_GEN && random(1) < BRANCH_CHANCE) {
Vec2D branchDir = dir.getRotated(random(-0.5, 0.5) * BRANCH_THETA);
Branch b = new Branch(currPos.copy(), branchDir, speed * 0.99, theta);
children.add(b);
}
}
for (Branch c : children) {
c.grow();
}
}
void draw() {
gfx.lineStrip2D(path);
for (Branch c : children) {
c.draw();
}
}
}
#!/usr/bin/env jruby
require 'picrate'
require 'toxiclibs'
# max segments per branch
MAX_LEN = 100
# max recursion limit
MAX_GEN = 3
# variance angle for growth direction per time step
THETA = Math::PI / 6
# branch chance per time step
BRANCH_CHANCE = 0.5
# branch angle variance
BRANCH_THETA = Math::PI / 3
# Simple recursive branching system inspired by mycelium growth
#
# This file is part of the SAC 2013 workshop project
# (c) 2013 Karsten Schmidt
# LGPLv3 licensed
class Mycelium < Processing::App
attr_reader :gfx, :root, :doWrap
def setup
@doWrap = true
@gfx = Gfx::ToxiclibsSupport.new(self)
@root = Branch.new(Vec2D.new(0, height / 2), Vec2D.new(1, 0), 10.0, THETA)
end
def draw
background(0)
stroke(255)
noFill
root.grow
root.draw
root.run
end
def settings
size(1280, 600)
end
end
Mycelium.new
class Branch
include Processing::Proxy
attr_reader :currPos, :dir, :path, :children, :generation, :speed, :theta
def initialize(p, d, s, t)
@currPos = p
@dir = d
@speed = s
@theta = t
@path ||= []
@children ||= []
path << TVec2D.new(p.x, p.y)
end
def grow
if path.length < MAX_LEN
if doWrap
newPos = currPos + (dir * speed)
dir.x *= -1 if (newPos.x < 0 || newPos.x > width)
dir.y *= -1 if (newPos.y < 0 || newPos.y > height)
end
end
@currPos += (dir * speed)
dir.rotate!(rand(-0.5..0.5) * THETA)
path << TVec2D.new(currPos.x, currPos.y)
if (children.length < MAX_GEN) && (rand < BRANCH_CHANCE)
branchDir = dir.rotate(rand(-0.5..0.5) * BRANCH_THETA)
children << Branch.new(currPos.copy, branchDir, speed * 0.99, theta)
end
end
def draw
gfx.lineStrip2D(path)
end
def run
children(&:grow)
children(&:draw)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment