/* Parametric Surface
 * Create a bunch of polys in LightWave
 * By Fredrik Öhrn
 *
 */

numeric digits 6

call addlib "LWModelerARexx.port", 0
call addlib "rexxmathlib.library", 0, -30, 0

signal on error
signal on syntax

dfile = 'ENV:PSurf.state'
pfile = ''

/* Defaults */
umin = 0
umax = 6.283
ustep = 20
vmin = 0
vmax = 6.283
vstep = 10
ptype = 2
FofUV.0 = "(1+.5*cos(v))*cos(u)"
FofUV.1 = "(1+.5*cos(v))*sin(u)"
FofUV.2 = ".5*sin(v)"

if (exists(dfile)) then do
	if (~open(state, dfile, 'R')) then break
	parse value readln(state) with umin umax ustep vmin vmax vstep ptype .
	do i = 0 to 2
		FofUV.i = readln(state)
	end i
	call close state
end

do forever
	call req_begin 'Parametric Surface'

	id_mes = req_addcontrol("Make Surface using", 'T', "custom equations X(u, v), Y(u, v), Z(u, v)")
	id_umin = req_addcontrol("u min ", 'n', 0)
	id_umax = req_addcontrol("u max ", 'n', 0)
	id_ustep = req_addcontrol("No of steps", 'n')
	id_vmin = req_addcontrol("v min ", 'n', 0)
	id_vmax = req_addcontrol("v max ", 'n', 0)
	id_vstep = req_addcontrol("No of steps", 'n')
	id_fn.0 = req_addcontrol("X(u, v) = ", 'S', 40)
	id_fn.1 = req_addcontrol("Y(u, v) = ", 'S', 40)
	id_fn.2 = req_addcontrol("Z(u, v) = ", 'S', 40)
	id_ptype = req_addcontrol("Create ", 'CH', "Points Polys Quads")
	id_action = req_addcontrol("", 'CH', "Use Load Save")
	id_file = req_addcontrol("Parameter file ", 'T', pfile)

	call req_setval id_umin, umin
	call req_setval id_umax, umax
	call req_setval id_ustep, ustep
	call req_setval id_vmin, vmin
	call req_setval id_vmax, vmax
	call req_setval id_vstep, vstep
	do i = 0 to 2
		call req_setval id_fn.i, FofUV.i
	end i
	call req_setval id_ptype, ptype
	call req_setval id_action, 1

	if (~req_post()) then do
		call req_end
		exit
	end

	umin = req_getval(id_umin)
	umax = req_getval(id_umax)
	ustep = req_getval(id_ustep)
	vmin = req_getval(id_vmin)
	vmax = req_getval(id_vmax)
	vstep = req_getval(id_vstep)
	do i = 0 to 2
		FofUV.i = req_getval(id_fn.i)
	end i
	ptype = req_getval(id_ptype)
	action = req_getval(id_action)

	/* Load params */
	if action = 2 then do
		pfile = getfilename("Load Parameter File", '', pfile)
		if fil ~= '(none)' then do
			if (~open(state, pfile, 'R')) then break
			parse value readln(state) with umin umax ustep vmin vmax vstep ptype .
			do i = 0 to 2
				FofUV.i = readln(state)
			end i
			call close state

			call req_setval id_umin, umin
			call req_setval id_umax, umax
			call req_setval id_ustep, ustep
			call req_setval id_vmin, vmin
			call req_setval id_vmax, vmax
			call req_setval id_vstep, vstep
			do i=0 to 2
				call req_setval id_fn.i, FofUV.i
			end i
			call req_setval id_ptype, ptype
			call req_setval id_action, 1
		end
	end

	/* Save params */
	if action = 3 then do
		pfile = getfilename("Save Parameter File", '', pfile)
		if pfile ~= '(none)' then do
			if (~open(state, pfile, 'W')) then break
			call writeln state, umin umax ustep vmin vmax vstep ptype
			do i = 0 to 2
				call writeln state, FofUV.i
			end i
			call close state
			call req_setval id_action, 1
		end
	end
	call req_end

	if action ~= 1 then iterate

	if (open(state, dfile, 'W')) then do
		call writeln state, umin umax ustep vmin vmax vstep ptype
		do i=0 to 2
			call writeln state, FofUV.i
		end i
		call close state
	end

	call meter_begin (ustep+1)*(vstep+1), 'Generating Points'
	call add_begin

	du = (umax-umin)/ustep
	dv = (vmax-vmin)/vstep
	do u=umin to umax by du
		do v=vmin to vmax by dv
			interpret 'X='||FofUV.0
			interpret 'Y='||FofUV.1
			interpret 'Z='||FofUV.2
			call add_point(X Y Z)
			call meter_step
		end v
	end u
	call meter_end

	if ptype > 1 then do
		call meter_begin (ustep+1)*(vstep+1), 'Adding Polygons'
		if ptype = 2 then do
			do u = 1 to ustep*(vstep+1) by vstep+1
				do v = u to u+vstep-1
					call add_polygon(v||' '||(v+1)||' '||(v+vstep+2)||' '||(v+vstep+1))
					call meter_step
				end v
			end u
		end
		if ptype = 3 then do
			do u = 1 to ustep*(vstep+1) by vstep+1
				do v = u to u+vstep-1
					call add_quad(v||' '||(v+1)||' '||(v+vstep+2)||' '||(v+vstep+1))
					call meter_step
				end v
			end u
		end
		call meter_end
	end
	call add_end
	call end_all
	exit

end /* Forever */

syntax:
error:
	call end_all
	call notify(1,'!Rexx Script Error','@'ErrorText(rc),'Line 'SIGL)
	exit
