I started out looking into a variety of different tree fractals, but one of the earliest classes of tree fractal I found has kept me pretty busy. So today I’m going to go over the Pythagoras tree and some interesting 3d extensions that you can make to the basic fractal.

The traditional Pythagoras tree uses a sequence of squares to build up a simple fractal. The first square is placed at the base, and the next two are placed on either side of a symmetrical right angled triangle. The basic wooscript for this is pretty simple so here comes iteration 1 of a Pythagoras tree.

rule main { adjust(y, +1) adjust(scale, *0.707106781186, *0.707106781186, *0.707106781186) push() adjust(rz, -45) adjust(y, +0.5) call(box) pop() adjust(rz, +45) adjust(y, +0.5) call(box) }

// Wooscript 2.1 (current syntax) box pos.y += 1 scale *= vec(0.707106781186,0.707106781186,0.707106781186) { rz -= 45 pos.y += 0.5 box } { rz += 45 pos.y += 0.5 box }

What makes this a fractal, is that you can continue to apply this pattern to each of the sub-squares that have been added. The script needs to be changed a bit so it calls itself recursively. To do this the main pattern is moved into a rule called “r1″ and this is called instead of the box primitive. To control the iterations of the fractal you just adjust the number of recursions you want the system to allow using adjust(recursions, =10).

So here goes with the fractal going on one more iteration, and then two more iterations.

rule main { adjust(recursions, =2) call (r1) } rule r1 { call(box) adjust(y, +1) adjust(scale, *0.707106781186, *0.707106781186, *0.707106781186) push() adjust(rz, -45) adjust(y, +0.5) call(r1) pop() adjust(rz, +45) adjust(y, +0.5) call(r1) }

// Wooscript 2.1 (current syntax) rule main { recursions = 2 r1 } rule r1 { box pos.y += 1 scale *= vec(0.707106781186,0.707106781186,0.707106781186) { rz -= 45 pos.y += 0.5 r1 } { rz += 45 pos.y += 0.5 r1 } }

And finally lets just whack the iterations right up and have a look at a whole row of Pythagoras trees at increasing iteration counts.

This is all a lot of fun so far, but these trees do all look a bit too regular for me. A standard extension to the Pythagoras tree is to swap the 45 degree angles on the corners so that we’re building trees using a different right angled triangle. It seems fitting to use the famous 3, 4, 5 sided triangle to build a tree instead of the current symmetrical building block.

Let’s take a look at iteration 1 of the 3,4,5 fractal.

rule r1 { call(box) adjust(y, +1) adjust(diff, *1, *0.88, *0.88) push() adjust(scale, *0.6, *0.6, *0.6) adjust(rz, -53.13) adjust(y, +0.625) call(r1) pop() adjust(scale, *0.8, *0.8, *0.8) adjust(rz, +36.87) adjust(y, +0.375) call(r1) }

// Wooscript 2.1 (current syntax) rule r1 { box pos.y += 1 { scale *= vec(0.6,0.6,0.6) rz -= 53.13 pos.y += 0.625 r1 } { scale *= vec(0.8,0.8,0.8) rz += 36.87 pos.y += 0.375 r1 } }

And once we iterate that a few times we get quite a pretty little fractal.

This is definitely a bit cuter than the bog standard fractal, but it’s still not making much use of the 3d side of things. With a number of fractal trees I’ve added a 30 degree twist on each iteration, but with this fractal it’d break that simple pythagoras triangle which the fractal is named after, so instead of rotating the fractal step, I’m going to split the cube into two, and rotate halfway along the cube.

That gives you an interesting fractal which makes much better use of the 3d nature of the renderer.

The code does get a little bit more complex though…

rule r1 { adjust(scaley, *0.5) call(box) adjust(scaley, *2) adjust(y, +0.5) adjust(ry, +30) adjust(scaley, *0.5) call(box) adjust(scaley, *2) adjust(y, +0.5) adjust(diff, *1, *0.88, *0.88) push() adjust(scale, *0.6, *0.6, *0.6) adjust(rz, -53.13) adjust(y, +0.625) call(r1) pop() adjust(scale, *0.8, *0.8, *0.8) adjust(rz, +36.87) adjust(y, +0.375) call(r1) }

// Wooscript 2.1 (current syntax) rule r1 { { scale.y *= 0.5 box } pos.y += 0.5 ry += 30 { scale.y *= 0.5 box } pos.y += 0.5 { scale *= vec(0.6,0.6,0.6) rz -= 53.13 pos.y += 0.625 r1 } { scale *= vec(0.8,0.8,0.8) rz += 36.87 pos.y += 0.375 r1 } }

So that just leaves me to do a few feature renders to show off the fractal.

First up another angle with ambient occlusion turned on, this shows a bit more colour gradient in the shadows.

And finally a darker render with full path tracing enabled.