I’ve been continuing to work on the scripting language for generating procedural objects. During the last article I introduced the basics of Wooscript. There were a few things that weren’t quite right with the way various adjustments worked together.

This is an example of a simple script that builds a curving row of cubes. The adjust(rz, +10) adds 10 degrees to the roll that’s in the stack. As each cube is generated the rotation matrix is set using roll, pitch and yaw.

rule main { repeat (r1, 10) } rule r1 { call(box) adjust(y, +1.2) adjust(rz, +10) }

// Wooscript 2.1 rule main { repeat (10) { box pos.y += 1.2 rz += 10 } }

This looks good for single rotations, and now I want to make a wall of these curved cubes.

To do that I change the call(box) operation to repeat instantiation of another rule r2, which then adds the cube.

The change to the code is really pretty simple, and now I have a wall of cubes.

rule main { repeat (r1, 10) } rule r1 { repeat(r2, 10) adjust(y, +1.2) adjust(rz, +10) } rule r2 { call(box) adjust(z, +1.2) }

// Wooscript 2.1 rule main { repeat (10) { {repeat (10) { box pos.z += 1.2 }} pos.y += 1.2 rz += 10 } }

So far so good, but what I really want to do is make each of those extra rows of Cubes curve away from the centre of the circle. This will give a 3d fan instead of a flat wall.

To modify the code it’s a simple case of adding adjust(ry, +10) into the second rule. This should now rotate the cube around the y axis and leave a big 3d fan, but it doesn’t quite work…

rule main { repeat (r1, 10) } rule r1 { repeat(r2, 10) adjust(y, +1.2) adjust(rz, +10) } rule r2 { call(box) adjust(ry, +10) adjust(z, +1.2) }

// Wooscript 2.1 rule main { repeat (10) { {repeat (10) { box pos.z += 1.2 ry += 10 }} pos.y += 1.2 rz += 10 } }

What happens is that each rotation occurs as if the cubes hadn’t been rotated on the other axis, so they all follow the same curve around the y axis.

What we really want is to change the code so that the rotations occur relative to previous rotations. This is probably making no sense at all right now, so I’ll just show you the picture of what I was after.

Much better. The way I did this was to keep track of the rotation matrix for each cube as it’s transformed. For further calls the rotation matrix itself is rotated using roll, pitch and yaw, which leads to rotations that occur relative to each other.

It’s now a simple thing to extend the ring all the way round, switch on the pathtracer and generate the final render for this article.

rule main { repeat (r1, 20) } rule r1 { repeat (r2, 20) adjust(y, +1.2) adjust(rz, +10) } rule r2 { call(box) adjust(z, +1.2) adjust(ry, +10) adjust(rz, -5) }

// Wooscript 2.1 rule main { repeat (20) { {repeat (20) { box pos.z += 1.2 ry += 10 rz -= 5 }} pos.y += 1.2 rz += 10 } }