/* CMD: PClone Deluxe * Particle Clone Deluxe version 1.4 by GLYPH (03/15/1997) E-Mail: y82s1@unb.ca * Clones active layer data at offsets given by points in background layers and places clones in first empty layer. * Clones points or polygons * Optional boolean union of clones - good for crater stencils & bubbles * Random Scaling & Rotation - good for asteroids & grass * Lock Scale factors to X for random yet proportionally correct clones * 2-D Radial Alignment of clones - good for making things stick out in 2-D * 3-D Radial Alignment of clones - good for making things stick out in 3-D * User-definable Radial Alignment Center from which things stick * Global scaling function dependant on distance from Radial Center * Uses LW3.1 commands for compatability (3.5 commands would have been easier) */ call addlib("LWModelerARexx.port",0) signal on error signal on syntax call addlib("rexxmathlib.library",0,-30,0) call addlib("rexxsupport.library",0,-30,0) call main exit syntax: error: t=Notify(1,'!Rexx Script Error','@'ErrorText(rc),'Line 'SIGL) if (mxx_add) then call remlib(mxx) exit MAIN: call random(,,time('s')) syscode = "Particle Clone Deluxe" tmpnam = "t:pclone.tmp" pi=3.1415926385897932384626 /* Store current and background layers and first empty layer. */ fg = curlayer() bg = curblayer() emp = emptylayers() if (words(emp) = 0) then do ok = notify(2,'!No empty layer.','Clones will be placed','on current layer.','Original will be','!nuked.') if ok = 0 then return tlt = 0 end if (words(emp) > 0) then do tl = word(emp,1) tlt = 1 end filnam = 'ENV:PCDLX.state' version = 'PCloneDeluxe1.5' slm = 2 clm = 0 rrx = 1 rry = 1 rrz = 1 rmp = 360 360 360 rcn = 0 0 0 tdr = 0 rsx = 1 rsy = 1 rsz = 1 globs = '1' smp = 30 30 30 if (exists(filnam)) then do if (~open(state, filnam, 'R')) then break if (readln(state) = version) then do parse value readln(state) with slm clm rrx rry rrz rsx rsy rsz tdr globs = readln(state) parse value readln(state) with rmp parse value readln(state) with rcn parse value readln(state) with smp end call close state end rotops="None Random Radial" scalops="None Random Fixed" call req_begin 'Particle Clone Deluxe 1.4' rq_sm = req_addcontrol("Clone", CH, 'Points Polygons') rq_cm = req_addcontrol("Unify Clones", B) rq_rx = req_addcontrol("Rotation on X", CH, rotops) rq_ry = req_addcontrol(" Y", CH, rotops) rq_rz = req_addcontrol(" Z", CH, rotops) rq_rmp = req_addcontrol("Max Random Rotations", V, 0) rq_rcn = req_addcontrol("Radial Center", V, 1) rq_tdr = req_addcontrol("3-D Radial Alignment", B) rq_sx = req_addcontrol("Scaling on X", CH, scalops) rq_sy = req_addcontrol(" Y", CH, scalops' Lock_to_X') rq_sz = req_addcontrol(" Z", CH, scalops' Lock_to_X') rq_gs = req_addcontrol("Scaling funtion (of d)", S, 40) rq_smp = req_addcontrol("Max Scale Percentages", V, 0) call req_setval rq_sm, slm, 2 call req_setval rq_cm, clm, 0 call req_setval rq_rx, rrx, 1 call req_setval rq_ry, rry, 1 call req_setval rq_rz, rrz, 1 call req_setval rq_rmp, rmp, 360 360 360 call req_setval rq_rcn, rcn, 0 0 0 call req_setval rq_tdr, tdr, 0 call req_setval rq_sx, rsx, 1 call req_setval rq_sy, rsy, 1 call req_setval rq_sz, rsz, 1 call req_setval rq_gs, globs, "1" call req_setval rq_smp, smp, 30 30 30 if (~req_post()) then do call req_end exit end slm = req_getval(rq_sm) clm = req_getval(rq_cm) rrx = req_getval(rq_rx) rry = req_getval(rq_ry) rrz = req_getval(rq_rz) rmp = req_getval(rq_rmp) parse var rmp rmx rmy rmz rcn = req_getval(rq_rcn) parse var rcn rcx rcy rcz rsx = req_getval(rq_sx) tdr = req_getval(rq_tdr) rsy = req_getval(rq_sy) rsz = req_getval(rq_sz) globs = req_getval(rq_gs) smp = req_getval(rq_smp) parse var smp smx smy smz call req_end call setlayer(bg) n = xfrm_begin() if (n = 0) then return call meter_begin(n, syscode, "Reading Points") do i=1 to n xyz.i = xfrm_getpos(i) call meter_step() end i call meter_end() call xfrm_end() cloneop = 2 if clm=0 then cloneop=1 if slm=1 then cloneop=1 if cloneop = 1 then do call setlayer(fg) call sel_mode('user') if slm=1 then call sel_point('CLEAR') if slm=2 then call sel_polygon('CLEAR') if tlt=1 then do call copy() call setlayer(tl) call paste() end call PadVol if slm = 1 then call sel_point('SET','VOLUME',x1 y1 z1,x2 y2 z2) if slm = 2 then call sel_polygon('SET','VOLINCL',x1 y1 z1,x2 y2 z2) call repl_begin(COPY) call meter_begin(n, syscode, "Generating Clones") do i=1 to n call RTSCLCLC call repl_step(xyz.i, scx scy scz, rox roy roz) call meter_step() end i call meter_end() call repl_end() call cut() call CREDITS return end if cloneop=2 then do if tlt=0 then do call notify(1,"!Must have an empty layer","!to UNIFY polygons.","Try again!") call setlayer(fg) call sel_mode('USER') call sel_polygon('CLEAR') call PadVol call sel_polygon('SET','VOLINCL',x1 y1 z1,x2 y2 z2) call paste() call cut() return end if n > 3 then do ok = notify(2,"!Unifying Clones is REALLY SLOW","(Clones are UNIFIED","one at a time)","@Continue Anyway?") if ok = 0 then return end call setlayer(fg) call sel_mode('user') call sel_polygon('CLEAR') call PadVol then call sel_polygon('SET','VOLINCL',x1 y1 z1,x2 y2 z2) call cut() call ADD_BEGIN pt = ADD_POINT(0 0 0) call ADD_END call sel_point('CLEAR') call PadVol call sel_point('SET','VOLUME',x1 y1 z1,x2 y2 z2) call paste() call cut() call sel_polygon('CLEAR') do i=1 to n call RTSCLCLC call PadVol call sel_point('SET','VOLUME',x1 y1 z1,x2 y2 z2) call repl_begin('COPY') call repl_step(xyz.i, scx scy scz, rox roy roz) call repl_end() call CUT() call setlayer(tl) call setblayer(fg) call meter_begin(n, syscode, "Generating Clones ("i"/"n")") do j=1 to i call meter_step() end j call BOOLEAN('UNION') call meter_end() call setlayer(fg) call sel_polygon('CLEAR') call PadVol call sel_polygon('SET','VOLINCL',x1 y1 z1,x2 y2 z2) call PASTE() call cut() end i call setlayer(tl) call CREDITS return end PADVOL: box=boundingbox() parse var box blah x1 x2 y1 y2 z1 z2 x1=x1-1 x2=x2+1 y1=y1-1 y2=y2+1 z1=z1-1 z2=z2+1 return ARCTAN: actu = actn if actu < -1 then th = 90+(atan(1/abs(actn)) * 180 / pi) if (actu < 1.00001)&(actu > -1.00001) then th = atan(actn) * 180 / pi if actu > 1 then th = 90-(atan(1/actn) * 180 / pi) return RTSCLCLC: parse var xyz.i x y z x=x-rcx y=y-rcy z=z-rcz d = sqrt(x*x+y*y+z*z) interpret 'scx='||globs interpret 'scy='||globs interpret 'scz='||globs if rsx=2 then scx=scx*((randu()-.5)*smx/50*rsx+1) if rsy=2 then scy=scy*((randu()-.5)*smy/50*rsy+1) if rsz=2 then scz=scz*((randu()-.5)*smz/50*rsz+1) if rsx=3 then scx=scx*smx/100 if rsy=3 then scy=scy*smy/100 if rsz=3 then scz=scz*smz/100 if rsy=4 then scy=scx if rsz=4 then scz=scx rox = 0 roy = 0 roz = 0 if tdr=1 then do /* 3-D Radial Rotation */ /* First we adjust our heading */ yf=0 if z=0 then do if x>0 then roy=roy+90 if x<0 then roy=roy-90 yf = 1 end if x=0 then do if z>0 then roy=roy+0 if z<0 then roy=roy+180 yf = 1 end if yf=0 then do actn=abs(x/z) call arctan if z>0 then do /* quadrant 1 */ if x>0 then roy=roy+th end if z>0 then do /* quadrant 2 */ if x<0 then roy=roy-th end if x<0 then do /* quadrant 3 */ if z<0 then roy=roy+180+th end if z<0 then do /* quadrant 4 */ if x>0 then roy=roy+180-th end end /* Now we pitch up */ nd=sqrt(z*z+x*x) yf=0 if nd=0 then do if y>0 then rox=rox+90 if y<0 then rox=rox+-90 yf = 1 end if y=0 then yf = 1 if yf=0 then do actn=abs(y/nd) call arctan if y>0 then rox=rox+th if y<0 then rox=rox-th end end if rrx=2 then rox=rox+(randu()-.5)*rmx*2 if rrx=3 then do /* radial rotation for x */ yf=0 if y=0 then do if z>0 then rox=rox+0 if z<0 then rox=rox+180 yf = 1 end if z=0 then do if y>0 then rox=rox+90 if y<0 then rox=rox-90 yf = 1 end if yf=0 then do actn=abs(z/y) call arctan if y>0 then do /* quadrant 1 */ if z>0 then rox=rox+90-th end if y>0 then do /* quadrant 2 */ if z<0 then rox=rox+90+th end if z<0 then do /* quadrant 3 */ if y<0 then rox=rox-90-th end if y<0 then do /* quadrant 4 */ if z>0 then rox=rox-90+th end end end if rry=2 then roy=roy+(randu()-.5)*rmy*2 if rry=3 then do /* radial rotation for y */ yf=0 if z=0 then do if x>0 then roy=roy+90 if x<0 then roy=roy-90 yf = 1 end if x=0 then do if z>0 then roy=roy+0 if z<0 then roy=roy+180 yf = 1 end if yf=0 then do actn=abs(x/z) call arctan if z>0 then do /* quadrant 1 */ if x>0 then roy=roy+th end if z>0 then do /* quadrant 2 */ if x<0 then roy=roy-th end if x<0 then do /* quadrant 3 */ if z<0 then roy=roy+180+th end if z<0 then do /* quadrant 4 */ if x>0 then roy=roy+180-th end end end if rrz=2 then roz=roz+(randu()-.5)*rmz*2 if rrz=3 then do /* radial rotation for z */ yf=0 if y=0 then do if x>0 then roz=roz+90 if x<0 then roz=roz-90 yf = 1 end if x=0 then do if y>0 then roz=roz+0 if y<0 then roz=roz+180 yf = 1 end if yf=0 then do actn=abs(x/y) call arctan if y>0 then do /* quadrant 1 */ if x>0 then roz=roz+th end if y>0 then do /* quadrant 2 */ if x<0 then roz=roz-th end if x<0 then do /* quadrant 3 */ if y<0 then roz=roz+180+th end if y<0 then do /* quadrant 4 */ if x>0 then roz=roz+180-th end end end return CREDITS: call notify(1,'Thank you for using','!Particle Clone Deluxe','@ -GLYPH (03/15/1997)') if (open(state, filnam, 'W')) then do call writeln state, version call writeln state, slm clm rrx rry rrz rsx rsy rsz tdr call writeln state, globs call writeln state, rmp call writeln state, rcn call writeln state, smp call close state end return