ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimate.c
Revision: 2.1
Committed: Fri Jan 12 12:16:17 1996 UTC (28 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 2.1 /* Copyright (c) 1995 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Radiance animation control program
9     */
10    
11     #include "standard.h"
12     #include <sys/types.h>
13     #include <sys/stat.h>
14     #include "view.h"
15     #include "vars.h"
16     /* input variables */
17     #define HOST 0 /* rendering host machine */
18     #define RENDER 1 /* rendering options */
19     #define PFILT 2 /* pfilt options */
20     #define PINTERP 3 /* pinterp options */
21     #define OCTREE 4 /* octree file name */
22     #define DIRECTORY 5 /* working (sub)directory */
23     #define BASENAME 6 /* output image base name */
24     #define VIEWFILE 7 /* animation frame views */
25     #define START 8 /* starting frame number */
26     #define END 9 /* ending frame number */
27     #define RIF 10 /* rad input file */
28     #define NEXTANIM 11 /* next animation file */
29     #define ANIMATE 12 /* animation command */
30     #define TRANSFER 13 /* frame transfer command */
31     #define ARCHIVE 14 /* archiving command */
32     #define INTERP 15 /* # frames to interpolate */
33     #define OVERSAMP 16 /* # times to oversample image */
34     #define MBLUR 17 /* samples for motion blur */
35     #define RTRACE 18 /* use rtrace with pinterp? */
36     #define DISKSPACE 19 /* how much disk space to use */
37     #define RESOLUTION 20 /* desired final resolution */
38     #define EXPOSURE 21 /* how to compute exposure */
39    
40     int NVARS = 22; /* total number of variables */
41    
42     VARIABLE vv[] = { /* variable-value pairs */
43     {"host", 4, 0, NULL, NULL},
44     {"render", 3, 0, NULL, catvalues},
45     {"pfilt", 2, 0, NULL, catvalues},
46     {"pinterp", 2, 0, NULL, catvalues},
47     {"OCTREE", 3, 0, NULL, onevalue},
48     {"DIRECTORY", 3, 0, NULL, onevalue},
49     {"BASENAME", 3, 0, NULL, onevalue},
50     {"VIEWFILE", 2, 0, NULL, onevalue},
51     {"START", 2, 0, NULL, intvalue},
52     {"END", 2, 0, NULL, intvalue},
53     {"RIF", 3, 0, NULL, onevalue},
54     {"NEXTANIM", 3, 0, NULL, onevalue},
55     {"ANIMATE", 2, 0, NULL, onevalue},
56     {"TRANSFER", 2, 0, NULL, onevalue},
57     {"ARCHIVE", 2, 0, NULL, onevalue},
58     {"INTERP", 3, 0, NULL, intvalue},
59     {"OVERSAMP", 2, 0, NULL, fltvalue},
60     {"MBLUR", 2, 0, NULL, onevalue},
61     {"RTRACE", 2, 0, NULL, boolvalue},
62     {"DISKSPACE", 3, 0, NULL, fltvalue},
63     {"RESOLUTION", 3, 0, NULL, onevalue},
64     {"EXPOSURE", 3, 0, NULL, onevalue},
65     };
66    
67     #define SFNAME "STATUS" /* status file name */
68    
69     struct {
70     char host[64]; /* control host name */
71     int pid; /* control process id */
72     char cfname[128]; /* control file name */
73     int rnext; /* next frame to render */
74     int fnext; /* next frame to filter */
75     int tnext; /* next frame to transfer */
76     } astat; /* animation status */
77    
78     char *progname; /* our program name */
79     char *cfname; /* our control file name */
80    
81     int nowarn = 0; /* turn warnings off? */
82     int silent = 0; /* silent mode? */
83     int noaction = 0; /* take no action? */
84    
85     char rendopt[2048] = ""; /* rendering options */
86     char rresopt[32]; /* rendering resolution options */
87     char fresopt[32]; /* filter resolution options */
88     int pfiltalways; /* always use pfilt? */
89    
90     VIEW *getview();
91     char *getexp();
92    
93    
94     main(argc, argv)
95     int argc;
96     char *argv[];
97     {
98     int explicate = 0;
99     int i;
100    
101     progname = argv[0]; /* get arguments */
102     for (i = 1; i < argc && argv[i][0] == '-'; i++)
103     switch (argv[i][1]) {
104     case 'e': /* print variables */
105     explicate++;
106     break;
107     case 'w': /* turn off warnings */
108     nowarn++;
109     break;
110     case 's': /* silent mode */
111     silent++;
112     break;
113     case 'n': /* take no action */
114     noaction++;
115     break;
116     default:
117     goto userr;
118     }
119     if (i != argc-1)
120     goto userr;
121     cfname = argv[i];
122     /* load variables */
123     loadvars(cfname);
124     /* did we get DIRECTORY? */
125     checkdir();
126     /* check status */
127     if (getastat() < 0) {
128     fprintf(stderr, "%s: exiting\n", progname);
129     quit(1);
130     }
131     /* pfilt always if options given */
132     pfiltalways = vdef(PFILT);
133     /* load RIF if any */
134     if (vdef(RIF))
135     getradfile(vval(RIF));
136     /* set defaults */
137     setdefaults();
138     /* print variables */
139     if (explicate)
140     printvars(stdout);
141     /* run animation */
142     animate();
143     /* all done */
144     if (vdef(NEXTANIM)) {
145     argv[i] = vval(NEXTANIM); /* just change input file */
146     if (!silent)
147     printargs(argc, argv, stdout);
148     if (!noaction) {
149     execvp(progname, argv); /* pass to next */
150     quit(1); /* shouldn't return */
151     }
152     }
153     quit(0);
154     userr:
155     fprintf(stderr, "Usage: %s [-s][-n][-w][-e] anim_file\n", progname);
156     quit(1);
157     }
158    
159    
160     getastat() /* check/set animation status */
161     {
162     char buf[256];
163     FILE *fp;
164    
165     sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME);
166     if ((fp = fopen(buf, "r")) == NULL) {
167     if (errno != ENOENT) {
168     perror(buf);
169     return(-1);
170     }
171     astat.rnext = astat.fnext = astat.tnext = 0;
172     goto setours;
173     }
174     if (fscanf(fp, "Control host: %s\n", astat.host) != 1)
175     goto fmterr;
176     if (fscanf(fp, "Control PID: %d\n", &astat.pid) != 1)
177     goto fmterr;
178     if (fscanf(fp, "Control file: %s\n", astat.cfname) != 1)
179     goto fmterr;
180     if (fscanf(fp, "Next render: %d\n", &astat.rnext) != 1)
181     goto fmterr;
182     if (fscanf(fp, "Next filter: %d\n", &astat.fnext) != 1)
183     goto fmterr;
184     if (fscanf(fp, "Next transfer: %d\n", &astat.tnext) != 1)
185     goto fmterr;
186     fclose(fp);
187     if (astat.pid != 0) { /* thinks it's still running */
188     gethostname(buf, sizeof(buf));
189     if (strcmp(buf, astat.host)) {
190     fprintf(stderr,
191     "%s: process %d may still be running on host %s\n",
192     progname, astat.pid, astat.host);
193     return(-1);
194     }
195     if (kill(astat.pid, 0) != -1 || errno != ESRCH) {
196     fprintf(stderr, "%s: process %d is still running\n",
197     progname, astat.pid);
198     return(-1);
199     }
200     /* assume it is dead */
201     }
202     if (strcmp(cfname, astat.cfname) && astat.tnext != 0) { /* other's */
203     fprintf(stderr, "%s: unfinished job \"%s\"\n",
204     progname, astat.cfname);
205     return(-1);
206     }
207     setours: /* set our values */
208     gethostname(astat.host, sizeof(astat.host));
209     astat.pid = getpid();
210     strcpy(astat.cfname, cfname);
211     return(0);
212     fmterr:
213     fprintf(stderr, "%s: format error in status file \"%s\"\n",
214     progname, buf);
215     fclose(fp);
216     return(-1);
217     }
218    
219    
220     putastat() /* put out current status */
221     {
222     char buf[256];
223     FILE *fp;
224    
225     sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME);
226     if ((fp = fopen(buf, "w")) == NULL) {
227     perror(buf);
228     quit(1);
229     }
230     fprintf(fp, "Control host: %s\n", astat.host);
231     fprintf(fp, "Control PID: %d\n", astat.pid);
232     fprintf(fp, "Control file: %s\n", astat.cfname);
233     fprintf(fp, "Next render: %d\n", astat.rnext);
234     fprintf(fp, "Next filter: %d\n", astat.fnext);
235     fprintf(fp, "Next transfer: %d\n", astat.tnext);
236     fclose(fp);
237     }
238    
239    
240     checkdir() /* make sure we have our directory */
241     {
242     struct stat stb;
243    
244     if (!vdef(DIRECTORY)) {
245     fprintf(stderr, "%s: %s undefined\n",
246     progname, vnam(DIRECTORY));
247     quit(1);
248     }
249     if (stat(vval(DIRECTORY), &stb) == -1) {
250     if (errno == ENOENT && mkdir(vval(DIRECTORY), 0777) == 0)
251     return;
252     perror(vval(DIRECTORY));
253     quit(1);
254     }
255     if (!(stb.st_mode & S_IFDIR)) {
256     fprintf(stderr, "%s: not a directory\n", vval(DIRECTORY));
257     quit(1);
258     }
259     }
260    
261    
262     setdefaults() /* set default values */
263     {
264     char buf[256];
265    
266     if (vdef(OCTREE) == vdef(ANIMATE)) {
267     fprintf(stderr, "%s: either %s or %s must be defined\n",
268     progname, vnam(OCTREE), vnam(ANIMATE));
269     quit(1);
270     }
271     if (!vdef(VIEWFILE)) {
272     fprintf(stderr, "%s: %s undefined\n", progname, vnam(VIEWFILE));
273     quit(1);
274     }
275     if (!vdef(START)) {
276     vval(START) = "1";
277     vdef(START)++;
278     }
279     if (!vdef(END)) {
280     sprintf(buf, "%d", countviews());
281     vval(END) = savqstr(buf);
282     vdef(END)++;
283     }
284     if (!vdef(BASENAME)) {
285     sprintf(buf, "%s/frame%%03d", vval(DIRECTORY));
286     vval(BASENAME) = savqstr(buf);
287     vdef(BASENAME)++;
288     }
289     if (!vdef(RESOLUTION)) {
290     vval(RESOLUTION) = "640";
291     vdef(RESOLUTION)++;
292     }
293     if (!vdef(OVERSAMP)) {
294     vval(OVERSAMP) = "2";
295     vdef(OVERSAMP)++;
296     }
297     if (!vdef(INTERP)) {
298     vval(INTERP) = "0";
299     vdef(INTERP)++;
300     }
301     if (!vdef(MBLUR)) {
302     vval(MBLUR) = "0";
303     vdef(MBLUR)++;
304     }
305     if (!vdef(RTRACE)) {
306     vval(RTRACE) = "F";
307     vdef(RTRACE)++;
308     }
309     if (!vdef(DISKSPACE)) {
310     if (!nowarn)
311     fprintf(stderr,
312     "%s: warning - no %s setting, assuming 100 Mbytes available\n",
313     progname, vnam(DISKSPACE));
314     vval(DISKSPACE) = "100";
315     vdef(DISKSPACE)++;
316     }
317     /* append rendering options */
318     if (vdef(RENDER))
319     sprintf(rendopt+strlen(rendopt), " %s", vval(RENDER));
320     }
321    
322    
323     getradfile(rfname) /* run rad and get needed variables */
324     char *rfname;
325     {
326     static short mvar[] = {OCTREE,PFILT,RESOLUTION,EXPOSURE,-1};
327     char combuf[256];
328     register int i;
329     register char *cp;
330     /* create rad command */
331     sprintf(rendopt, " @%s/render.opt", vval(DIRECTORY));
332     sprintf(combuf,
333     "rad -v 0 -s -e -w %s OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
334     rfname, rendopt+2);
335     cp = combuf;
336     while (*cp) cp++; /* match unset variables */
337     for (i = 0; mvar[i] >= 0; i++)
338     if (!vdef(mvar[i])) {
339     *cp++ = '|';
340     strcpy(cp, vnam(mvar[i]));
341     while (*cp) cp++;
342     }
343     sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY));
344     cp += 11; /* point to file name */
345     if (system(combuf)) {
346     fprintf(stderr, "%s: bad rad input file \"%s\"\n",
347     progname, rfname);
348     quit(1);
349     }
350     loadvars(cp); /* load variables and remove file */
351     unlink(cp);
352     }
353    
354    
355     animate() /* run animation */
356     {
357     int xres, yres;
358     float pa, mult;
359     int frames_batch;
360     register int i;
361     double d1, d2;
362     /* compute rpict resolution */
363     i = sscanf(vval(RESOLUTION), "%d %d %f", &xres, &yres, &pa);
364     mult = vflt(OVERSAMP);
365     if (i == 3) {
366     sprintf(rresopt, "-x %d -y %d -pa %f", (int)(mult*xres),
367     (int)(mult*yres), pa);
368     sprintf(fresopt, "-x %d -y %d -pa %f", xres, yres, pa);
369     } else if (i) {
370     if (i == 1) yres = xres;
371     sprintf(rresopt, "-x %d -y %d", (int)(mult*xres),
372     (int)(mult*yres));
373     sprintf(fresopt, "-x %d -y %d -pa 1", xres, yres);
374     } else
375     badvalue(RESOLUTION);
376     /* consistency checks */
377     if (vdef(ANIMATE)) {
378     if (vint(INTERP)) {
379     if (!nowarn)
380     fprintf(stderr,
381     "%s: resetting %s=0 for animation\n",
382     progname, vnam(INTERP));
383     vval(INTERP) = "0";
384     }
385     if (atoi(vval(MBLUR))) { /* can't handle this yet */
386     if (!nowarn)
387     fprintf(stderr,
388     "%s: resetting %s=0 for animation\n",
389     progname, vnam(MBLUR));
390     vval(MBLUR) = "0";
391     }
392     }
393     /* figure # frames per batch */
394     d1 = mult*xres*mult*yres*4; /* space for orig. picture */
395     if ((i=vint(INTERP)) || atoi(vval(MBLUR)))
396     d1 += mult*xres*mult*yres*4; /* space for z-buffer */
397     d2 = xres*yres*4; /* space for final picture */
398     frames_batch = (i+1)*(vflt(DISKSPACE)*1048576.-d1)/(d1+i*d2);
399     if (frames_batch < i+2) {
400     fprintf(stderr, "%s: insufficient disk space allocated\n",
401     progname);
402     quit(1);
403     }
404     /* initialize status file */
405     if (astat.rnext == 0)
406     astat.rnext = astat.fnext = astat.tnext = vint(START);
407     putastat();
408     /* render in batches */
409     while (astat.rnext <= vint(END)) {
410     renderframes(frames_batch);
411     filterframes();
412     transferframes();
413     }
414     /* mark status as finished */
415     astat.pid = 0;
416     putastat();
417     /* close open files */
418     getview(0);
419     getexp(0);
420     }
421    
422    
423     renderframes(nframes) /* render next nframes frames */
424     int nframes;
425     {
426     static char vendbuf[16];
427     VIEW *vp;
428     FILE *fp = NULL;
429     char vfname[128];
430     int lastframe;
431     register int i;
432    
433     if (astat.tnext < astat.rnext) /* other work to do first */
434     return;
435     /* create batch view file */
436     if (!vdef(ANIMATE)) {
437     sprintf(vfname, "%s/anim.vf", vval(DIRECTORY));
438     if ((fp = fopen(vfname, "w")) == NULL) {
439     perror(vfname);
440     quit(1);
441     }
442     }
443     /* bound batch properly */
444     lastframe = astat.rnext + nframes - 1;
445     if ((lastframe-1) % (vint(INTERP)+1)) /* need even interval */
446     lastframe += vint(INTERP)+1 - ((lastframe-1)%(vint(INTERP)+1));
447     if (lastframe > vint(END)) /* check for end */
448     lastframe = vint(END);
449     /* render each view */
450     for (i = astat.rnext; i <= lastframe; i++) {
451     if ((vp = getview(i)) == NULL) {
452     if (!nowarn)
453     fprintf(stderr,
454     "%s: ran out of views before last frame\n",
455     progname);
456     sprintf(vval(END)=vendbuf, "%d", i-1);
457     lastframe = i - 1;
458     break;
459     }
460     if (vdef(ANIMATE)) /* animate frame */
461     animrend(i, vp);
462     else { /* else record it */
463     fputs(VIEWSTR, fp);
464     fprintview(vp, fp);
465     putc('\n', fp);
466     }
467     }
468     if (vdef(ANIMATE)) /* wait for renderings to finish */
469     animwait(0);
470     else { /* else if walk-through */
471     fclose(fp); /* close view file */
472     walkwait(astat.rnext, lastframe, vfname); /* walk it */
473     unlink(vfname); /* remove view file */
474     }
475     if (vdef(ARCHIVE)) /* archive results */
476     archive(astat.rnext, lastframe);
477     astat.rnext = i; /* update status */
478     putastat();
479     }
480    
481    
482     filterframes() /* catch up with filtering */
483     {
484     VIEW *vp;
485     register int i;
486    
487     if (astat.tnext < astat.fnext) /* other work to do first */
488     return;
489     /* filter each view */
490     for (i = astat.fnext; i < astat.rnext; i++) {
491     if ((vp = getview(i)) == NULL) { /* get view i */
492     fprintf(stderr,
493     "%s: unexpected error reading view for frame %d\n",
494     progname, i);
495     quit(1);
496     }
497     dofilt(i, vp, getexp(i)); /* filter frame */
498     }
499     filtwait(0); /* wait for filter processes */
500     astat.fnext = i; /* update status */
501     putastat();
502     }
503    
504    
505     transferframes() /* catch up with picture transfers */
506     {
507     char combuf[10240];
508     register char *cp;
509     register int i;
510    
511     if (astat.tnext >= astat.fnext) /* nothing to do, yet */
512     return;
513     if (!vdef(TRANSFER)) { /* no transfer function -- leave 'em */
514     astat.tnext = astat.fnext;
515     putastat(); /* update status */
516     return;
517     }
518     strcpy(combuf, vval(TRANSFER)); /* start transfer command */
519     cp = combuf + strlen(combuf);
520     /* make argument list */
521     for (i = astat.tnext; i < astat.fnext; i++) {
522     *cp++ = ' ';
523     sprintf(cp, vval(BASENAME), i);
524     while (*cp) cp++;
525     strcpy(cp, ".pic");
526     cp += 4;
527     }
528     if (runcom(combuf)) { /* transfer frames */
529     fprintf(stderr, "%s: error running transfer command\n",
530     progname);
531     quit(1);
532     }
533     astat.tnext = i; /* update status */
534     putastat();
535     }
536    
537    
538     animrend(frame, vp) /* start animation frame */
539     int frame;
540     VIEW *vp;
541     {
542     char combuf[2048];
543     char fname[128];
544    
545     sprintf(fname, vval(BASENAME), frame);
546     strcat(fname, ".unf");
547     if (access(fname, F_OK) == 0)
548     return;
549     sprintf(combuf, "%s %d | rpict%s%s %s > %s", vval(ANIMATE), frame,
550     rendopt, viewopt(vp), rresopt, fname);
551     if (runcom(combuf)) {
552     fprintf(stderr, "%s: error rendering frame %d\n",
553     progname, frame);
554     quit(1);
555     }
556     }
557    
558    
559     animwait(nwait) /* wait for renderings to finish */
560     int nwait;
561     {
562     /* currently does nothing since parallel rendering not working */
563     }
564    
565    
566     walkwait(first, last, vfn) /* walk-through frames */
567     int first, last;
568     char *vfn;
569     {
570     char combuf[2048];
571     register int i;
572    
573     if (!noaction && vint(INTERP)) /* create dummy frames */
574     for (i = first; i <= last; i++)
575     if (i < vint(END) && (i-1) % (vint(INTERP)+1)) {
576     sprintf(combuf, vval(BASENAME), i);
577     strcat(combuf, ".unf");
578     close(open(combuf, O_RDONLY|O_CREAT, 0666));
579     }
580     /* create command */
581     sprintf(combuf, "rpict%s ", rendopt);
582     if (vint(INTERP) || atoi(vval(MBLUR)))
583     sprintf(combuf+strlen(combuf), "-z %s.zbf ", vval(BASENAME));
584     sprintf(combuf+strlen(combuf), "-o %s.unf %s -S %d %s < %s",
585     vval(BASENAME), rresopt, first, vval(OCTREE), vfn);
586     if (runcom(combuf)) {
587     fprintf(stderr,
588     "%s: error rendering walk-through frames %d through %d\n",
589     progname, first, last);
590     quit(1);
591     }
592     if (!noaction && vint(INTERP)) /* remove dummy frames */
593     for (i = first; i <= last; i++)
594     if (i < vint(END) && (i-1) % (vint(INTERP)+1)) {
595     sprintf(combuf, vval(BASENAME), i);
596     strcat(combuf, ".unf");
597     unlink(combuf);
598     }
599     }
600    
601    
602     recover(frame) /* recover the specified frame */
603     int frame;
604     {
605     char combuf[2048];
606     char fname[128];
607     register char *cp;
608    
609     sprintf(fname, vval(BASENAME), frame);
610     if (vdef(ANIMATE))
611     sprintf(combuf, "%s %d | rpict%s",
612     vval(ANIMATE), frame, rendopt);
613     else
614     sprintf(combuf, "rpict%s", rendopt);
615     cp = combuf + strlen(combuf);
616     if (vint(INTERP) || atoi(vval(MBLUR))) {
617     sprintf(cp, " -z %s.zbf", fname);
618     while (*cp) cp++;
619     }
620     sprintf(cp, " -ro %s.unf", fname);
621     while (*cp) cp++;
622     if (!vdef(ANIMATE)) {
623     *cp++ = ' ';
624     strcpy(cp, vval(OCTREE));
625     }
626     if (runcom(combuf)) {
627     fprintf(stderr, "%s: error recovering frame %d\n",
628     progname, frame);
629     quit(1);
630     }
631     }
632    
633    
634     archive(first, last) /* archive finished renderings */
635     int first, last;
636     {
637     char combuf[10240];
638     int offset;
639     struct stat stb;
640     register char *cp;
641     register int i;
642    
643     strcpy(cp=combuf, vval(ARCHIVE));
644     while (*cp) cp++;
645     offset = cp - combuf;
646     *cp++ = ' '; /* make argument list */
647     for (i = first; i <= last; i++) {
648     sprintf(cp, vval(BASENAME), i);
649     strcat(cp, ".unf");
650     if (stat(cp, &stb) == 0 && stb.st_size > 0) { /* non-zero? */
651     while (*cp) cp++;
652     *cp++ = ' ';
653     sprintf(cp, vval(BASENAME), i);
654     strcat(cp, ".zbf");
655     if (access(cp, F_OK) == 0) { /* exists? */
656     while (*cp) cp++;
657     *cp++ = ' ';
658     }
659     }
660     }
661     *--cp = '\0';
662     if (cp <= combuf + offset) /* no files? */
663     return;
664     if (runcom(combuf)) { /* run archive command */
665     fprintf(stderr,
666     "%s: error running archive command on frames %d through %d\n",
667     progname, first, last);
668     quit(1);
669     }
670     }
671    
672    
673     dofilt(frame, vp, ep) /* filter frame */
674     int frame;
675     VIEW *vp;
676     char *ep;
677     {
678     char fnbefore[128], fnafter[128];
679     char combuf[1024], fname[128];
680     int usepinterp, usepfilt;
681     int frbefore, frafter, triesleft;
682     /* check what is needed */
683     usepinterp = atoi(vval(MBLUR));
684     usepfilt = pfiltalways | ep==NULL;
685     /* compute rendered views */
686     frbefore = frame - ((frame-1) % (vint(INTERP)+1));
687     frafter = frbefore + vint(INTERP) + 1;
688     if (frafter > vint(END))
689     frafter = vint(END);
690     if (frafter == frame) { /* pfilt only */
691     frbefore = frafter;
692     usepinterp = 0; /* update what's needed */
693     usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1");
694     triesleft = 2;
695     } else if (frbefore == frame) { /* no interpolation */
696     /* remove unneeded files */
697     if (frbefore-vint(INTERP)-1 >= 1) {
698     sprintf(fname, vval(BASENAME), frbefore-vint(INTERP)-1);
699     sprintf(combuf, "rm -f %s.unf %s.zbf", fname, fname);
700     runcom(combuf);
701     }
702     /* update what's needed */
703     if (usepinterp)
704     triesleft = 3;
705     else {
706     usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1");
707     triesleft = 2;
708     }
709     } else { /* interpolation needed */
710     usepinterp++;
711     triesleft = 3;
712     }
713     if (frafter >= astat.rnext) { /* next batch unavailable */
714     frafter = frbefore;
715     if (triesleft > 2)
716     triesleft = 2;
717     }
718     sprintf(fnbefore, vval(BASENAME), frbefore);
719     sprintf(fnafter, vval(BASENAME), frafter);
720     tryit: /* generate command */
721     if (usepinterp) { /* using pinterp */
722     if (atoi(vval(MBLUR))) {
723     FILE *fp; /* motion blurring */
724     sprintf(fname, "%s/vw0", vval(DIRECTORY));
725     if ((fp = fopen(fname, "w")) == NULL) {
726     perror(fname); quit(1);
727     }
728     fputs(VIEWSTR, fp);
729     fprintview(vp, fp);
730     putc('\n', fp); fclose(fp);
731     if ((vp = getview(frame+1)) == NULL) {
732     fprintf(stderr,
733     "%s: unexpected error reading view for frame %d\n",
734     progname, frame+1);
735     quit(1);
736     }
737     sprintf(fname, "%s/vw1", vval(DIRECTORY));
738     if ((fp = fopen(fname, "w")) == NULL) {
739     perror(fname); quit(1);
740     }
741     fputs(VIEWSTR, fp);
742     fprintview(vp, fp);
743     putc('\n', fp); fclose(fp);
744     sprintf(combuf,
745     "(pmblur %s %d %s/vw0 %s/vw1; rm -f %s/vw0 %s/vw1) | pinterp -B",
746     *sskip(vval(MBLUR)) ? sskip(vval(MBLUR)) : "1",
747     atoi(vval(MBLUR)), vval(DIRECTORY),
748     vval(DIRECTORY), vval(DIRECTORY),
749     vval(DIRECTORY), vval(DIRECTORY));
750     } else /* no blurring */
751     strcpy(combuf, "pinterp");
752     strcat(combuf, viewopt(vp));
753     if (vbool(RTRACE))
754     sprintf(combuf+strlen(combuf), " -ff -fr '%s %s'",
755     rendopt, vval(OCTREE));
756     if (vdef(PINTERP))
757     sprintf(combuf+strlen(combuf), " %s", vval(PINTERP));
758     if (usepfilt)
759     sprintf(combuf+strlen(combuf), " %s", rresopt);
760     else
761     sprintf(combuf+strlen(combuf), " %s -e %s",
762     fresopt, ep);
763     sprintf(combuf+strlen(combuf), " %s.unf %s.zbf",
764     fnbefore, fnbefore);
765     if (frafter != frbefore)
766     sprintf(combuf+strlen(combuf), " %s.unf %s.zbf",
767     fnafter, fnafter);
768     if (usepfilt) { /* also pfilt */
769     if (vdef(PFILT))
770     sprintf(combuf+strlen(combuf), " | pfilt %s",
771     vval(PFILT));
772     else
773     strcat(combuf, " | pfilt");
774     if (ep != NULL)
775     sprintf(combuf+strlen(combuf), " -1 -e %s %s",
776     ep, fresopt);
777     else
778     sprintf(combuf+strlen(combuf), " %s", fresopt);
779     }
780     } else if (usepfilt) { /* pfilt only */
781     if (vdef(PFILT))
782     sprintf(combuf, "pfilt %s", vval(PFILT));
783     else
784     strcpy(combuf, "pfilt");
785     if (ep != NULL)
786     sprintf(combuf+strlen(combuf), " -1 -e %s %s %s.unf",
787     ep, fresopt, fnbefore);
788     else
789     sprintf(combuf+strlen(combuf), " %s %s.unf",
790     fresopt, fnbefore);
791     } else { /* else just check it */
792     sprintf(combuf, "ra_rgbe -r %s.unf", fnbefore);
793     }
794     /* output file name */
795     sprintf(fname, vval(BASENAME), frame);
796     sprintf(combuf+strlen(combuf), " > %s.pic", fname);
797     if (runcom(combuf)) /* run filter command */
798     switch (--triesleft) {
799     case 2: /* try to recover frafter */
800     recover(frafter);
801     goto tryit;
802     case 1: /* try to recover frbefore */
803     recover(frbefore);
804     goto tryit;
805     default: /* we've really failed */
806     fprintf(stderr,
807     "%s: unrecoverable filtering error on frame %d\n",
808     progname, frame);
809     quit(1);
810     }
811     }
812    
813    
814     filtwait(nwait) /* wait for filtering processes to finish */
815     int nwait;
816     {
817     /* currently does nothing since parallel filtering not working */
818     }
819    
820    
821     VIEW *
822     getview(n) /* get view number n */
823     int n;
824     {
825     static FILE *viewfp = NULL; /* view file pointer */
826     static int viewnum = 0; /* current view number */
827     static VIEW curview = STDVIEW; /* current view */
828     char linebuf[256];
829    
830     if (n == 0) { /* signal to close file and clean up */
831     if (viewfp != NULL) {
832     fclose(viewfp);
833     viewfp = NULL;
834     viewnum = 0;
835     copystruct(&curview, &stdview);
836     }
837     return(NULL);
838     }
839     if (viewfp == NULL) { /* open file */
840     if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
841     perror(vval(VIEWFILE));
842     quit(1);
843     }
844     } else if (n < viewnum) { /* rewind file */
845     if (fseek(viewfp, 0L, 0) == EOF) {
846     perror(vval(VIEWFILE));
847     quit(1);
848     }
849     copystruct(&curview, &stdview);
850     viewnum = 0;
851     }
852     while (n > viewnum) { /* scan to desired view */
853     if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
854     return(NULL);
855     if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
856     viewnum++;
857     }
858     return(&curview); /* return it */
859     }
860    
861    
862     int
863     countviews() /* count views in view file */
864     {
865     register int n = 0;
866    
867     while (getview(n+1) != NULL)
868     n++;
869     return(n);
870     }
871    
872    
873     char *
874     getexp(n) /* get exposure for nth frame */
875     int n;
876     {
877     extern char *fskip();
878     static char expval[32];
879     static FILE *expfp = NULL;
880     static long *exppos;
881     static int curfrm;
882     register char *cp;
883    
884     if (n == 0) { /* signal to close file */
885     if (expfp != NULL) {
886     fclose(expfp);
887     expfp = NULL;
888     }
889     return(NULL);
890     }
891     if (!vdef(EXPOSURE)) /* no setting (auto) */
892     return(NULL);
893     if (isflt(vval(EXPOSURE))) /* always the same */
894     return(vval(EXPOSURE));
895     if (expfp == NULL) { /* open exposure file */
896     if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
897     fprintf(stderr,
898     "%s: cannot open exposure file \"%s\"\n",
899     progname, vval(EXPOSURE));
900     quit(1);
901     }
902     curfrm = vint(END) + 1; /* init lookup tab. */
903     exppos = (long *)malloc(curfrm*sizeof(long *));
904     if (exppos == NULL) {
905     perror(progname);
906     quit(1);
907     }
908     while (curfrm--)
909     exppos[curfrm] = -1L;
910     curfrm = 0;
911     }
912     /* find position in file */
913     if (n-1 != curfrm && n != curfrm && exppos[n-1] >= 0 &&
914     fseek(expfp, exppos[curfrm=n-1], 0) == EOF) {
915     fprintf(stderr, "%s: seek error on exposure file\n", progname);
916     quit(1);
917     }
918     while (n > curfrm) { /* read exposure */
919     if (exppos[curfrm] < 0)
920     exppos[curfrm] = ftell(expfp);
921     if (fgets(expval, sizeof(expval), expfp) == NULL) {
922     fprintf(stderr, "%s: too few exposures\n",
923     vval(EXPOSURE));
924     quit(1);
925     }
926     curfrm++;
927     cp = fskip(expval); /* check format */
928     if (cp == NULL || *cp != '\n') {
929     fprintf(stderr,
930     "%s: exposure format error on line %d\n",
931     vval(EXPOSURE), curfrm);
932     quit(1);
933     }
934     *cp = '\0';
935     }
936     return(expval); /* return value */
937     }
938    
939    
940     runcom(cs) /* run command */
941     char *cs;
942     {
943     if (!silent) /* echo it */
944     printf("\t%s\n", cs);
945     if (noaction)
946     return(0);
947     fflush(stdout); /* flush output and pass to shell */
948     return(system(cs));
949     }
950    
951    
952     rmfile(fn) /* remove a file */
953     char *fn;
954     {
955     if (!silent)
956     #ifdef MSDOS
957     printf("\tdel %s\n", fn);
958     #else
959     printf("\trm -f %s\n", fn);
960     #endif
961     if (noaction)
962     return(0);
963     return(unlink(fn));
964     }
965    
966    
967     badvalue(vc) /* report bad variable value and exit */
968     int vc;
969     {
970     fprintf(stderr, "%s: bad value for variable '%s'\n",
971     progname, vnam(vc));
972     quit(1);
973     }