Above is a representation of the component graph used to generate the procedural texture in the previous blog entry (click image for full size version). The components are created with the NetBeans Visual Library, which seems very well suited for component based graphs.
I implemented a custom Bezier spline based connection path. I feel that it is easier to read and understand than one with straight lines, or non-overlapping connectors automatically routed in a manhattan grid (axis aligned, only right angles). The curvature of the connection adds some extra information; it is easier to see if a connection is going backwards or forwards, or spanning a long distance or a short one.
Researching splines took a surprising amount of time again, there was no simple cut-and-paste Java code available either. I found the Unraveling Beizer Splines article on GameDev.net informative and simple (despite some typos in the code), the Wikipedia article on Bezier curves has nice animated graphs, but was a bit too theoretical to base a quick implementation on.
The resulting Java spline code is available, if you want to use it.
The procedural textures from the last time now have source code generated and stitched together for each component, and compiled on the fly using Janino. A trippy example texture can be seen above, created using four sin components, connected to inputs that change over the texture area, and outputs for producing red, green, and blue color channels.
The rendering time seems to be around 1 second (compared to about 5 seconds with a non-compiled implementation). I suspect the difference will be more marked with more complicated textures, as there is some overhead when the data is copied to a BufferedImage for rendering.
I ended up having to implement a Topological Sort algorithm for the dependency ordering, and a Cycle Detection algorithm to prevent creation of cyclical dependencies between components (I implemented that after spending about six hours trying to figure out what was wrong with the other algorithms, when there was a simple typo in the example code, causing a cyclical dependency). This paper on various graph algorithms was an useful reference.
Implementing the graph algorithms wasn't that straightforward, so I was considering using some existing graph library instead, especially as the next step will be to visualize the component graphs and edit them in a UI. However, it seems there are not many library aimed for graphs of components that can be connected to each other through input and output ports except for JGraph, which is a bit daunting in its complexity. A promising alternaive seems to be the NetBeans Visual Libray, which is aimed at graph visualization and graph oriented modeling. It would seem to be a perfect fit, provided it doesn't depend on all of NetBenas (doesn't seem to), and has a flexible enough model, and customizable visualization.
I'm working at a procedural texture system for Skycastle at the moment. The intent is partly to get a useful and fun texturing tool to play with, and partly to create a spike for exploring what a more generic component oriented procedural content editor should be like.
Based on some initial tests that just calculated random pixel values, it soon became evident that having components calculate the values and request calculated values from other components would be quite slow, so I decided to explore on-the-fly code generation. Janino seems to be one of the established libraries in this area. Janino has the advantage of not needing the Java compiler (which is only available in the JDK, not the JRE), instead it actually implements a large subset of a Java compiler.
Currently I'm doing some prototyping on what generated code would look like (by just writing it out by hand). An interesting looking result obtained with four sin functions and some constant parameters for them is shown in the screenshot. It is still slow (about 5 seconds for a medium size window on my T60 laptop), so I was thinking of including the whole pixel iteration loop in the generated code, to eliminate any method calls for each pixel.