From Context Free Art
Feature Ideas
The two main features that are driving version 3 are parameters or arguments for rules and having a random number function that is different each time a rule is executed.
Some other feature ideas are:
- Syntax change: adding comma delimiters between numbers in size x y z adjustments as well as between the two angles in skew y angle x angle adjustments. This allows us to get rid of the requirement that expressions be inside parentheses.
- Or maybe there could be a comma operator that binds together multiple numbers into a vector. So s (2, 3) would equivalent to s 2 3. The requirement to have parentheses around expressions wouldn't go away, but it would be more palatable. The advantage of this approach would be that older code that doesn't have commas would still be valid.
- Closures and shape adjustments as parameters.
- Parameters for paths too
- If statements
- It would probably be nice to have some form of variables so that you can get a random number and use it more than once or use the result of a complicated expression in more than one place without duplicating it. Maybe you can initialize them but not change them afterward.
- Accessing the loop index in expressions
- I was going to do this using a $0, $1, ... syntax where $0 evaluates to the index of the inner-most loop, $1 is the index of the next inner loop, etc.
rule sinewave {
360* {x 1}
CIRCLE { y (90 * sin($0)) }
} But Mark thinks that this is ugly and obscure and that it would be better to have an alternate loop syntax with a named loop index variable:
rule sinewave {
for (angle = 0; angle < 360; ++angle; {x 1}) {
CIRCLE { y (90 * sin(angle)) }
}
} or maybe
rule sinewave {
for angle => 0 .. 360 {x 1}
CIRCLE { y (90 * sin(angle)) }
} if we want to keep loop indices in the integer domain.
- Perspective transforms
- Adding a concept of shape time so that the designer has explicit control over what animation frames a given shape is visible.
- Allowing shape adjustments in the startshape line so that the default color can be changed
- Global parameters
- And the ability to override the in-file parameters via command-line options are dialog box options.
- Ending recursion when a shape is transparent
- Painting shapes with images in addition to colors
- This goes for the background too
- A new FILL shape that fills the entire canvas with a specified color at a specified z.
- Text, maybe even text on a path.
- Currently a shape can either be defined by a single path or by one or more rules. Maybe this should be relaxed to allow a shape to be defined by any number of paths or rules.
kipling's wish list
These are ideas of varying quality, based on what I feel like suggesting just now, as well as some of the forum discussions.
Opinions on MtnViewJohn's list
- Parameters in rules - you might have to drop the "Free" from "Context free". So as a purist, I don't care for this... However, it would open up CF to many L-systems, so I would probably end up using them just because.
- [MVJ] I don't think that parameters break the context free paradigm. I've read through the wikipedia entry on context free grammars and I don't see anything that says that a rule with parameters can't be part of a context free grammar. Without parameters a rule transforms a non-terminal to a list of terminals and non-terminals. With parameters a rule does the same thing, but for a family of non-terminals.
- AK: it is a while since I did anything formal on grammars, but looking at the wikipedia page, my interpretation is that adding parameters to the rules e.g. rule foo (bar) { ... } means that the set of non-terminal symbols now consists of all possible symbols of the form "foo ( * )" creating an infinite set of non-terminals. Of course, it is not an arbitrary infinite family of non-terminals. Actually, looking deeper into the wp page, I notice that having arguments in rules is listed as an "extension" of context free grammars. My original feeling about whether "context free" still applies is that the parameter can be used to carry state information from parent expansions to child expansions - this is maybe ill-directed. I would have to think about this a little more.
- [MVJ] I think that information transfer from parent to child is OK (i.e. is context free) but info transfer from child to parent or from sibling to sibling is not OK.
Context Free has always passed parameters from parent to child: color, geometry, z, and the random seed. This information is really a parameter of the terminals and non-terminals in the cfdg grammars. Version 3 is simply adding user specified parameters. ETA - on second thought this is not true. Color, geometry, etc have no effect on rule production in CF2, but CF3 parameters are explicitly conceived as affecting rule production. We must be careful that this does not take us away from our context-free roots.
- AK: OK. I guess I was seeing these inherited parameters as "rendering details" on how the program renders a visualisation of the expansion/substitution process, and that these rendering parameters don't affect the rules available in the expansion of the child (except via bail-outs). From a formal grammar point of view, the underlying grammar is still a formal CF grammar and generates a formal CF language (or maybe a "formal-CF-language-with-infinite-words") and the image is actually a by-product of the sequence of expansions.
- I am pretty sure it is the case that the ability to add parameters to the rules actually moves the grammar to a different class, in that the language L = {abc,aabbcc,aaabbbccc,....} can be generated by a "parameterised CFG", but not a "CFG" - I suspect this makes it an indexed grammar but you would have to ask an expert on formal languages. This is certainly true if you allow parameters to be integers and are allowed to do arithmetic with them, and I suspect it is also true if the parameters are strings of non-terminal symbols on which you are only allowed to do CF expansion. I think the latter is possible via in your "closure parameters" as described below - admittedly I am not sure that I have grasped closure params completely.
- Of course, this may be a bit too esoteric to matter - I mean we already have a seed of non-CF behaviour via the size-threshold bail-out rule. I understood the existing bail-out as a means to an end - the images CF creates are only approximations to the "true" images that are produced where we are visualising a non-terminating expansion process via a CF grammar. The bail-outs allow this approximation by saying "this shape is too small to matter". Given this, an ideal bail-out rule should have the property that as the threshold converges to 0, the image should converge to a "final" image.
- I think my next .cfdg will be an infinite number of angels dancing on the heads of an infinite number of pins, skewering infinitely many angels, ...
- [Nom]: Kipling's example is imho illuminating, with respect to the class of grammars. From what I recall, the Chomskian hierarchy would swallow such transformations under context sensitive grammars. Of course, the question remains, to which extent context sensitiveness is an extralinguistic feature related to the execution model. In my Context3 endeavor I found a real context sensitive grammar from the point of view of Chomsky's definition -- impractical. Wielding a virtual machine would definitely move us to the realm of Turing completeness, and after that, interpreting the details might be a matter of politics :) I'm definitely very interested on what kinds of features will show up!
- [MVJ] The wikipedia entry for context-free grammars lists indexed and affix grammars as extensions of context-free grammars. Since CF3 rules only transform individual non-terminals with no regard to their neighboring symbols I think we are still context-free.
- [Nom]: If you look at the Wikipedia entry for formal grammars (the main one), it places indexed and affix grammars somewhere between context free and context sensitive grammars, but does not appoint Chomskian types to them. This is probably more correct than to say that affix grammars belong to context free grammars (or are under context free grammars). Indexed grammars and affix grammars include additional properties that the Chomskian hierarchy does not know. Yacc (or bison), for one instance, uses context free structuring, but depends on the turing completeness of its underlying implementation (c-language) for its output. I think one way to visualise the gap would be to think about the number of states that are needed in context free vs. context sensitive generation. A simple machine that has two atomic states, one for iterating over an input tape, and one for iterating over a set of context free transformations, can generate a new input tape (which process could be iterated). But matching the contexts would require at least two additional states. I think. Being not so very versed in the mathematical model...
- Global parameters or constants - yes please
- Bailing out on transparency - not by default, as it is possible to have rules that increase alpha back above 0.
- [MVJ] that's true. Maybe there should be some keywords to indicate what bailout rules to use. We could think of many bailout rules. Actually for a context free grammar the bailout rules are actually implicit rules that replace the non-terminal symbol with null if the bailout condition is met. So to be context free, all expansions of a given non-terminal must use the same bailout rules. Actually, why even make them implicit rules replacing the non-terminal with null. How about keeping the current behavior by defining implicit 'too small' rules that replace the non-terminal with null, but allow users to define explicit bailout rules that can replace the non-terminal symbol with anything they want. Like having a rule that draws a tendril but when the tendril segments get too small bailing out and drawing a flower.
- AK: With CF3 parameters, this could also be achieved by having an explicit parameter (e.g. proportional to area scaling) that is passed down the generations and yields a flower once it hits a threshold. See above discussion!
- [MVJ] Mark reminded me that the too-small "rule" is not context-free because it is based on global information about extent of all of the terminals in the sentence. We need this one bit of context-sensitive behavior for practical reasons: to allow CF to execute a grammar in a finite amount of time. But to turn this context-sensitive rule into a user-accessible feature would be a mistake. I take it back.
- FILL - yes please. (You know what I will use it for already) The background command could then be an instance of this, especially if you have a parameter/constant "infinity" pre-defined.
Language enhancement ideas
- The FILL object above could be an extension of the background command, or could eventually replace the background command.
- Allow options in the tile command to capture a few more planar symmetry groups
- An "inverse" attribute for elements that (e.g.) turns a square into a FILL with a square hole. A bit like "inverse" does in povray. How this propagates to descendants would need consideration, but maybe it should only be available for elementary rules. Other constructive-geometry operations could also be useful (as in povray). These probably couldn't propagate to descendants without making CF very C-non-F.
- Separate "transparency" and "filtering" instead of, or as well as, just "alpha". Again, see povray, which expresses all colours in 5-value "rgbft" space. I don't know agg well enough to know if this is possible.
- [MVJ] AGG does not support the POV-Ray rgbft color space. The POV-Ray license does not look very friendly so I can't imagine writing my own color blender.
- AK: Fair enough. I was wondering if any other blending modes exist in agg, which is essentially what is required for filtering-type transparency vs opacity-type transparency.
- [MVJ] AGG supports all of the compositing operations that are in SVG 1.2. It shouldn't be too hard to add a blend-type option to stroke or fill commands in paths.
- Some vector-valued syntax, compatible with the comma syntax in the first suggestion above. For example:
- An alternative to "x 2 y 3" is "translate 2 3" or "t (2,3)" or "translate 2,3,0", etc
- [MVJ] I'm toying with the idea for a 'transform' adjustment. tr (2, 3) is equivalent to x 2 y 3, tr (2, 3, 5, 6) is the transforms that converts the unit square to a square with corners at (2, 3) and (5, 6), tr (2, 3, 5, 6, 3, 1) is the transform that converts the unit square to a parallelogram with corners at (2, 3), (5, 6), and (3, 1). If we add perspective transforms then there would be a four coordinate version.
- [MVJ] In the current version 3 beta I have turned the comma symbol into a w:cons operator. Many of the adjustments have been modified to accept linked lists of numbers: x (2, 3) is equivalent to x 2 y 3, x (2, 3, -1) is equivalent to x 2 y 3 z -1, size (2, 4) is equivalent to size 2 4, etc.
- An alternative to "size A B rotate X skew Y Z" is "matrix a,b,c,d"
- Global constants/params of type "vector" that can be used in translate, rotate, skew modifiers. Possible syntax v := vector { x 2 rotate 10 }.
- Global constants of type "transform" or "transformation" that can be used as rule modifiers. This would consist of an affine transform of the xy-plane together with an affine transform of the z-axis. Possible syntax: tr := transformation { s 2 1 0.5 r 20 x 1 z 2 } and A { B { transform tr }}
- [MVJ] Part of the idea for rule parameters and global parameters is to have three type of parameters: numeric, transformation (affine, color, or z), and closures.
- AK - sounds good, and covers many of the ideas I had in this list.
CF program ideas
- Execution options, either from command-line, application prefs, or maybe in the .cfdg:
- Toggle multi-threaded rule expansion, to speed things up on multi-processor machines.
- Toggle antialiasing
- Specify gamma of output image.
- Run the .cfdg through the C pre-processor (or other macro expansion language) at the start. This would integrate what TorfusPolymorphus did as an add-on: see this.
- Options on criteria for bail-out, such as size, transparency, depth, z-value. (all C-non-F)
- Specify language version .... especially if you are going to break backward-compatibility with commas.
- Interaction with online gallery:
- Browse the online gallery from the application (e.g. via RSS) to open .cfdg files directly, upload comments, votes, favourite variation codes
- Upload a modification of someone else's design to be available as a "descendent", providing original license allows remixing. Mashups?
- AK, 9-Feb-09: Use AGG's 16-bit formats rather than the 8-bit formats. The main advantage of this I can currently identify is that it fixes the "muddy colours" problem that emerged in the CF2.1->CF2.2 transition. These occur in designs containing many layers with small alpha. I have diagnosed that this is due to round-off in the compositing process - the CFDG internal HSB representation (doubles) is converted to Greyscale, RGB or RGBA with 1 byte per channel. When a pixel with RGBA=(0,0,0,0.01) (actually alpha=3/256) in front of a pixel RGB=(43,43,43), the resulting value is 42*253/256=42.496, which is rounded down to 42. Another identical "shading" layer then reduces the 42 to 41.5078, which is rounded up to 42. Further layers have no further effect, and so instead of fading to black, they fade to (42,42,42)-grey or maybe a murky off-grey (if one RGB-component of the original colour was between 0 and 42). Incidentally, from this I think I fully understand the CF2.1 -> CF2.2 bug fix - there must have been a change from round-down to round-nearest. Now, if compositing is done instead in 16-bit colour spaces (AGG has these) then the problem the occurs at 42/65536, which displays as 0/256. A logical extension of this idea is 16-bit-per-channel png output, if you wanted to produce images that would break a lot of image viewers. From the CF2.2 code, 16-bit compositing seems to be an extensive change, but mostly in the type substitution from RGBA8 (aka agg::rgba8) to agg::rgba16, and then changes to various of conversion routines. I think AGG handles the rest. On the weekend, I had a limited go at trying to patch this in but my C/C++ skills are too rusty (originally learned C ~20 years ago) and too limited (taught myself C++ about 10 years ago but never did anything with templates).
- [MVJ] The bug was a bit worse than changing from round-down to round-nearest. If you had a white shape with alpha it would be drawn as gray. If you drew many of these on top of each other you would get solid black instead of solid white. Supporting rgb16 should be pretty easy on Mac and Unix/Linux, but harder on Windows. Windows always saves PNG files as rgb8, so I would have to replace the PNG save code with code that uses libpng.
- There needs to be a way for a cfdg file to specify what its rendering attributes are: 8 or 16 bit color, desired level of detail, border width, etc.
- AK: Regarding rounding -- OK, I didn't fully understand. My testing didn't extend as far as trying white, as I was playing with black.
- AK: Regarding 16-bit depth, I was thinking that this would just be internal, mostly handled by AGG, and this would be downgraded/truncated to 8-bit on view (well, until everyone has 48bpp DisplayPort) and on save-to-png (ditto). As far as I can see, most of CF works in HSBA and it is only when things are getting drawn (or turned into FinishedShapes) that RGBA is used. Is it realistic to have "progressive render" at 8-bit and then "re-draw" at 16-bit? If 16-bit internals were not too expensive, can 16-bit be "always on"? If 16-bit is expensive, how is the option implemented? It could be optional as you say - either way, I guess aggCanvas gets a new PixelFormat, and a pile of new constructors, etc get added. Regarding the interface for this and other rendering options, they could be command-line switches and/or application preferences for default values, and then a language interface via global directives in the .cfdg. Whether it is worth bundling all these up in one "header" that contains all rendering directives (e.g. a render{} directive could have properties like size{}, tile{}, background{}, bitdepth{}, etc) or kept as individual ones is a matter of taste.
- [MVJ] I'm not too worried about the computational cost of 16-bit color. Everybody has multi-core CPUs these days and the drawing step can be parallelized without compromising the results (unlike the rule expansion step). My only concern is that it doubles the size of bitmaps. This isn't an issue for the 1000x1000 pixel images that most people generate. But it would cause problems for the few people who want to generate 30000x30000 pixel images. Since the majority of cfdg designs only need 8-bit color I would prefer to add 16-bit pixel formats to aggCanvas that are only used when they are needed.
- AK: Are you saying that 4GB should be enough for everyone?? 8-] Personally, I would find 16-bit more useful than gigapixel. Large images can be batched and patched via the size{} directive if absolutely necessary. But yes, keeping the 8-bit pipelines open might be useful too, in particular for images that rely on the round-off error. It would be nice if all features/bugs of previous versions of the language were still available.
- Guigui: 16-bit sounds nice, yes. But gigapixel is important to me. Some artworks are even more fascinating with the maximum of visible small fractal details.
Transform and Closure Parameters
The basic idea of transform parameters (both global and local) is that you could take some list of shape adjustments like s 0.5 y 0.25 b 0.25 h 2 z 1 and pass it to a shape rule, like so:
rule foo {
bar ({s 0.5 y 0.25 b 0.25 h 2 z 1}) {x 4}
}
rule bar (transform baz) {
SQUARE {exec $baz}
} Where rule foo takes the list of shape adjustments
s 0.5 y 0.25 b 0.25 h 2 z 1 and passes them to rule bar, which has a parameter of type transform named baz. Within rule bar the baz parameter can be applied anywhere that a shape adjustment can go.
The basic idea of closure parameters is that you take a list of shapes like
bam1 {s 4 h 160 sat 0.9 b 1 z -1}
bam2 {s 4 h 160 sat 0.9 b 1 z -2}
5 * {r 72} {
trunkr {y 0.2}
trunkr {r 180 y -1.6 s 0.4}
} and pass it to a rule. The rule can then execute the closure, which causes all of the shapes in the closure to get inserted into the rule. Why are we calling this a closure and not an anonymous rule? Because if the closure contains references to rule parameters or loop index variables from the surrounding rule then these values are bound to the closure. When the rule the receives the closure parameter executes the closure the closure will still be able to access these bound values, even though the shape that they came from has already completed its execution and gone away.
What is and is not enclosed in the closure?
The parameters and loop variables in the source shape are bound to the closure. But the world state (affine transform, color, z, random number seed) is not. When a rule executes a closure it provides a world state for the closure.
Isn't a transform parameter also a closure?
I think it is. There is nothing stopping the shape adjustments in a transform parameter from referencing rule parameters or loop variables, unless we explicitly forbid it (which would be bogus). So transform parameters will also have parameters and loop variables from the source rule bound to them. So really there are two kinds of closure parameters: transform and shape. The only difference is the context of where the closure is executed.
TorfusPolymorphus' wish list
- A command to extract a (rectangular) part of the image after all drawing has been done. This is similar to the tile command, but without the wrap-around
- [MVJ] This was added in version 2.2. The "size" command works just like the "tile" command, but without the wrap-around.
Guigui's wish list
- A simple way to allow animated artwork would be a variable 'frameCount'. It returns the number of the frames when rendering a SEQUENCE (and equal to 1 for a single frame). Of course, the "size" command would be necessary for a constant composition during all the sequence (but should not be compulsory while constant composition is only a option).
(The MtnViewJohn's sentence "Adding a concept of shape time so that the designer has explicit control over what animation frames a given shape is visible." is not so clear to me and maybe it tells something equivalent.)
- [MVJ] The idea of shape time is that a shape will have a notion of when it exists. When making an animation sequence CF will define a timeline for the animation (i.e., what is the time for the beginning of the first frame and the end of the last frame). The timeline will be divided evenly amongst the animation frames. When each frame is rendered only the shapes that exist during that frame will be drawn. If a shape exists for only part of the time slice of a frame then its alpha would be adjusted. The simplest way to specify shape time is for the shape to not exist before its birth time and after its death time, but exist and be fully opaque between birth and death. Or it could be more complicated: a shape could fade in and fade out using a linear or sigmoid function. We could even make the time of the animation frame available as a variable, so that a shape could change color or size from frame to frame. This would be computationally very expensive if we allowed rules (non-terminals) to depend on frame time. But allowing paths and primitive shapes (terminals) to depend on frame time would not be too bad.
- AK: instead of a global framecount variable why not have a local time variable? It could be more in the spirit of "context free". A "visibility profile" could be hard coded into the primitives and time "t" treated like a fourth dimension. For example, each animation could extend from t=0 to t=1 and each primitive appears only between t=0 and t=1, but "t" could be scaled and shifted just like the x,y,z coordinates, to control which slice of time it occupies. This only allows fixed position and hsva. So the next step is to allow the scaled time variable to be accessed in simple expressions (e.g. affine aka "linear") within the parameters. For the position variables, being dependent on an affine function of time is just a skew operation in four-dimensional spacetime, which means it could be done with matrix stuff at the parsing stage. For other variables like hsva, you need to store initial value and rate of change (intercept and slope) at the parse stage, and since the composition of two affine functions is affine, as you expand rules, subrules, etc these variables are still an affine function of t. Whether this is worth the effort I can only guess. I can see the potential pitfalls of taking this too far -- it would be most manageable if it all occurred after the expansion stage -- all this messing around with position, colour, etc only occurs in the render stage, rather than trying to feed back into the expansion stage. Once you make it too complicated, so that affects decisions made at the expansion stage, it would mess with expansion order, probabilities, bail-out and therefore which rules are expanded and which objects appear could be totally random, frame by frame, which would not be great. Kipling 18:16, 15 July 2009 (PDT)
- [MVJ] OK, accessing frame time within a shape transform or color is too hard with the current animation model where all of the shapes are computed and then frames are rendered afterward. Your simple time formulation, with a start time, end time, and time scale is a very sensible extension to cfdg animation in the current model. But we could make current frame time available if we re-evaluate the cfdg file for each frame. That way the frame time is simply a global constant. This new animation model would be pretty powerful and not very difficult to implement. But it would be pretty slow. However, if a cfdg file doesn't access the current frame time variable then animations can be rendered using the current animation model, which is faster. MtnViewJohn 16:09, 16 July 2009 (PDT)
- AK I had thought of frame-by-frame expansion. After all, it is possible to do something like this already with some shell scripting of the command-line version of CF. As you say, it would be slow. The other problem with this approach is that it could be difficult to generate designs which varied smoothly frame-by-frame without having completely deterministic designs. (This was my "random" comment above) Vary all the parameters from one frame to the next and suddenly all the expansion and random-number propagation happens in a different order with different parameters, with the result that each frame looks completely different to the previous one. That's why I thought of animation via placing the objects into 4-dimensional spacetime at the expansion stage, so that this doesn't happen. It is more restricted, but total freedom here could be just a mess. I can already think of some neat ways to animate limiting curves (snowflake, koch, etc) if this were the animation model. Kipling 19:50, 4 August 2009 (PDT)
- [MVJ] I think that the random-number propagation would be stable from frame to frame because the actual contents of the frame time variable will not get XORed into the random number seed. My goal for all variables (user generated and frame time) is that changing the value of a variable should not cause large changes to the random number propagation. We can smooth out frame boundary changes using the same code that we already have for zoomed animation. Or the user can put in a size directive (which can itself explicitly depend on frame time). MtnViewJohn 10:11, 4 October 2009 (PDT)
- I still have the feeling that the saturation, brightness and alpha should be free of the limits due to their default states. Well, I'm not sure I say it correctly and I know it's a point we have already discuss, but I really think it restrain the coloring manipulations. e.g:
startshape EG
rule EG {
DECREASE_ALPHA{x -2}
INCREASE_ALPHA{x 2}
DECREASE_SATURATION{x -2 y -3}
INCREASE_SATURATION{x 2 y -3}
DECREASE_BRIGHTNESS{x -2 y -6}
INCREASE_BRIGHTNESS{x 2 y -6}
}
rule DECREASE_ALPHA {
DECREASE_ALPHA{s .9 x .95 r 40 alpha -.1}
// IT'S WORKING
EG_SHAPE{}
}
rule INCREASE_ALPHA {
INCREASE_ALPHA{s .9 x .95 r 40 alpha .1}
// IT'S NOT WORKING
EG_SHAPE{}
}
rule DECREASE_SATURATION {
DECREASE_SATURATION{s .9 x .95 r 40 sat -.1}
// IT'S NOT WORKING
EG_SHAPE{}
}
rule INCREASE_SATURATION {
INCREASE_SATURATION{s .9 x .95 r 40 sat .1}
// IT'S WORKING
EG_SHAPE{}
}
rule DECREASE_BRIGHTNESS {
DECREASE_BRIGHTNESS{s .9 x .95 r 40 b -.1}
// IT'S NOT WORKING
EG_SHAPE{}
}
rule INCREASE_BRIGHTNESS {
INCREASE_BRIGHTNESS{s .9 x .95 r 40 b .1}
// IT'S WORKING
EG_SHAPE{}
}
rule EG_SHAPE {CIRCLE{alpha -.5 sat .5 b .5}}
FireLizzard's Wish List
- Functions - another type of rule that took parameters and returned a value without ever drawing anything.
SHiNKiROU's Wish List
- Ranges, for example,
{ r 60..80 } will set a random rotation between 60 and 80.
- This is exactly equivalent to
{ r rand(60, 80) } But I like your idea as a form of syntactic sugar. Lexically it is impossible to differentiate 60..80 from 60. .80 (i.e., the range from 60 to 80 from the number pair 60.0 and 0.80). But I can fix the lexer to scan it as a range. We can also have { r 70+/-10 h 70±10 } indicate centered ranges. The centered range operator would have an ASCII form, '+/-', and a Unicode form, '±'.
- Also, we want more metaprogramming features
- Interpolation, normally, we use x 1 to move linearly,
rule main {
SQUARE { }
main { x 1 }
}
However, it will be awesome of we can interpolate the transformations with experssion functions, so we can make sine wave or these complex curves.
interpolation SINE(aa) sin(aa / 10)
rule main {
SQUARE { }
main { x 1 * SINE(depth) }
}
The
depth
will increase by the recursion depth, and it can be pushed popped or resetted.
- You would be able to do this using the rule parameter feature:
rule main(depth) {
SQUARE { }
main (depth + 0.1) { x sin(depth) y 1 }
}
phonx's wish list
- Make it large print/ High resolution enable please
- Able to save variation macro and can re-run variation later on
- Auto sequence screen capture and export to avi, gif or swf
- network rendering and or distributed global Internet rendering for very complex rendering
- water mark to protect artist right
- Block base ide like scratch http://scratch.mit.edu/
Implementation
We are thinking that the best way to implement expressions with random numbers and rules with parameters is to compile the cfdg file to a virtual machine. Otherwise we would have to compile the cfdg file to a syntax tree and re-interpret the tree each time a rule is executed. Compiling to a VM just seems easier. If we use a JITting VM then we probably even get a speed boost. VM candidates are:
- .Net/Mono
- LLVM
- Roll our own, no JIT :(
- Java VM