This project has moved. For the latest updates, please go here.
How the algorithm works















I use a trail of particles to advance the tree growth, so each particle that moves over iterations is a trunk, branch or leaves (depending on what particle it is). Each particle has a behaviour that is executed, the most basic one being 'advance the particle in its current direction'. All particles also have a limited life span of x nr of iterations.

I start off with a trunk particle at the bottom of the screen that moves up. Trunk particles have a few behaviours it does:
            // stimulate branching where life is low
            if (stimulateBranchingAtEndOfLife)
                BranchingBehaviour((float)LineairScaleTo((((float)trunk.MaxLife - trunk.Life) / (float)trunk.MaxLife), 0.0f, 1f) * branchingPercent, trunk, depth);
            else
                BranchingBehaviour(branchingPercent, trunk, depth);

            // leaves behaviour
            LeavesBehaviour(trunk);

            // make the tree thicker
            TrunkThickingBehaviour(trunk);

            // zigzag the tree a little
           TrunkNudgeBehaviour(trunk);

           // make the trunk split sometimes
            TrunkSplittingBehaviour(trunk);

Branching should be fairly obvious, at each iteration there's a random chance it will spawn a branch particle. The direction range of a branch is dependent on the depth of the branch, trunk -> branch1 would be depth 1, branch1 -> branch2 would be depth 2, which halves the range the angle can vary from the direction of branch1.

A branch particle has the following behaviour:
                // define the behaviour of the branch
                branch.Behaviour = b =>
                        {
                            // branches should sprout leaves
                            LeavesBehaviour(b);

                            // branches can branch again
                            BranchingBehaviour(branchingPercent, b, depth + 1);

                            // weight behaviour
                            if (applyWeightOnBranches)
                                b.Direction = new Vector2D(initialDirection.X, initialDirection.Y * LineairScaleTo((double)b.Life / (double)branch.MaxLife, -1f, 1f));
                        };


You can see the recursion of the branching there. Both branches and trunk particles also have do the leaves behaviour, which spawns a number of leaf particles when the life of the particle is below a certain threshold. Leaf particles have a short life, and just grow without any additional behaviour

Another thing branches do is curve downwards due to gravity, so in its behaviour I change the direction vector downward based on the progress along its lifespan.

Those behaviours alone would make a tree that has a perfectly vertical thin trunk, which is not how all trees are. To accommodate that I added 3 other trunk behaviours:

- Trunk Thicking: a trunk grows thicker, obviously, so I spawn particles without any behaviour in the direction perpendicular to the direction of the trunk (that was a real fun thing in 3D to not leave any gaps).

- Trunk Nudging: a trunk randomly changes it direction a bit (like there were other trees nearby and it grows toward the most light exposure), that's the zig zag factor.

- Trunk Splitting: sometimes a trunk split into 2, each growing like a Y fork. What I do is half the life of the current trunk particle, spawn a new trunk particle and rotate the direction with a random angle between -pi,pi. The original trunk particle's direction is set to a perfect mirror of the direction of the new particle (-x,y).

And that's about it, I find classifying things into behaviours a rather elegant design and is rather extensible: for example you can introduce fruit particles that grow fruit when leaves reach a certain life treshold, or add additional starving behaviour based on the worlds water supply etc.

Class diagram

Last edited Nov 10, 2013 at 9:36 AM by drake7707, version 5