 /*************************************************************\
/                                                               \                              
             Plants V2.0, by Reinhard Grams © 1995
\                                                               / 
 \*************************************************************/

StartMacro:

	call InitMacro("Plants",1)
	call SetParms()
	call DoTheJob()
	call ExitMacro()

/**************************************************************/

DoTheJob:

    source_layer=curlayer()
	result_layer=LWE_GetEmptyLayer(source_layer)
	if (result_layer=0) then call ExitMacro(NO_LAYER_ERR)

	call InitPlants()
	
	do tree=1 to trees
		do trun=1 to truncs
			call Plant1(obj_points,0,0,0,range_x,range_y,range_z)
			call mergepoints()
			call unifypols()
		end
		if (trees>1) then do
			call save(LWE_AddExt(file_name,tree))
			call cut(); call cut()
		end
	end

	if (verbose & trees>1) then do
		call notify(1,trees vmes.language)
	end
	
	return

/**************************************************************/

InitPlants:

	call randu(random_seed)
	range_x=end_range_x-start_range_x
	range_y=end_range_y-start_range_y
	range_z=end_range_z-start_range_z

	do i=0 to obj_points+1; ffact.i=fact(i); end
	do i=1 to obj_points+1
        j=i-1; k=obj_points-j
		fcoeff.i=ffact.obj_points/(ffact.j*ffact.k)
	end

	return

/**************************************************************/

Plant1: ARG obj_points,x,y,z,range_x,range_y,range_z

	wx=randu()*0.5+0.25
	wz=randu()*0.5+0.25

	px.1=x+(randu()*2-1)*jitter; py.1=y; pz.1=z+(randu()*2-1)*jitter
	do p=2 to obj_points
		l=p-1; f=(p-1)/(obj_points-1)
		gy=LWE_GetCurveVal(f,coeff.2)
		gxz=LWE_GetCurveVal(f,coeff.1)*sin(f*PI*gy)
		px.p=px.l+((randu()-0.5)*range_x)*wx*gxz*grow_x
		py.p=py.l+(randu()*range_y+start_range_y)*grow_y/(obj_points-1)
		pz.p=pz.l+((randu()-0.5)*range_z)*wz*gxz*grow_z
	end

	call surface("Trunk")
	call add_begin()
	step=1/(obj_points-1); fact=0
    do point=1 to obj_points
		nx.point=0; ny.point=0; nz.point=0
        t=(fact*fact)*exp_fact+fact*(1-exp_fact)
		do i=1 to obj_points+1
			if (i>obj_points) then index=i-1; else index=i
			f=fcoeff.i*(t**(i-1)*(1-t)**(obj_points-(i-1)))
			nx.point=nx.point+px.index*f
			ny.point=ny.point+py.index*f
			nz.point=nz.point+pz.index*f
		end
		call add_point(nx.point ny.point nz.point)
    	fact=fact+step
	end
	do p=1 to obj_points-1; call add_polygon(p p+1); end
	call add_end()

	max_height=abs(py.obj_points-py.1)
	max_dist=max_height/2

	if (min_leafs>0) then do
		call add_begin()
		do p1=1 to obj_points-1; p2=p1+1
			a1=LWE_Heading(ny.p2-ny.p1,nz.p2-nz.p1)*PID180
    		a2=LWE_Heading(nz.p2-nz.p1,nx.p2-nx.p1)*PID180
    		a3=LWE_Heading(ny.p2-ny.p1,nx.p2-nx.p1)*PID180
	   		rotate=LWE_InitRotate(a1,a2,-a3)
			ls=LWE_GetCurveVal(abs(ny.p2)/max_height,coeff.3)
			if (ls>0) then do
		  		call Leafs1(1,nx.p2,ny.p2,nz.p2,min_leafs,max_leafs,,
					ls*size_fact,random_fact)
			end
	   		rotate=LWE_RemoveRotate(rotate)
		end
		call add_end()
    end

	return

/**************************************************************/

Leafs1: PROCEDURE EXPOSE PIM2 a1 a2 a3 rotate stop_leafs 
		ARG iter,px,py,pz,min_leafs,max_leafs,size,rand_fact

	po=add_point(px py pz)
	leafs=trunc(min_leafs+randu()*(max_leafs-min_leafs))
	do l=1 to leafs
		f=l/leafs*PIM2
		x=sin(f)*size
        y=randu()*size*rand_fact
        z=cos(f)*size
		parse value LWE_PointsRotate(rotate,x,y,z) with x y z .
		p=add_point(px+x py+y pz+z)
		call surface("Leafs"||LWE_CustExt(iter,2))
		call add_polygon(po p)
		call surface("Tops"||LWE_CustExt(iter,2))
		call add_polygon(p)
		if (min_leafs>stop_leafs) then do
			call Leafs1(iter+1,px+x,py+y,pz+z,,
			trunc(min_leafs*0.66),trunc(max_leafs*0.66),,
			size*0.33,rand_fact/2)
		end
	end

    return

