/*
This example is a translation of the example "tree-shedding"
of the L-Studio software, see http://www.algorithmicbotany.org/
*/

module A(int dir, int del, float vig) extends NURBSSurface(SWEEP)
{
	{setShader (barkMat);}
}

module Q(float a, float d, float f) extends Vertex(0.05);
module Leaf(int age);
module Del(int count);

const int DEL = 16;
const float R0Angle = -20;
const float R1Angle = 32;
const float VDECR = 0.9;

protected void init ()
{
	n = 1;
	[
		Axiom ==> Mark Circle(1) A(1,0,2);
	]
}

float n = 1;

const Shader leafMat = shader("Leaf");
const Shader barkMat = shader("Bark");

public void derive ()
{
	float p = (2*n + 1) / (n * n);
	[
		A(dir,del,vig) ==>
			if (del > 0) (
				A(dir,del-1,vig)
			) else if (probability (p)) (
				Q(0.001,0,1) M(vig) RH(90)
				[	Mark Circle(1) RU(R1Angle*dir) A(dir,DEL,vig*VDECR) ]
					RU(R0Angle*dir) A(-dir,DEL,vig*VDECR)
			) else (
				Q(0.001,0,1) M(vig) RH(90)
				[	RU(R1Angle*dir)
					Leaf(53) Q(0.001,0,2.5) leaf(0.9, 0.5).(setMaterial(leafMat))
				]
					RU(R0Angle*dir) A(-dir,DEL,vig*VDECR)
			);
		
		q:Q ::>
			{
				int n = 0;
				float sa = 0, sd = 0, sf = 0;
				for ((* q -minDescendants-> Q(a,d,f) *))
				{
					n++;
					sa += a; sd += d; sf += f;
				}
				if (n > 0)
				{
					q[scale] = Math.max (q[scale], Math.sqrt(sa + sd));
					q[a] = sa;
					q[d] = sd;
					q[f] = sf - 1;
				}
			}

		l:Leaf Q ==>
			if (l[age] > 0) {
				l[age] :+= -1;
				break;
			} else (
				Q(0,0.001,0) Del(5)
			);

		d:Del ==>> if (d[count] > 0) {d[count] :+= -1; break;};
	]
	n += 1f / DEL;
}

public void grow300 ()
{
	for (apply (300)) derive ();
}
