/* CMD: Motion/Envelope
 * Make Object Motion Path or envelope for LW
 * By Arnie Cachelin © 1992 NewTek Inc.
 */
/* Sun Apr  4 19:00:42 1993 */

NUMERIC DIGITS 6
address "LWModelerARexx.port"
call addlib "LWModelerARexx.port", 0
SIGNAL ON ERROR
SIGNAL ON SYNTAX
MATHLIB="rexxmathlib.library"
IF POS(MATHLIB , SHOW('L')) = 0 THEN
  IF ~ADDLIB(MATHLIB , 0 , -30 , 0) THEN DO
	call notify(1,"!Can't find "MATHLIB)
	exit
	END
call addlib "rexxsupport.library", 0, -30, 0

FnList.1='Random'
FnList.2='Oscillator'
FnList.3='Bounce'
FnList.4='Exponential'
FnList.5='Custom'
FList= FnList.1 FnList.2 FnList.3 FnList.4 FnList.5

sysnam = 'Motion/Envelope Maker '
version = 'v1.0'
mename.1='Motion'
medir.1='Mot'
mename.2='Envelope'
medir.2='Env'

call req_begin sysnam
id_frames  = req_addcontrol("Frames", 'n')
id_keysp  = req_addcontrol("Key Spacing", 'n')
id_ME  = req_addcontrol('','CH','Motion Envelope')
id_fn  = req_addcontrol('Type:','CV',FList)
call req_setval id_frames, 60
call req_setval id_Keysp, 5
if (~req_post()) then do
    call req_end
    exit
end
frames   = req_getval(id_frames) % 1
KeySpacing = req_getval(id_keysp)
ME= = req_getval(id_ME)
if ME=2 then Motion=0
else  Motion=1
call req_end

if Motion then do
call req_begin sysnam
  id_frames  = req_addcontrol("Frames", 'n')
  id_keysp  = req_addcontrol("Key Spacing", 'n')
  id_X  = req_addcontrol('Initial Position','V',1)
  id_V  = req_addcontrol('Initial Velocity','V',1)
  id_AX  = req_addcontrol('X Force(x,y,z)','S',35)
  id_AY  = req_addcontrol('Y Force(x,y,z)','S',35)
  id_AZ  = req_addcontrol('Z Force(x,y,z)','S',35)
  call req_setval id_frames, frames
  call req_setval id_Keysp, KeySpacing
  if (~req_post()) then do
    call req_end
    exit
  end
  frames   = req_getval(id_frames) % 1
  KeySpacing = req_getval(id_keysp)
  X0=req_getval(id_X)
  V0=req_getval(id_V)
  AX=req_getval(id_AX)
  AY=req_getval(id_AY)
  AZ=req_getval(id_AZ)
  call req_end

ENVFile=getfilename("-- Save "mename.ME" --",medir.ME)
if ENVFile ~="(none)" File.Name=ENVFile
else exit




h=0; p=0; b=0
xsc=1; ysc=1; zsc=1
File.type="LWMO"
SecsPerFrame=1/30
Time=SecsPerFrame*Frames
Keys=1+Frames%KeySpacing
SlicesPerFrame=10
dt=SecsPerFrame/SlicesPerFrame
g=9.8 /* acceleration of gravity in m/s */
frame=0
slice=0

/* For ballistic trajectory, Vx=V*cos(a), Vy=V*sin(a), Y=((Vy)^2)/g, T=2*Vy/g
    ==> X=T*Vx=2*Vy*Vx/g.  Setting shot duration will be the priority, so the
    only input will be the time.  The height, Y, will then be set since:
    Y=((T*g/2)^2)/g =(g*T^2)/4.  Vx is arbitrary, but it determines the angle
    and the distance. To make X=Y, use Vx=Vy/4, which is about 76 degrees.
    I'll add wind a bit later!!!
*/

/* Initial Conditions */

vyi=Time*g/2
vxi=vyi*tan(phi)
vxi=vxi*cos(theta)
vzi=vxi*sin(theta)
x=xi; y=yi; z=zi
vx=vxi; vy=vyi; vz=vzi

call meter_begin Time*dt, 'Generating Motion'
call WriteHeader(mot,keys)
do t=0 to Time+dt by dt
    if slice//SlicesPerFrame = 0 then do
      if frame//KeySpacing=0 then
        call WriteKey(mot,frame,0)
      else if frame=Frames then
        call WriteKey(mot,frame,0)
      frame=frame+1
    end
    slice=slice+1
    vx=vx+dt*ax(x,y,z)
    vy=vy+dt*ay(x,y,z)
    vz=vz+dt*az(x,y,z)
    x=x + dt*vx
    y=y + dt*vy
    z=z + dt*vz
    call meter_step
end
call close mot
call meter_end
call notify(1,'!Created LightWave Motion File: 'File.name)
exit

ax: procedure
  arg x,y,z
  return(0)

ay: procedure expose g
  arg x,y,z
  return(-g)

az: procedure
  arg x,y,z
  return(0)

WriteKey:  PROCEDURE  EXPOSE x y z h p b xsc ysc zsc
  arg MotFile, frame, lin
  channels=x y z h p b xsc ysc zsc
  spline=frame lin "0.0 0.0 0.0"
  say channels spline
  call writeln(MotFile,channels)
  call writeln(MotFile,spline)
  return frame

WriteHeader: PROCEDURE EXPOSE File.
  arg MotFile, Keys
  if open(MotFile,File.name,'W') then do
    call writeln(MotFile,File.type)
    call writeln(MotFile,"1") /* magic # */
    call writeln(MotFile,"9") /* Channels */
    call writeln(MotFile,Keys)
  end
  else do
    Bummer("Can't open Motion file : "File.name)
  end
  return 1

Bummer:
 ARG etxt
 SAY "ERROR: "||RC||etxt
SYNTAX:
ERROR:
  say 'Sorry, Error #'RC' on line 'SIGL' has been detected.'
  if etxt=''| etxt='ETXT' then etxt= errortext(rc)
  say sourceline(SIGL)
  t=notify(1,'!Total Bummer Dude!','!An error has been detected.','@'etxt,'Line 'SIGL)
  call end_all
  exit
