WooScript 2.0

This is going to be a fairly long article as I’ve been busy over the past few weeks. Along with rebuilding my sceneediting application and refactoring the interface to the raytracer, I’ve also started again with Wooscript and designed the language with far more complex syntax.

To start with lets talk about one of the bigger jobs, scrapping my old scene editor and starting again. When I started this project a few years ago I wanted a simple editing application with a topdown view, drag and drop scene editing, and a preview window. This application has served me well while developing the raytracing engine (now called the Wootracer). However, it has added a bit of an awkward interface for developing Wooscript. To add a scripting object I click a button named “WooScript”, this adds a circle into the top down view. Double clicking the circle brings up the scripting window from where you can write and compile your program. Once this is done you close that dialogue and click preview to have a quick look at how the script came out. Here’s an example screenshot from the old “SceneDesigner”…

SceneDesigner

The original scenedesigner with the wooscript button and basic preview window

In the new scene editor I want the application to use the scripting language as the primary interface. Instead of an overhead view I’ve simplified it right down to a scripting panel, and a preview panel. Below the preview panel there’s plenty of place for configuration options when I get round to adding them back in. I’m going to retain the final render window as I want to do the gradual refinement method for displaying the results of the pathtracer, setting exposure, etc.

Image of Wooscripter v0.1

The WooScripter application

This application is still looking very alpha, but hopefully I can get it up to beta status fairly quickly and add a download link to the site. At that point you’ll be able to start playing with the new version of WooScript; Wooscript 2.0.

Wooscript 2.0

You may remember some of my posts about Wooscript a while ago, where you could build an object design using a list of simple functions. For example;

adjust(x, =0)
repeat(r1, 10)
adjust(x, +1:2)

The slightly neat bit of the language was the way numbers were represented. Instead of only allowing fixed numbers (1, 2, 3, etc.), the Wooscript representation of numbers allowed 3 types of number to be specified. Single number (1, 2, 3, …), range (1:2, 2:3, 1:3, …) and option (1|2, 2|3, etc.). Within an adjust statement you’d specify the state variable to change (x, y, z, …) and an operator (+, -, *, …) with a number. This made it a lot easier to add randomness than requiring if/else or rand() type generators.

Beyond that there really isn’t much complexity to the language. In particular you couldn’t use mathematical functions (cos, sin, …), or cross assign variables (x = y, …) or arithmetic instructions (x = 1/7). And of course, every statement that modified a state variable had to use adjust().

With the new language I’m keen to make the syntax more expressive so that you can use state variables as sources for operations. I’d also like to support a full set of mathematical operators so you don’t need to hardcode the square root of 2, etc. Instead you can just put sqrt(2).

The parser for this new type of syntax is considerably more complicated than for the simple function based approach I originally took. In the past the parsing steps were very simple. First off look for

rule [name] {}

This defines a rule. Within the braces there will be a number of statements of the form

[functionname] ( [arguments] )

Each type of function had it’s own class which understood the argument format and handled the logic required by the call. There were ~8/9 different functions with the only complex one being adjust() which allowed for all state modification. The entire language parser, interpreter and scene generator was about 800 lines of code.

For the new language I’ve kept the global namespace the same

rule [name] {}

But within the rule there is now a grammar for all possible statements. The grammar is something like this…

rule rulename { statement* }
statement = floatvar aop floatexpr | vecvar aop vecexpr | nfun ( args )
args = (rulename|floatexpr|vecexpr)*
floatexpr = ( floatexpr ) | floatexpr op floatexpr | num | ffun(args) | floatvar
num = 0.x | vec.sel
vecexpr = ( vecexpr ) | vec op vecexpr | vfun ( args ) | vecvar
vec = vec | vec.rep

floatvar = floating point variable
vecvar = vector variable
floatexpr = an expression that results in a floating point value
vecexpr = an expression that results in a vector
nfun = a function with a null return type
ffun = a function with a float return type
vfun = a function with a vector return type
num = a floating point number, or a vector with a selector (x, y, z, r, g, b)
vec = a vector or a vector with a replication argument (xxx, yyy, zyx, etc)
aop = assignment operator
op = general operator

As you’ll note there is now a concept of two “types” within the language. First off the floating point values which are used for rotations, recursions, etc. But you can also use these floating point values to build a vector using the vec(f,f,f) constructor. This allows for a lot more flexibility in the way code is written. The state object itself also uses vectors to represent the obvious triple parameters like diff (diffuse colour), spec (specular colour) and notably position (pos).

For example, let’s say that I want to increment the y position by 1. In Wooscript 1.0 this looked like

adjust(y, +1)

In Wooscript 2.0 I can do this in many ways.

pos.y += 1
pos.y = pos.y + 1
pos += vec(0,1,0)
pos = pos + vec(0,1,0)
pos.y += cos(0)

The ability to cross assign variables has opened up a number of cool possibilities for tying state together. For example, lets say that I want the colour of the objects to get brighter as they get “higher” in the scene.

diff = vec(0, pos.y * 0.1, 0)

And if I want to tie the specular colour to the diffuse colour…

spec = diff

I’m hoping this will lead to some really interesting scenes once I get my head around what is actually possible with the new syntax. And hopefully it’ll lead to some really really interesting stuff when I’ve got the application ready for download so that other people can use it too! :)

For now I’m still in the middle of implementing all the different types of operators, functions, assignment operators, etc. etc.. but hopefully I’m only 4-6 hours of drudge work away from having a first downloadable beta.

Incidentally, and I’ll talk about this another time, there is hideous complexity in typing within language design. It makes compilers much much harder. i.e. I am enjoying this new challenge, but I will continue to refer to it as a challenge.

3 Responses

  1. Sam Swain says:

    I may have said this before, but this object grammar reminds me of this… http://procworld.blogspot.co.uk/2012/02/real-men-dont-draw-buildings.html Sorry if I’m repeating myself D.

  2. Salvatore says:

    Hello,

    Where can I download WooTracer and WooSCript ?

    Regards

  3. Salvatore says:

    Oops, i should have read your post entirely …
    Sorry

Leave a Reply

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

Spam Protection *

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=""> <strike> <strong>