--- ray/src/util/ranimate.c 1996/01/23 16:14:28 2.5 +++ ray/src/util/ranimate.c 2003/02/25 02:47:24 2.31 @@ -1,69 +1,87 @@ -/* Copyright (c) 1995 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: ranimate.c,v 2.31 2003/02/25 02:47:24 greg Exp $"; #endif - /* * Radiance animation control program + * + * The main difference between this program and ranimove is that + * we have many optimizations here for camera motion in static + * environments, calling rpict and pinterp on multiple processors, + * where ranimove puts its emphasis on object motion, and does + * not use any external programs for image generation. + * + * See the ranimate(1) man page for further details. */ +#include "copyright.h" + #include "standard.h" #include -#include #include #include "view.h" #include "vars.h" #include "netproc.h" - /* input variables */ -#define HOST 0 /* rendering host machine */ -#define RENDER 1 /* rendering options */ -#define PFILT 2 /* pfilt options */ -#define PINTERP 3 /* pinterp options */ -#define OCTREE 4 /* octree file name */ -#define DIRECTORY 5 /* working (sub)directory */ -#define BASENAME 6 /* output image base name */ -#define VIEWFILE 7 /* animation frame views */ -#define START 8 /* starting frame number */ -#define END 9 /* ending frame number */ -#define RIF 10 /* rad input file */ -#define NEXTANIM 11 /* next animation file */ -#define ANIMATE 12 /* animation command */ -#define TRANSFER 13 /* frame transfer command */ -#define ARCHIVE 14 /* archiving command */ -#define INTERP 15 /* # frames to interpolate */ -#define OVERSAMP 16 /* # times to oversample image */ -#define MBLUR 17 /* samples for motion blur */ -#define RTRACE 18 /* use rtrace with pinterp? */ -#define DISKSPACE 19 /* how much disk space to use */ -#define RESOLUTION 20 /* desired final resolution */ -#define EXPOSURE 21 /* how to compute exposure */ + /* default blur samples */ +#ifndef DEF_NBLUR +#define DEF_NBLUR 5 +#endif + /* default remote shell */ +#ifdef _AUX_SOURCE +#define REMSH "remsh" +#else +#define REMSH "rsh" +#endif + /* input variables (alphabetical by name) */ +#define ANIMATE 0 /* animation command */ +#define ARCHIVE 1 /* archiving command */ +#define BASENAME 2 /* output image base name */ +#define DIRECTORY 3 /* working (sub)directory */ +#define DISKSPACE 4 /* how much disk space to use */ +#define END 5 /* ending frame number */ +#define EXPOSURE 6 /* how to compute exposure */ +#define HOST 7 /* rendering host machine */ +#define INTERP 8 /* # frames to interpolate */ +#define MBLUR 9 /* motion blur parameters */ +#define NEXTANIM 10 /* next animation file */ +#define OCTREE 11 /* octree file name */ +#define OVERSAMP 12 /* # times to oversample image */ +#define PFILT 13 /* pfilt options */ +#define PINTERP 14 /* pinterp options */ +#define RENDER 15 /* rendering options */ +#define RESOLUTION 16 /* desired final resolution */ +#define RIF 17 /* rad input file */ +#define RSH 18 /* remote shell script or program */ +#define RTRACE 19 /* use rtrace with pinterp? */ +#define START 20 /* starting frame number */ +#define TRANSFER 21 /* frame transfer command */ +#define VIEWFILE 22 /* animation frame views */ -int NVARS = 22; /* total number of variables */ +int NVARS = 23; /* total number of variables */ VARIABLE vv[] = { /* variable-value pairs */ - {"host", 4, 0, NULL, NULL}, - {"render", 3, 0, NULL, catvalues}, - {"pfilt", 2, 0, NULL, catvalues}, - {"pinterp", 2, 0, NULL, catvalues}, - {"OCTREE", 3, 0, NULL, onevalue}, - {"DIRECTORY", 3, 0, NULL, onevalue}, - {"BASENAME", 3, 0, NULL, onevalue}, - {"VIEWFILE", 2, 0, NULL, onevalue}, - {"START", 2, 0, NULL, intvalue}, - {"END", 2, 0, NULL, intvalue}, - {"RIF", 3, 0, NULL, onevalue}, - {"NEXTANIM", 3, 0, NULL, onevalue}, {"ANIMATE", 2, 0, NULL, onevalue}, - {"TRANSFER", 2, 0, NULL, onevalue}, {"ARCHIVE", 2, 0, NULL, onevalue}, + {"BASENAME", 3, 0, NULL, onevalue}, + {"DIRECTORY", 3, 0, NULL, onevalue}, + {"DISKSPACE", 3, 0, NULL, fltvalue}, + {"END", 2, 0, NULL, intvalue}, + {"EXPOSURE", 3, 0, NULL, onevalue}, + {"host", 4, 0, NULL, NULL}, {"INTERPOLATE", 3, 0, NULL, intvalue}, - {"OVERSAMPLE", 2, 0, NULL, fltvalue}, {"MBLUR", 2, 0, NULL, onevalue}, - {"RTRACE", 2, 0, NULL, boolvalue}, - {"DISKSPACE", 3, 0, NULL, fltvalue}, + {"NEXTANIM", 3, 0, NULL, onevalue}, + {"OCTREE", 3, 0, NULL, onevalue}, + {"OVERSAMPLE", 2, 0, NULL, fltvalue}, + {"pfilt", 2, 0, NULL, catvalues}, + {"pinterp", 2, 0, NULL, catvalues}, + {"render", 3, 0, NULL, catvalues}, {"RESOLUTION", 3, 0, NULL, onevalue}, - {"EXPOSURE", 3, 0, NULL, onevalue}, + {"RIF", 3, 0, NULL, onevalue}, + {"RSH", 3, 0, NULL, onevalue}, + {"RTRACE", 2, 0, NULL, boolvalue}, + {"START", 2, 0, NULL, intvalue}, + {"TRANSFER", 2, 0, NULL, onevalue}, + {"VIEWFILE", 2, 0, NULL, onevalue}, }; #define SFNAME "STATUS" /* status file name */ @@ -84,11 +102,15 @@ int nowarn = 0; /* turn warnings off? */ int silent = 0; /* silent mode? */ int noaction = 0; /* take no action? */ -char rendopt[2048] = ""; /* rendering options */ +char *remsh; /* remote shell program/script */ +char rendopt[2048]; /* rendering options */ char rresopt[32]; /* rendering resolution options */ char fresopt[32]; /* filter resolution options */ int pfiltalways; /* always use pfilt? */ +char arcargs[10240]; /* files to archive */ +char *arcfirst, *arcnext; /* pointers to first and next argument */ + struct pslot { int pid; /* process ID (0 if empty) */ int fout; /* output frame number */ @@ -96,17 +118,19 @@ struct pslot { } *pslot; /* process slots */ int npslots; /* number of process slots */ -int lastpid; /* ID of last completed background process */ -PSERVER *lastpserver; /* last process server used */ - #define phostname(ps) ((ps)->hostname[0] ? (ps)->hostname : astat.host) struct pslot *findpslot(); +PSERVER *lastpserver; /* last process server with error */ + VIEW *getview(); -char *getexp(); +char *getexp(), *dirfile(); +int getblur(); +extern time_t time(); + main(argc, argv) int argc; char *argv[]; @@ -137,6 +161,8 @@ char *argv[]; cfname = argv[i]; /* load variables */ loadvars(cfname); + /* check variables */ + checkvalues(); /* did we get DIRECTORY? */ checkdir(); /* check status */ @@ -163,8 +189,11 @@ char *argv[]; argv[i] = vval(NEXTANIM); /* just change input file */ if (!silent) printargs(argc, argv, stdout); - execvp(progname, argv); /* pass to next */ - quit(1); /* shouldn't return */ + if ((argv[0] = getpath(progname,getenv("PATH"),X_OK)) == NULL) + fprintf(stderr, "%s: command not found\n", progname); + else + execv(progname, argv); + quit(1); } quit(0); userr: @@ -175,13 +204,13 @@ userr: getastat() /* check/set animation status */ { - char buf[256]; + char sfname[256]; FILE *fp; - sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME); - if ((fp = fopen(buf, "r")) == NULL) { + sprintf(sfname, "%s/%s", vval(DIRECTORY), SFNAME); + if ((fp = fopen(sfname, "r")) == NULL) { if (errno != ENOENT) { - perror(buf); + perror(sfname); return(-1); } astat.rnext = astat.fnext = astat.tnext = 0; @@ -201,8 +230,7 @@ getastat() /* check/set animation status */ goto fmterr; fclose(fp); if (astat.pid != 0) { /* thinks it's still running */ - gethostname(buf, sizeof(buf)); - if (strcmp(buf, astat.host)) { + if (strcmp(myhostname(), astat.host)) { fprintf(stderr, "%s: process %d may still be running on host %s\n", progname, astat.pid, astat.host); @@ -215,19 +243,24 @@ getastat() /* check/set animation status */ } /* assume it is dead */ } - if (strcmp(cfname, astat.cfname) && astat.tnext != 0) { /* other's */ + if (strcmp(cfname, astat.cfname) && astat.pid != 0) { /* other's */ fprintf(stderr, "%s: unfinished job \"%s\"\n", progname, astat.cfname); return(-1); } + /* check control file mods. */ + if (!nowarn && fdate(cfname) > fdate(sfname)) + fprintf(stderr, + "%s: warning - control file modified since last run\n", + progname); setours: /* set our values */ - gethostname(astat.host, sizeof(astat.host)); + strcpy(astat.host, myhostname()); astat.pid = getpid(); strcpy(astat.cfname, cfname); return(0); fmterr: fprintf(stderr, "%s: format error in status file \"%s\"\n", - progname, buf); + progname, sfname); fclose(fp); return(-1); } @@ -279,6 +312,8 @@ checkdir() /* make sure we have our directory */ setdefaults() /* set default values */ { + extern char *atos(); + int decades; char buf[256]; if (vdef(ANIMATE)) { @@ -312,7 +347,9 @@ setdefaults() /* set default values */ quit(1); } if (!vdef(BASENAME)) { - sprintf(buf, "%s/frame%%03d", vval(DIRECTORY)); + decades = (int)log10((double)vint(END)) + 1; + if (decades < 3) decades = 3; + sprintf(buf, "%s/frame%%0%dd", vval(DIRECTORY), decades); vval(BASENAME) = savqstr(buf); vdef(BASENAME)++; } @@ -344,6 +381,17 @@ setdefaults() /* set default values */ vval(DISKSPACE) = "100"; vdef(DISKSPACE)++; } + if (!vdef(RSH)) { + vval(RSH) = REMSH; + vdef(RSH)++; + } + /* locate remote shell program */ + atos(buf, sizeof(buf), vval(RSH)); + if ((remsh = getpath(buf, getenv("PATH"), X_OK)) != NULL) + remsh = savqstr(remsh); + else + remsh = vval(RSH); /* will generate error if used */ + /* append rendering options */ if (vdef(RENDER)) sprintf(rendopt+strlen(rendopt), " %s", vval(RENDER)); @@ -406,35 +454,42 @@ sethosts() /* set up process servers */ } -getradfile(rfname) /* run rad and get needed variables */ -char *rfname; +getradfile(rfargs) /* run rad and get needed variables */ +char *rfargs; { static short mvar[] = {OCTREE,PFILT,RESOLUTION,EXPOSURE,-1}; char combuf[256]; register int i; register char *cp; + char *pippt; /* create rad command */ sprintf(rendopt, " @%s/render.opt", vval(DIRECTORY)); sprintf(combuf, "rad -v 0 -s -e -w %s OPTFILE=%s | egrep '^[ \t]*(NOMATCH", - rfname, rendopt+2); + rfargs, rendopt+2); cp = combuf; - while (*cp) cp++; /* match unset variables */ + while (*cp) { + if (*cp == '|') pippt = cp; + cp++; + } /* match unset variables */ for (i = 0; mvar[i] >= 0; i++) if (!vdef(mvar[i])) { *cp++ = '|'; strcpy(cp, vnam(mvar[i])); while (*cp) cp++; + pippt = NULL; } - sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY)); - cp += 11; /* point to file name */ - if (system(combuf)) { - fprintf(stderr, "%s: bad rad input file \"%s\"\n", - progname, rfname); - quit(1); + if (pippt != NULL) + strcpy(pippt, "> /dev/null"); /* nothing to match */ + else { + sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY)); + cp += 11; /* point to file name */ } - loadvars(cp); /* load variables and remove file */ - unlink(cp); + system(combuf); /* ignore exit code */ + if (pippt == NULL) { /* load variables and remove file */ + loadvars(cp); + unlink(cp); + } } @@ -449,9 +504,9 @@ animate() /* run animation */ i = sscanf(vval(RESOLUTION), "%d %d %f", &xres, &yres, &pa); mult = vflt(OVERSAMP); if (i == 3) { - sprintf(rresopt, "-x %d -y %d -pa %f", (int)(mult*xres), + sprintf(rresopt, "-x %d -y %d -pa %.3f", (int)(mult*xres), (int)(mult*yres), pa); - sprintf(fresopt, "-x %d -y %d -pa %f", xres, yres, pa); + sprintf(fresopt, "-x %d -y %d -pa %.3f", xres, yres, pa); } else if (i) { if (i == 1) yres = xres; sprintf(rresopt, "-x %d -y %d", (int)(mult*xres), @@ -468,7 +523,7 @@ animate() /* run animation */ progname, vnam(INTERP)); vval(INTERP) = "0"; } - if (atoi(vval(MBLUR))) { /* can't handle this yet */ + if (strcmp(vval(MBLUR),"0")) { /* can't handle this */ if (!nowarn) fprintf(stderr, "%s: resetting %s=0 for animation\n", @@ -478,8 +533,8 @@ animate() /* run animation */ } /* figure # frames per batch */ d1 = mult*xres*mult*yres*4; /* space for orig. picture */ - if ((i=vint(INTERP)) || atoi(vval(MBLUR))) - d1 += mult*xres*mult*yres*4; /* space for z-buffer */ + if ((i=vint(INTERP)) || getblur(NULL) > 1) + d1 += mult*xres*mult*yres*sizeof(float); /* Z-buffer */ d2 = xres*yres*4; /* space for final picture */ frames_batch = (i+1)*(vflt(DISKSPACE)*1048576.-d1)/(d1+i*d2); if (frames_batch < i+2) { @@ -487,6 +542,9 @@ animate() /* run animation */ progname); quit(1); } + /* initialize archive argument list */ + i = vdef(ARCHIVE) ? strlen(vval(ARCHIVE))+132 : 132; + arcnext = arcfirst = arcargs + i; /* initialize status file */ if (astat.rnext == 0) astat.rnext = astat.fnext = astat.tnext = vint(START); @@ -581,7 +639,7 @@ filterframes() /* catch up with filtering */ dofilt(i, vp, getexp(i), 0); /* filter frame */ } bwait(0); /* wait for filter processes */ - archive(astat.fnext, i-1); /* archive originals */ + archive(); /* archive originals */ astat.fnext = i; /* update status */ putastat(); } @@ -589,7 +647,7 @@ filterframes() /* catch up with filtering */ transferframes() /* catch up with picture transfers */ { - char combuf[10240]; + char combuf[10240], *fbase; register char *cp; register int i; @@ -600,12 +658,19 @@ transferframes() /* catch up with picture transfers putastat(); /* update status */ return; } - strcpy(combuf, vval(TRANSFER)); /* start transfer command */ - cp = combuf + strlen(combuf); + strcpy(combuf, "cd "); /* start transfer command */ + fbase = dirfile(cp = combuf+3, vval(BASENAME)); + if (*cp) { + while (*++cp) ; + *cp++ = ';'; *cp++ = ' '; + } else + cp = combuf; + strcpy(cp, vval(TRANSFER)); + while (*cp) cp++; /* make argument list */ for (i = astat.tnext; i < astat.fnext; i++) { *cp++ = ' '; - sprintf(cp, vval(BASENAME), i); + sprintf(cp, fbase, i); while (*cp) cp++; strcpy(cp, ".pic"); cp += 4; @@ -642,8 +707,10 @@ walkwait(first, last, vfn) /* walk-through frames */ int first, last; char *vfn; { + double blurf; + int nblur = getblur(&blurf); char combuf[2048]; - char *inspoint; + register char *inspoint; register int i; if (!noaction && vint(INTERP)) /* create dummy frames */ @@ -654,15 +721,26 @@ char *vfn; close(open(combuf, O_RDONLY|O_CREAT, 0666)); } /* create command */ - sprintf(combuf, "rpict%s -w0", rendopt); - if (vint(INTERP) || atoi(vval(MBLUR))) - sprintf(combuf+strlen(combuf), " -z %s.zbf", vval(BASENAME)); - sprintf(combuf+strlen(combuf), " -o %s.unf %s -S %d", + sprintf(combuf, "rpict%s%s -w0", rendopt, + viewopt(getview(first>1 ? first-1 : 1))); + inspoint = combuf; + while (*inspoint) inspoint++; + if (nblur) { + sprintf(inspoint, " -pm %.3f", blurf/nblur); + while (*inspoint) inspoint++; + } + if (nblur > 1 || vint(INTERP)) { + sprintf(inspoint, " -z %s.zbf", vval(BASENAME)); + while (*inspoint) inspoint++; + } + sprintf(inspoint, " -o %s.unf %s -S %d", vval(BASENAME), rresopt, first); - inspoint = combuf + strlen(combuf); + while (*inspoint) inspoint++; sprintf(inspoint, " %s < %s", vval(OCTREE), vfn); /* run in parallel */ - if (pruncom(combuf, inspoint, (last-first+1)/(vint(INTERP)+1))) { + i = (last-first+1)/(vint(INTERP)+1); + if (i < 1) i = 1; + if (pruncom(combuf, inspoint, i)) { fprintf(stderr, "%s: error rendering frames %d through %d\n", progname, first, last); quit(1); @@ -683,6 +761,8 @@ int frame; { static int *rfrm; /* list of recovered frames */ static int nrfrms = 0; + double blurf; + int nblur = getblur(&blurf); char combuf[2048]; char fname[128]; register char *cp; @@ -698,8 +778,13 @@ int frame; vval(ANIMATE), frame, rendopt); else sprintf(combuf, "rpict%s -w0", rendopt); - cp = combuf + strlen(combuf); - if (vint(INTERP) || atoi(vval(MBLUR))) { + cp = combuf; + while (*cp) cp++; + if (nblur) { + sprintf(cp, " -pm %.3f", blurf/nblur); + while (*cp) cp++; + } + if (nblur > 1 || vint(INTERP)) { sprintf(cp, " -z %s.zbf", fname); while (*cp) cp++; } @@ -740,53 +825,45 @@ int frame; } -archive(first, last) /* archive and remove renderings */ -int first, last; +archive() /* archive and remove renderings */ { #define RMCOML (sizeof(rmcom)-1) static char rmcom[] = "rm -f"; - int offset = RMCOML; - char combuf[10240]; - struct stat stb; - register char *cp; - register int i; + char basedir[128]; + int dlen, alen; + register int j; - if (noaction) - return; - if (vdef(ARCHIVE) && strlen(vval(ARCHIVE)) > offset) - offset = strlen(vval(ARCHIVE)); - cp = combuf + offset; - *cp++ = ' '; /* make argument list */ - for (i = first; i <= last; i++) { - sprintf(cp, vval(BASENAME), i); - strcat(cp, ".unf"); - if (stat(cp, &stb) == 0 && stb.st_size > 0) { /* non-zero? */ - while (*cp) cp++; - *cp++ = ' '; - sprintf(cp, vval(BASENAME), i); - strcat(cp, ".zbf"); - if (access(cp, F_OK) == 0) { /* exists? */ - while (*cp) cp++; - *cp++ = ' '; - } - } - } - *--cp = '\0'; - if (cp <= combuf + offset) /* no files? */ - return; + if (arcnext == arcfirst) + return; /* nothing to do */ + dirfile(basedir, vval(BASENAME)); + dlen = strlen(basedir); if (vdef(ARCHIVE)) { /* run archive command */ - i = strlen(vval(ARCHIVE)); - strncpy(combuf+offset-i, vval(ARCHIVE), i); - if (runcom(combuf+offset-i)) { - fprintf(stderr, - "%s: error running archive command on frames %d through %d\n", - progname, first, last); + alen = strlen(vval(ARCHIVE)); + if (dlen) { + j = alen + dlen + 5; + strncpy(arcfirst-j, "cd ", 3); + strncpy(arcfirst-j+3, basedir, dlen); + (arcfirst-j)[dlen+3] = ';'; (arcfirst-j)[dlen+4] = ' '; + } else + j = alen; + strncpy(arcfirst-alen, vval(ARCHIVE), alen); + if (runcom(arcfirst-j)) { + fprintf(stderr, "%s: error running archive command\n", + progname); quit(1); } } + if (dlen) { + j = RMCOML + dlen + 5; + strncpy(arcfirst-j, "cd ", 3); + strncpy(arcfirst-j+3, basedir, dlen); + (arcfirst-j)[dlen+3] = ';'; (arcfirst-j)[dlen+4] = ' '; + } else + j = RMCOML; /* run remove command */ - strncpy(combuf+offset-RMCOML, rmcom, RMCOML); - runcom(combuf+offset-RMCOML); + strncpy(arcfirst-RMCOML, rmcom, RMCOML); + runcom(arcfirst-j); + arcnext = arcfirst; /* reset argument list */ #undef RMCOML } @@ -799,26 +876,47 @@ char *ep; int rvr; { extern int frecover(); - char fnbefore[128], fnafter[128]; - char combuf[1024], fname[128]; - int usepinterp, usepfilt; + static int iter = 0; + double blurf; + int nblur = getblur(&blurf); + char fnbefore[128], fnafter[128], *fbase; + char combuf[1024], fname0[128], fname1[128]; + int usepinterp, usepfilt, nora_rgbe; int frseq[2]; /* check what is needed */ - usepinterp = atoi(vval(MBLUR)); + usepinterp = (nblur > 1); usepfilt = pfiltalways | ep==NULL; + if (ep != NULL && !strcmp(ep, "1")) + ep = "+0"; + nora_rgbe = strcmp(vval(OVERSAMP),"1") || ep==NULL || + *ep != '+' || *ep != '-' || !isint(ep); /* compute rendered views */ frseq[0] = frame - ((frame-1) % (vint(INTERP)+1)); frseq[1] = frseq[0] + vint(INTERP) + 1; + fbase = dirfile(NULL, vval(BASENAME)); if (frseq[1] > vint(END)) frseq[1] = vint(END); if (frseq[1] == frame) { /* pfilt only */ frseq[0] = frseq[1]; usepinterp = 0; /* update what's needed */ - usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1"); - } else if (frseq[0] == frame) { /* no interpolation */ - /* update what's needed */ - if (!usepinterp) - usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1"); + usepfilt |= nora_rgbe; + } else if (frseq[0] == frame) { /* no interpolation needed */ + if (!rvr && frame > 1+vint(INTERP)) { /* archive previous */ + *arcnext++ = ' '; + sprintf(arcnext, fbase, frame-vint(INTERP)-1); + while (*arcnext) arcnext++; + strcpy(arcnext, ".unf"); + arcnext += 4; + if (usepinterp || vint(INTERP)) { /* and Z-buf */ + *arcnext++ = ' '; + sprintf(arcnext, fbase, frame-vint(INTERP)-1); + while (*arcnext) arcnext++; + strcpy(arcnext, ".zbf"); + arcnext += 4; + } + } + if (!usepinterp) /* update what's needed */ + usepfilt |= nora_rgbe; } else /* interpolation needed */ usepinterp++; if (frseq[1] >= astat.rnext) /* next batch unavailable */ @@ -831,48 +929,49 @@ int rvr; if (usepinterp) { /* using pinterp */ if (rvr == 2 && recover(frseq[1])) /* recover after? */ return(1); - if (atoi(vval(MBLUR))) { - FILE *fp; /* motion blurring */ - sprintf(fname, "%s/vw0", vval(DIRECTORY)); - if (access(fname, F_OK) == 0) - sleep(10); - if ((fp = fopen(fname, "w")) == NULL) { - perror(fname); quit(1); - } - fputs(VIEWSTR, fp); - fprintview(vp, fp); - putc('\n', fp); fclose(fp); - if ((vp = getview(frame+1)) == NULL) { - fprintf(stderr, + if (nblur > 1) { /* with pmblur */ + sprintf(fname0, "%s/vw0%c", vval(DIRECTORY), + 'a'+(iter%26)); + sprintf(fname1, "%s/vw1%c", vval(DIRECTORY), + 'a'+(iter%26)); + if (!noaction) { + FILE *fp; /* motion blurring */ + if ((fp = fopen(fname0, "w")) == NULL) { + perror(fname0); quit(1); + } + fputs(VIEWSTR, fp); + fprintview(vp, fp); + putc('\n', fp); fclose(fp); + if ((vp = getview(frame+1)) == NULL) { + fprintf(stderr, "%s: unexpected error reading view for frame %d\n", - progname, frame+1); - quit(1); + progname, frame+1); + quit(1); + } + if ((fp = fopen(fname1, "w")) == NULL) { + perror(fname1); quit(1); + } + fputs(VIEWSTR, fp); + fprintview(vp, fp); + putc('\n', fp); fclose(fp); } - sprintf(fname, "%s/vw1", vval(DIRECTORY)); - if ((fp = fopen(fname, "w")) == NULL) { - perror(fname); quit(1); - } - fputs(VIEWSTR, fp); - fprintview(vp, fp); - putc('\n', fp); fclose(fp); sprintf(combuf, - "(pmblur %s %d %s/vw0 %s/vw1; rm -f %s/vw0 %s/vw1) | pinterp -B", - *sskip(vval(MBLUR)) ? sskip2(vval(MBLUR),1) : "1", - atoi(vval(MBLUR)), vval(DIRECTORY), - vval(DIRECTORY), vval(DIRECTORY), - vval(DIRECTORY), vval(DIRECTORY)); + "(pmblur %.3f %d %s %s; rm -f %s %s) | pinterp -B -a", + blurf, nblur, + fname0, fname1, fname0, fname1); + iter++; } else /* no blurring */ strcpy(combuf, "pinterp"); strcat(combuf, viewopt(vp)); if (vbool(RTRACE)) sprintf(combuf+strlen(combuf), " -ff -fr '%s -w0 %s'", - rendopt, vval(OCTREE)); + rendopt+1, vval(OCTREE)); if (vdef(PINTERP)) sprintf(combuf+strlen(combuf), " %s", vval(PINTERP)); if (usepfilt) sprintf(combuf+strlen(combuf), " %s", rresopt); else - sprintf(combuf+strlen(combuf), " %s -e %s", + sprintf(combuf+strlen(combuf), "-a %s -e %s", fresopt, ep); sprintf(combuf+strlen(combuf), " %s.unf %s.zbf", fnbefore, fnbefore); @@ -907,11 +1006,11 @@ int rvr; } else { /* else just check it */ if (rvr == 2) return(1); - sprintf(combuf, "ra_rgbe -r %s.unf", fnbefore); + sprintf(combuf, "ra_rgbe -e %s -r %s.unf", ep, fnbefore); } /* output file name */ - sprintf(fname, vval(BASENAME), frame); - sprintf(combuf+strlen(combuf), " > %s.pic", fname); + sprintf(fname0, vval(BASENAME), frame); + sprintf(combuf+strlen(combuf), " > %s.pic", fname0); if (rvr) /* in recovery */ return(runcom(combuf)); bruncom(combuf, frame, frecover); /* else run in background */ @@ -937,12 +1036,14 @@ int n; } return(NULL); } - if (viewfp == NULL) { /* open file */ + if (viewfp == NULL) { /* open file */ if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) { perror(vval(VIEWFILE)); quit(1); } - } else if (n < viewnum) { /* rewind file */ + } else if (n > 0 && n < viewnum) { /* rewind file */ + if (viewnum == 1 && feof(viewfp)) + return(&curview); /* just one view */ if (fseek(viewfp, 0L, 0) == EOF) { perror(vval(VIEWFILE)); quit(1); @@ -950,9 +1051,16 @@ int n; copystruct(&curview, &stdview); viewnum = 0; } + if (n < 0) { /* get next view */ + register int c = getc(viewfp); + if (c == EOF) + return((VIEW *)NULL); /* that's it */ + ungetc(c, viewfp); + n = viewnum + 1; + } while (n > viewnum) { /* scan to desired view */ if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL) - return(NULL); + return(viewnum==1 ? &curview : (VIEW *)NULL); if (isview(linebuf) && sscanview(&curview, linebuf) > 0) viewnum++; } @@ -963,9 +1071,11 @@ int n; int countviews() /* count views in view file */ { - register int n = 0; + int n; - while (getview(n+1) != NULL) + if (getview(n=1) == NULL) + return(0); + while (getview(-1) != NULL) n++; return(n); } @@ -985,10 +1095,12 @@ int n; if (n == 0) { /* signal to close file */ if (expfp != NULL) { fclose(expfp); + free((void *)exppos); expfp = NULL; } return(NULL); - } + } else if (n > vint(END)) /* request past end (error?) */ + return(NULL); if (!vdef(EXPOSURE)) /* no setting (auto) */ return(NULL); if (isflt(vval(EXPOSURE))) /* always the same */ @@ -1026,13 +1138,15 @@ int n; } curfrm++; cp = fskip(expval); /* check format */ - if (cp == NULL || *cp != '\n') { + if (cp != NULL) + while (isspace(*cp)) + *cp++ = '\0'; + if (cp == NULL || *cp) { fprintf(stderr, "%s: exposure format error on line %d\n", vval(EXPOSURE), curfrm); quit(1); } - *cp = '\0'; } return(expval); /* return value */ } @@ -1062,6 +1176,7 @@ int pn; int status; { register PROC *pp; + register struct pslot *psl; pp = ps->proc + pn; if (pp->elen) { /* pass errors */ @@ -1073,9 +1188,24 @@ int status; if (ps->hostname[0]) status = 1; /* because rsh doesn't return status */ } + lastpserver = NULL; + psl = findpslot(pp->pid); /* check for bruncom() slot */ + if (psl->pid) { + if (status) { + if (psl->rcvf != NULL) /* attempt recovery */ + status = (*psl->rcvf)(psl->fout); + if (status) { + fprintf(stderr, + "%s: error rendering frame %d\n", + progname, psl->fout); + quit(1); + } + lastpserver = ps; + } + psl->pid = 0; /* free process slot */ + } else if (status) + lastpserver = ps; freestr(pp->com); /* free command string */ - lastpid = pp->pid; /* record PID for bwait() */ - lastpserver = ps; /* record server for serverdown() */ return(status); } @@ -1083,6 +1213,8 @@ int status; int serverdown() /* check status of last process server */ { + if (lastpserver == NULL || !lastpserver->hostname[0]) + return(0); if (pserverOK(lastpserver)) /* server still up? */ return(0); delpserver(lastpserver); /* else delete it */ @@ -1109,8 +1241,8 @@ int (*rf)(); printf("\t%s\n", com); /* echo command */ return(0); } - /* else start it when we can */ - while ((pid = startjob(NULL, savestr(com), donecom)) == -1) + com = savestr(com); /* else start it when we can */ + while ((pid = startjob(NULL, com, donecom)) == -1) bwait(1); if (!silent) { /* echo command */ PSERVER *ps; @@ -1132,24 +1264,13 @@ bwait(ncoms) /* wait for batch job(s) to finish */ int ncoms; { int status; - register struct pslot *psl; if (noaction) return; while ((status = wait4job(NULL, -1)) != -1) { - psl = findpslot(lastpid); - if (status) { /* attempt recovery */ - serverdown(); /* check server */ - if (psl->rcvf == NULL || (*psl->rcvf)(psl->fout)) { - fprintf(stderr, - "%s: error rendering frame %d\n", - progname, psl->fout); - quit(1); - } - } - psl->pid = 0; /* free process slot */ - if (!--ncoms) - return; /* done enough */ + serverdown(); /* update server status */ + if (--ncoms == 0) + break; /* done enough */ } } @@ -1161,12 +1282,14 @@ int maxcopies; { int retstatus = 0; int hostcopies; - char com1buf[10240], *com1, *endcom1; + char buf[10240], *com1, *s; int status; + int pfd; + register int n; register PSERVER *ps; if (!silent) - printf("\t%s &\n", com); /* echo command */ + printf("\t%s\n", com); /* echo command */ if (noaction) return(0); fflush(stdout); @@ -1174,25 +1297,23 @@ int maxcopies; for (ps = pslist; ps != NULL; ps = ps->next) { hostcopies = 0; if (maxcopies > 1 && ps->nprocs > 1 && ppins != NULL) { - strcpy(com1=com1buf, com); /* build -PP command */ + strcpy(com1=buf, com); /* build -PP command */ sprintf(com1+(ppins-com), " -PP %s/%s.persist", vval(DIRECTORY), phostname(ps)); strcat(com1, ppins); - endcom1 = com1 + strlen(com1); - sprintf(endcom1, "; kill `sed -n '1s/^[^ ]* //p' %s/%s.persist`", - vval(DIRECTORY), phostname(ps)); - } else { + } else com1 = com; - endcom1 = NULL; + while (maxcopies > 0) { + s = savestr(com1); + if (startjob(ps, s, donecom) != -1) { + sleep(20); + hostcopies++; + maxcopies--; + } else { + freestr(s); + break; + } } - while (maxcopies > 0 && - startjob(ps, savestr(com1), donecom) != -1) { - sleep(10); - hostcopies++; - maxcopies--; - if (endcom1 != NULL) - *endcom1 = '\0'; - } if (!silent && hostcopies) { if (hostcopies > 1) printf("\t%d duplicate processes", hostcopies); @@ -1204,8 +1325,21 @@ int maxcopies; } /* wait for jobs to finish */ while ((status = wait4job(NULL, -1)) != -1) - if (status) - retstatus += !serverdown(); /* check server */ + retstatus += status && !serverdown(); + /* terminate parallel rpict's */ + for (ps = pslist; ps != NULL; ps = ps->next) { + sprintf(buf, "%s/%s.persist", vval(DIRECTORY), phostname(ps)); + if ((pfd = open(buf, O_RDONLY)) >= 0) { + n = read(pfd, buf, sizeof(buf)-1); /* get PID */ + buf[n] = '\0'; + close(pfd); + for (n = 0; buf[n] && !isspace(buf[n]); n++) + ; + /* terminate */ + sprintf(buf, "kill -ALRM %d", atoi(buf+n)); + wait4job(ps, startjob(ps, buf, NULL)); + } + } return(retstatus); } @@ -1243,4 +1377,57 @@ int vc; fprintf(stderr, "%s: bad value for variable '%s'\n", progname, vnam(vc)); quit(1); +} + + +char * +dirfile(df, path) /* separate path into directory and file */ +char *df; +register char *path; +{ + register int i; + int psep; + + for (i = 0, psep = -1; path[i]; i++) + if (path[i] == '/') + psep = i; + if (df != NULL) + if (psep == 0) { + df[0] = '/'; + df[1] = '\0'; + } else if (psep > 0) { + strncpy(df, path, psep); + df[psep] = '\0'; + } else + df[0] = '\0'; + return(path+psep+1); +} + + +int +getblur(double *bf) /* get # blur samples (and fraction) */ +{ + double blurf; + int nblur; + char *s; + + if (!vdef(MBLUR)) { + if (bf != NULL) + *bf = 0.0; + return(0); + } + blurf = atof(vval(MBLUR)); + if (blurf < 0.0) + blurf = 0.0; + if (bf != NULL) + *bf = blurf; + if (blurf <= FTINY) + return(0); + s = sskip(vval(MBLUR)); + if (!*s) + return(DEF_NBLUR); + nblur = atoi(s); + if (nblur <= 0) + return(1); + return(nblur); }