> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.tT-CXqZlw7z/rev.63
 * 
 * authors: 
 *   pete nelson

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/*This is actually by James Morris http://jwm-art.net/ - I commissioned it from him for my website*/ 

class organicBranch
{
    int     parent;
    int     level;

    int     x2, y2;

    float   length;
    float   width;
    float   angle;

    float   branch_thresh;
    float   growth_rate;

    int     life;

    organicBranch(  int _parent,            int _level,
                    float _branch_thresh,   float _growth_rate,
                    int _life)
    {
        parent = _parent;
        level = _level;
        length = 0;
        width = 0;
        angle = 0;
        branch_thresh = _branch_thresh;
        growth_rate = _growth_rate;
        life = _life;
    }
};


class organicTree
{
    int origin_x;
    int origin_y;

    int max_levels;
    int max_branches;

    int top_level;
    int branch_count;
    int life;

    float   init_growth_rate;
    float   init_branch_thresh;
    float   width_ratio;
    float   branch_multi;
    float   growth_multi;
    float   angle_add_min;
    float   angle_add_max;

    float   sway_ang;
    float   sway_step;
    float   sway_amount;

    color   col_trunk;
    color   col_leaf;

    int minx, maxx, miny, maxy;

    organicBranch[] branch;

    organicTree(int x, int y)
    {
        max_levels =            35;
        max_branches =          1000;

        init_growth_rate =      0.5;

        init_branch_thresh =    random(2.0,     4.0);
        width_ratio =           random(0.1,     0.35);
        branch_multi =          random(1.025,   4.00);
        growth_multi =          random(0.175,   0.999999);
        angle_add_min =                         random(1,   20);
        angle_add_max =         angle_add_min + random(1,   25);
        sway_step =             random(0.75, 5);
        sway_amount =           random(0.25, 4.0);

        int yy = y;
       

        life =  2;

        top_level = 0;

        branch_count = 1;
        branch = new organicBranch[2];

        branch[0] = new organicBranch(-1, 0, 0, 0, 0);
        branch[0].x2 = origin_x = x;
        branch[0].y2 = origin_y = y;

        branch[1] = new organicBranch(0,    0,
                                            init_branch_thresh,
                                            init_growth_rate,   life);

        branch[1].angle = 270 +
                            (random(0,10) < 5 ? -1 : 1)
                                * random(0, 10);
        stunt_growth = false;

        sway_ang = 0;

        col_trunk = color(  random(20,  50),
                            random(5,   10),
                            random(2,    6),
                            15 );

        col_leaf =  color(  random(5,    30),
                            random(100, 255),
                            random(2,    50),
                            15);
    }

    boolean grow_branch(int i)
    {
        branch[i].length += branch[i].growth_rate;
        branch[i].width +=  branch[i].growth_rate * width_ratio;

        if (branch[i].length > branch[i].branch_thresh)
        {
            branch[i].branch_thresh *=  branch_multi;
            branch[i].growth_rate *=    growth_multi;
            branch[i].life--;
            return true;
        }

        return false;
    }

    void grow()
    {
        int px = origin_x;
        int py = origin_y;
        int x, y;

        float offang = sway_amount * sin(radians(sway_ang));
        sway_ang = (sway_ang + sway_step) % 360;

        if (branch_count == max_branches)
            return;

        for (int i = 1; i <= branch_count; ++i)
        {
            if (branch[i].life <= 0)
                continue;

            boolean branchoff = (branch_count < max_branches)
                                    ? grow_branch(i)
                                    : false;

            int p = branch[i].parent;

            int x1, y1, x2, y2;

            x1 = branch[p].x2;
            y1 = branch[p].y2;

            x2 = x1 + 8 * (branch[i].length / init_branch_thresh) *
                    cos(radians(branch[i].angle +
                                    offang * branch[i].level));

            y2 = y1 + 8 * (branch[i].length / init_branch_thresh) *
                    sin(radians(branch[i].angle +
                                    offang * branch[i].level));

            branch[i].x2 = x2;
            branch[i].y2 = y2;

            strokeWeight(branch[i].width);

            stroke(lerpColor(col_trunk, col_leaf, i / max_branches));
            line(x1, y1, x2, y2);

            if (branchoff)
            {
                ++branch_count;
                int lvl = branch[i].level + 1;
                branch.push(new organicBranch(i,    lvl,
                                                    init_branch_thresh,
                                                    init_growth_rate,
                                                    life  ));

                if (lvl > top_level)
                    top_level = lvl;

                branch[branch_count].angle =
                    (branch[i].angle +
                        ((random(0, 10) < 5) ? 1 : -1)
                            * random(angle_add_min, angle_add_max)) % 360;

                if (branch[i].life <= 0)
                    max_branches++;
            }
        }
    }
};


organicTree tree1;
organicTree tree2;


void setup()
{
    size(500, 475);
    frameRate(30);

    tree1 = new organicTree(200, 550);
    

    noStroke();
    fill(0x0f3f3f3f);
    rect(0, 0, width, height);
}


void draw()
{
    tree1.grow();
}