Lexa

WPF, C#, Objective C and a little Math

Fast L-System rendering with OpenGL

Main news: WPF 3d renderer in the Viewer is replaced with OpenGL renderer (using OpenTK library). Now rendering is really fast. I didn’t do anything special: when L-System symbols string is parsed, all elements are collected in a huge array of vertexes, colors and normals, which is then rendered using glDrawArrays function.

The other interesting feature is “smooth” path of a turtle. Before each turtle movement was represented with a box, so sequence of movements looked like a chain of boxes. Now turtle path looks like a pipe, and user is allowed to change number of edges of the pipe. Below is an example of curly L-System with “smooth” rendering. Old way of rendering is still available though.

 

The other changes are related to StringParser, which helps to transform character strings to list of symbol objects. Now it support parameters in brackets. If parameters are present, then StringParser uses parameters as an array of doubles, and create a symbol using its constructor with double parameters. The source code of a Spiral above uses this feature in its production functions:

public class Spiral : LSystems.Turtle.SystemDefinition, LSystems.IRewriteRules
{
    public class e
    {
        public int Index { get; set; }
        public e() { this.Index = 0; }
        public e(double index) { this.Index = (int)index; }
    };

    public class s
    {
        public int Index { get; set; }
        public s() { this.Index = 0; }
        public s(double index) { this.Index = (int)index; }
    };

    public class D { };

    private LSystems.Turtle.StringParser parser = new LSystems.Turtle.StringParser();

    public Spiral()
    {
        parser.Register(typeof(e));
        parser.Register(typeof(s));
        parser.Register(typeof(D));
    }

    private const int GrowIndex = 8;

    [LSystems.Production]
    public object Grow(e endpoint)
    {
        int index = (endpoint.Index + 1) % GrowIndex;
        return parser.Produce(string.Format(
            "^+DF{0}e({1})",
            (index == 0 ? "[Ds]" : ""),
            index));
    }

    [LSystems.Production]
    public object Grow(s endpoint)
    {
        int index = (endpoint.Index + 1) % GrowIndex;
        return parser.Produce(string.Format(
            "-&DF{0}s({1})",
            (index == 0 ? "[De]" : ""),
                index));
    }

    [LSystems.Turtle.Interpret]
    public void Smaller(D d)
    {
        Turtle.SetColor(1, 1.0 - Turtle.Distance / 100.0, 0);
        Turtle.Distance = Turtle.Distance * 0.95;
        Turtle.Thickness = Turtle.Thickness * 0.93;
    }

    public object Axiom
    {
        get { return parser.Produce("#(100)d(100)a(45)\\a(20)e"); }
    }

    public int Depth
    {
        get { return 80; }
    }

    public LSystems.RewriteDirection RewriteDirection
    {
        get { return LSystems.RewriteDirection.LeftToRight; }
    }
}

Executable  Release.04 is here: http://tatalata.com/Blog/Viewer.Release.04.zip

Updated source code is already in the repository.


Categorised as: L-Systems, Turtle Graphics


2 Comments

  1. Piotr Rashidow says:

    very cool. how about adding mesh output to the OpenGLViewContainer? or maybe adding propabilities for stopping growth along a branch?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>