/**************************************************************/

Bezier: ARG obj_points, new_points

	do i=0 to obj_points+1
        ffact.i=fact(i)
    end
	do i=1 to obj_points+1
        j=i-1; k=obj_points-j
		coeff.i=ffact.obj_points/(ffact.j*ffact.k)
	end

	call surface("Trunk")
	call add_begin()
	step=1/(new_points-1)
    do point=1 to new_points
		nx.point=0; ny.point=0; nz.point=0
    	fact=(point-1)/(new_points-1)
        t=(fact*fact)*exp_fact+fact*(1-exp_fact)
		do i=1 to obj_points+1
			if (i>obj_points) then index=i-1; else index=i
			f=coeff.i*(t**(i-1)*(1-t)**(obj_points-(i-1)))
			nx.point=nx.point+px.index*f
			ny.point=ny.point+py.index*f
			nz.point=nz.point+pz.index*f
		end
		call add_point(nx.point ny.point nz.point)
	end
	do p=1 to new_points-1	
		call add_polygon(p p+1)
	end
	call add_end()
	
	return

/**************************************************************/

InitVariables:

	PI=3.14159265358
	PIM2=PI*2
	PID180=PI/180

	trees=1
	truncs=1
	random_seed=4713
	obj_points=15
    exp_fact=0.5
	grow_x=3.3
	grow_y=10.0
	grow_z=3.3
    start_range_x=0.5
	start_range_y=0.5
	start_range_z=0.5
	end_range_x=2.5
	end_range_y=1.5
	end_range_z=2.5
    min_leafs=3
    max_leafs=7
	stop_leafs=3
	size_fact=1
	random_fact=0.5
	jitter=0.005
	coeff.1=""
	coeff.2=""
	coeff.3=""

	rmes.0="Sequence Basename"
	rmes.1="Sequenz Basisnamen"
	vmes.0="Plants generated"
	vmes.1="Pflanzen generiert"

	return

/**************************************************************/

SetParms:

	call Requester1()
	call Requester2()
	call Requester3()
	call Requester4()

	if (trees>1) then do
		file_name=SelectFile(rmes.language,"3d:Objects",1)
		if (file_name="(none)") then call ExitMacro()
	end

	call SaveConfig()

	return

/**************************************************************/

Requester1:

	call req_begin(macro_name)

	id_01=req_addcontrol("Plants", 'n')
	id_02=req_addcontrol("Truncs", 'n')
	id_03=req_addcontrol("Random Seed", 'n')
	call req_setval(id_01,trees)
	call req_setval(id_02,truncs)
	call req_setval(id_03,random_seed)
	if (~req_post()) then call ExitMacro()

	trees=trunc(req_getval(id_01))
	truncs=trunc(req_getval(id_02))
	random_seed=req_getval(id_03)
	call req_end()

	if (trees<1) then trees=1
	if (truncs<1) then truncs=1
	if (random_seed=0) then random_seed=time('s')

	return

/**************************************************************/

Requester2:

	call req_begin(macro_name": Plant")

	id_01=req_addcontrol("Points", 'n')
	id_02=req_addcontrol("Exp Factor %", 'n')
	id_03=req_addcontrol("Jitter Factor %", 'n')
	id_04=req_addcontrol("Grow Factor XYZ", 'v',1)
	id_05=req_addcontrol("Start Range XYZ", 'v',1)
	id_06=req_addcontrol("End Range XYZ", 'v',1)

	call req_setval(id_01,obj_points)
	call req_setval(id_02,exp_fact*100)
	call req_setval(id_03,jitter*100)
	call req_setval(id_04,grow_x grow_y grow_z)
	call req_setval(id_05,start_range_x start_range_y start_range_z)
	call req_setval(id_06,end_range_x end_range_y end_range_z)
	if (~req_post()) then call ExitMacro()

	obj_points=trunc(req_getval(id_01))
	exp_fact=req_getval(id_02)/100
	jitter=req_getval(id_03)/100
	parse value req_getval(id_04) with grow_x grow_y grow_z .
	parse value req_getval(id_05) with start_range_x start_range_y start_range_z .
	parse value req_getval(id_06) with end_range_x end_range_y end_range_z .
	call req_end()

	if (obj_points<2) then obj_points=2
	
	return

/**************************************************************/

Requester3:

	call req_begin(macro_name": Leafs")

	id_01=req_addcontrol("Min Leafs", 'n')
	id_02=req_addcontrol("Max Leafs", 'n')
	id_03=req_addcontrol("Stop Leafs", 'n')
	id_04=req_addcontrol("Size Fact", 'n')
	id_05=req_addcontrol("Random Infl %", 'n')

	call req_setval(id_01,min_leafs)
	call req_setval(id_02,max_leafs)
	call req_setval(id_03,stop_leafs)
	call req_setval(id_04,size_fact)
	call req_setval(id_05,random_fact*100)
	if (~req_post()) then call ExitMacro()

	min_leafs=req_getval(id_01)
	max_leafs_seed=req_getval(id_02)
	stop_leafs=req_getval(id_03)
	size_fact=req_getval(id_04)
	random_fact=req_getval(id_05)/100
	call req_end()

	return

/**************************************************************/

Requester4:

	coeff.1=LWE_CurveRequester("Grow Form",coeff.1)
	if (coeff.1="") then call ExitMacro()

	coeff.2=LWE_CurveRequester("Segment Distribution",coeff.2)
	if (coeff.2="") then call ExitMacro()

	if (min_leafs>0) then do
		coeff.3=LWE_CurveRequester("Leaf Size",coeff.3)
		if (coeff.3="") then call ExitMacro()
	end

	return

/**************************************************************/

SaveConfig:

	success=open(state,config,'W')
	if (success) then do
		call writeln(state, obj_points jitter,
			exp_fact grow_x grow_y grow_z,
			start_range_x start_range_y start_range_z,
			end_range_x end_range_y end_range_z,
		    min_leafs max_leafs stop_leafs,
			size_fact random_fact trees random_seed truncs )
		do s=1 to 3; call writeln(state,coeff.s); end
		s=1; do while (s<=used_file_sel_nrs)
			writeln(state,sel_drawer.s); writeln(state,sel_file.s); s=s+1
		end
		call close state
	end
	return success

/**************************************************************/

LoadConfig:

    success=open(state,config,'R')
	if (success) then do
    	parse value readln(state) with obj_points jitter,
			exp_fact grow_x grow_y grow_z,
			start_range_x start_range_y start_range_z,
			end_range_x end_range_y end_range_z,
		    min_leafs max_leafs stop_leafs,
			size_fact random_fact trees random_seed truncs .
		do s=1 to 3; coeff.s=readln(state); end
		s=1; do while (s<=used_file_sel_nrs)
			sel_drawer.s=readln(state); sel_file.s=readln(state); s=s+1
		end
    	call close state
	end
	return success

/**************************************************************/
/**************************************************************/
			
InitMacro: PARSE ARG macro_name, used_file_sel_nrs

	signal on error; signal on syntax
	mathlib="rexxmathlib.library"
	rexxlib="rexxsupport.library"
	supplib="LWE.library"
	modport="LWModelerARexx.port"

	if (~show('L',rexxlib)) then do
		if (~addlib(rexxlib,0,-30,0)) then exit 14
		if (~show('L',rexxlib)) then exit 14
	end
	if (~show('L',mathlib)) then do
		if (~addlib(mathlib,0,-30,0)) then exit 14
		if (~show('L',mathlib)) then exit 14
	end
	if (~show('L',supplib)) then do
		if (~addlib(supplib,0,-30,0)) then exit 14
		if (~show('L',supplib)) then exit 14
	end
	p=addlib(modport,0); if (p!=0) then exit 14

	parse value LWE_GetSettings(macro_name) with,
		config selection temp language help verbose digits .
	call InitVariables(); success=LoadConfig()
	if ((help=1 & ~success) | help=2) then do
		t=LWE_Help(macro_name); if (t=3) then call ExitMacro()
	end
	return

/**************************************************************/

ExitMacro: PARSE ARG status, add_string

	call end_all()
	if (status~="") then do
		t=LWE_ErrorRequester(macro_name,status,add_string)
		if (t=1) then signal StartMacro
		if (t=2) then t=LWE_Help(macro_name)
		if (t=1) then signal StartMacro
	end
	call remlib(modport); exit 0

/**************************************************************/

error:; syntax:
	t=Notify(1,'!Rexx Script Error','@'ErrorText(rc),'Line 'SIGL)
	call ExitMacro()

/**************************************************************/

SelectFile: PROCEDURE EXPOSE sel_drawer. sel_file.
	PARSE ARG title,def_drawer,sel_nr

	if (sel_drawer.sel_nr=="SEL_DRAWER."||sel_nr) then do
		sel_drawer.sel_nr=def_drawer; sel_file.sel_nr=""; 
	end
	file=getfilename(title,sel_drawer.sel_nr,sel_file.sel_nr)
	if (file="(none)") then return file
	sel_drawer.sel_nr=LWE_Drawer(file)
	sel_file.sel_nr=LWE_File(file)
	return file

/**************************************************************/
