ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rad.c
Revision: 2.37
Committed: Sat Jan 1 09:16:50 1994 UTC (30 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.36: +9 -3 lines
Log Message:
added -w option to avoid warnings on variable assignments

File Contents

# User Rev Content
1 greg 2.37 /* Copyright (c) 1994 Regents of the University of California */
2 greg 2.1
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Executive program for oconv, rpict and pfilt
9     */
10    
11     #include "standard.h"
12     #include "paths.h"
13     #include <ctype.h>
14 greg 2.35 #include <sys/types.h>
15 greg 2.1
16    
17     typedef struct {
18     char *name; /* variable name */
19     short nick; /* # characters required for nickname */
20     short nass; /* # assignments made */
21     char *value; /* assigned value(s) */
22     int (*fixval)(); /* assignment checking function */
23     } VARIABLE;
24    
25 greg 2.30 int onevalue(), catvalues(), boolvalue(),
26     qualvalue(), fltvalue(), intvalue();
27 greg 2.1
28     /* variables */
29     #define OBJECT 0 /* object files */
30     #define SCENE 1 /* scene files */
31     #define MATERIAL 2 /* material files */
32 greg 2.26 #define ILLUM 3 /* mkillum input files */
33     #define MKILLUM 4 /* mkillum options */
34     #define RENDER 5 /* rendering options */
35     #define OCONV 6 /* oconv options */
36     #define PFILT 7 /* pfilt options */
37     #define VIEW 8 /* view(s) for picture(s) */
38     #define ZONE 9 /* simulation zone */
39     #define QUALITY 10 /* desired rendering quality */
40     #define OCTREE 11 /* octree file name */
41     #define PICTURE 12 /* picture file name */
42     #define AMBFILE 13 /* ambient file name */
43     #define OPTFILE 14 /* rendering options file */
44     #define EXPOSURE 15 /* picture exposure setting */
45     #define RESOLUTION 16 /* maximum picture resolution */
46     #define UP 17 /* view up (X, Y or Z) */
47     #define INDIRECT 18 /* indirection in lighting */
48     #define DETAIL 19 /* level of scene detail */
49     #define PENUMBRAS 20 /* shadow penumbras are desired */
50     #define VARIABILITY 21 /* level of light variability */
51     #define REPORT 22 /* report frequency and errfile */
52 greg 2.1 /* total number of variables */
53 greg 2.26 #define NVARS 23
54 greg 2.1
55     VARIABLE vv[NVARS] = { /* variable-value pairs */
56     {"objects", 3, 0, NULL, catvalues},
57     {"scene", 3, 0, NULL, catvalues},
58     {"materials", 3, 0, NULL, catvalues},
59 greg 2.26 {"illum", 3, 0, NULL, catvalues},
60     {"mkillum", 3, 0, NULL, catvalues},
61 greg 2.1 {"render", 3, 0, NULL, catvalues},
62     {"oconv", 3, 0, NULL, catvalues},
63     {"pfilt", 2, 0, NULL, catvalues},
64     {"view", 2, 0, NULL, NULL},
65     {"ZONE", 2, 0, NULL, onevalue},
66 greg 2.30 {"QUALITY", 3, 0, NULL, qualvalue},
67 greg 2.1 {"OCTREE", 3, 0, NULL, onevalue},
68     {"PICTURE", 3, 0, NULL, onevalue},
69     {"AMBFILE", 3, 0, NULL, onevalue},
70     {"OPTFILE", 3, 0, NULL, onevalue},
71 greg 2.30 {"EXPOSURE", 3, 0, NULL, fltvalue},
72 greg 2.1 {"RESOLUTION", 3, 0, NULL, onevalue},
73     {"UP", 2, 0, NULL, onevalue},
74 greg 2.30 {"INDIRECT", 3, 0, NULL, intvalue},
75     {"DETAIL", 3, 0, NULL, qualvalue},
76     {"PENUMBRAS", 3, 0, NULL, boolvalue},
77     {"VARIABILITY", 3, 0, NULL, qualvalue},
78 greg 2.1 {"REPORT", 3, 0, NULL, onevalue},
79     };
80    
81     VARIABLE *matchvar();
82     char *nvalue();
83    
84 greg 2.3 #define UPPER(c) ((c)&~0x20) /* ASCII trick */
85    
86 greg 2.1 #define vnam(vc) (vv[vc].name)
87     #define vdef(vc) (vv[vc].nass)
88     #define vval(vc) (vv[vc].value)
89     #define vint(vc) atoi(vval(vc))
90 greg 2.3 #define vlet(vc) UPPER(vval(vc)[0])
91 greg 2.30 #define vscale vlet
92 greg 2.1 #define vbool(vc) (vlet(vc)=='T')
93    
94 greg 2.30 #define HIGH 'H'
95     #define MEDIUM 'M'
96     #define LOW 'L'
97 greg 2.1
98 greg 2.6 /* overture calculation file */
99     #ifdef NIX
100     char overfile[] = "overture.raw";
101     #else
102     char overfile[] = "/dev/null";
103     #endif
104    
105 greg 2.35 extern time_t fdate(), time();
106 greg 2.1
107 greg 2.35 time_t scenedate; /* date of latest scene or object file */
108     time_t octreedate; /* date of octree */
109     time_t matdate; /* date of latest material file */
110     time_t illumdate; /* date of last illum file */
111 greg 2.1
112 greg 2.26 char *oct0name; /* name of pre-mkillum octree */
113 greg 2.35 time_t oct0date; /* date of pre-mkillum octree */
114 greg 2.26 char *oct1name; /* name of post-mkillum octree */
115 greg 2.35 time_t oct1date; /* date of post-mkillum octree (>= matdate) */
116 greg 2.26
117 greg 2.37 int nowarn = 0; /* no warnings */
118 greg 2.1 int explicate = 0; /* explicate variables */
119     int silent = 0; /* do work silently */
120     int noaction = 0; /* don't do anything */
121 greg 2.21 int sayview = 0; /* print view out */
122 greg 2.1 char *rvdevice = NULL; /* rview output device */
123     char *viewselect = NULL; /* specific view only */
124    
125     int overture = 0; /* overture calculation needed */
126    
127     char *progname; /* global argv[0] */
128 greg 2.22 char *rifname; /* global rad input file name */
129 greg 2.1
130     char radname[MAXPATH]; /* root Radiance file name */
131    
132    
133     main(argc, argv)
134     int argc;
135     char *argv[];
136     {
137     char ropts[512];
138     int i;
139    
140     progname = argv[0];
141     /* get options */
142     for (i = 1; i < argc && argv[i][0] == '-'; i++)
143     switch (argv[i][1]) {
144     case 's':
145     silent++;
146     break;
147     case 'n':
148     noaction++;
149     break;
150     case 'e':
151     explicate++;
152     break;
153     case 'o':
154     rvdevice = argv[++i];
155     break;
156 greg 2.20 case 'V':
157 greg 2.21 sayview++;
158     break;
159 greg 2.1 case 'v':
160     viewselect = argv[++i];
161     break;
162 greg 2.37 case 'w':
163     nowarn++;
164     break;
165 greg 2.1 default:
166     goto userr;
167     }
168     if (i >= argc)
169     goto userr;
170 greg 2.22 rifname = argv[i];
171 greg 2.1 /* assign Radiance root file name */
172 greg 2.22 rootname(radname, rifname);
173 greg 2.1 /* load variable values */
174 greg 2.22 load(rifname);
175 greg 2.1 /* get any additional assignments */
176     for (i++; i < argc; i++)
177     setvariable(argv[i]);
178     /* check assignments */
179     checkvalues();
180     /* check files and dates */
181     checkfiles();
182     /* set default values as necessary */
183     setdefaults();
184     /* print all values if requested */
185     if (explicate)
186     printvals();
187 greg 2.26 /* build octree (and run mkillum) */
188 greg 2.7 oconv();
189     /* check date on ambient file */
190     checkambfile();
191 greg 2.1 /* run simulation */
192     renderopts(ropts);
193     xferopts(ropts);
194     if (rvdevice != NULL)
195     rview(ropts);
196     else
197     rpict(ropts);
198     exit(0);
199     userr:
200     fprintf(stderr,
201 greg 2.26 "Usage: %s [-s][-n][-e][-V][-v view][-o dev] rfile [VAR=value ..]\n",
202 greg 2.1 progname);
203     exit(1);
204     }
205    
206    
207     rootname(rn, fn) /* remove tail from end of fn */
208     register char *rn, *fn;
209     {
210     char *tp, *dp;
211    
212     for (tp = NULL, dp = rn; *rn = *fn++; rn++)
213     if (ISDIRSEP(*rn))
214     dp = rn;
215     else if (*rn == '.')
216     tp = rn;
217     if (tp != NULL && tp > dp)
218     *tp = '\0';
219     }
220    
221    
222 greg 2.25 #define NOCHAR 127 /* constant for character to delete */
223    
224    
225 greg 2.1 load(rfname) /* load Radiance simulation file */
226     char *rfname;
227     {
228     FILE *fp;
229 greg 2.4 char buf[512];
230 greg 2.1 register char *cp;
231    
232     if (rfname == NULL)
233     fp = stdin;
234 greg 2.3 else if ((fp = fopen(rfname, "r")) == NULL)
235     syserr(rfname);
236 greg 2.1 while (fgetline(buf, sizeof(buf), fp) != NULL) {
237     for (cp = buf; *cp; cp++) {
238     switch (*cp) {
239     case '\\':
240 greg 2.25 *cp++ = NOCHAR;
241 greg 2.1 continue;
242     case '#':
243     *cp = '\0';
244     break;
245 greg 2.4 default:
246     continue;
247 greg 2.1 }
248     break;
249     }
250     setvariable(buf);
251     }
252     fclose(fp);
253     }
254    
255    
256     setvariable(ass) /* assign variable according to string */
257     register char *ass;
258     {
259     char varname[32];
260 greg 2.25 int n;
261 greg 2.1 register char *cp;
262     register VARIABLE *vp;
263     register int i;
264    
265     while (isspace(*ass)) /* skip leading space */
266     ass++;
267     cp = varname; /* extract name */
268     while (cp < varname+sizeof(varname)-1
269     && *ass && !isspace(*ass) && *ass != '=')
270     *cp++ = *ass++;
271     *cp = '\0';
272     if (!varname[0])
273     return; /* no variable name! */
274     /* trim value */
275     while (isspace(*ass) || *ass == '=')
276     ass++;
277 greg 2.25 for (n = strlen(ass); n > 0; n--)
278     if (!isspace(ass[n-1]))
279     break;
280 greg 2.37 if (!n && !nowarn) {
281 greg 2.1 fprintf(stderr, "%s: warning - missing value for variable '%s'\n",
282     progname, varname);
283     return;
284     }
285     /* match variable from list */
286     vp = matchvar(varname);
287     if (vp == NULL) {
288     fprintf(stderr, "%s: unknown variable '%s'\n",
289     progname, varname);
290     exit(1);
291     }
292     /* assign new value */
293 greg 2.4 if (i = vp->nass) {
294     cp = vp->value;
295     while (i--)
296     while (*cp++)
297     ;
298     i = cp - vp->value;
299     vp->value = realloc(vp->value, i+n+1);
300     } else
301     vp->value = malloc(n+1);
302 greg 2.3 if (vp->value == NULL)
303     syserr(progname);
304 greg 2.25 cp = vp->value+i; /* copy value, squeezing spaces */
305     *cp = *ass;
306     for (i = 1; i <= n; i++) {
307     if (ass[i] == NOCHAR)
308     continue;
309     if (isspace(*cp))
310     while (isspace(ass[i]))
311     i++;
312     *++cp = ass[i];
313     }
314 greg 2.26 if (isspace(*cp)) /* remove trailing space */
315     *cp = '\0';
316 greg 2.1 vp->nass++;
317     }
318    
319    
320     VARIABLE *
321     matchvar(nam) /* match a variable by its name */
322     char *nam;
323     {
324     int n = strlen(nam);
325     register int i;
326    
327     for (i = 0; i < NVARS; i++)
328     if (n >= vv[i].nick && !strncmp(nam, vv[i].name, n))
329     return(vv+i);
330     return(NULL);
331     }
332    
333    
334     char *
335     nvalue(vp, n) /* return nth variable value */
336     VARIABLE *vp;
337     register int n;
338     {
339     register char *cp;
340    
341 greg 2.19 if (vp == NULL | n < 0 | n >= vp->nass)
342 greg 2.1 return(NULL);
343     cp = vp->value;
344     while (n--)
345     while (*cp++)
346     ;
347     return(cp);
348     }
349    
350    
351     checkvalues() /* check assignments */
352     {
353     register int i;
354    
355     for (i = 0; i < NVARS; i++)
356     if (vv[i].fixval != NULL)
357     (*vv[i].fixval)(vv+i);
358     }
359    
360    
361     onevalue(vp) /* only one assignment for this variable */
362     register VARIABLE *vp;
363     {
364     if (vp->nass < 2)
365     return;
366 greg 2.37 if (!nowarn)
367     fprintf(stderr,
368     "%s: warning - multiple assignment of variable '%s'\n",
369 greg 2.1 progname, vp->name);
370 greg 2.2 do
371 greg 2.1 vp->value += strlen(vp->value)+1;
372 greg 2.2 while (--vp->nass > 1);
373 greg 2.1 }
374    
375    
376     catvalues(vp) /* concatenate variable values */
377     register VARIABLE *vp;
378     {
379     register char *cp;
380    
381     if (vp->nass < 2)
382     return;
383     for (cp = vp->value; vp->nass > 1; vp->nass--) {
384     while (*cp)
385     cp++;
386     *cp++ = ' ';
387     }
388     }
389    
390    
391 greg 2.30 int
392     badmatch(tv, cv) /* case insensitive truncated comparison */
393     register char *tv, *cv;
394     {
395     if (!*tv) return(1); /* null string cannot match */
396     do
397     if (UPPER(*tv) != *cv++)
398     return(1);
399     while (*++tv);
400     return(0); /* OK */
401     }
402    
403    
404     boolvalue(vp) /* check boolean for legal values */
405     register VARIABLE *vp;
406     {
407     if (!vp->nass) return;
408     onevalue(vp);
409     switch (UPPER(vp->value[0])) {
410     case 'T':
411     if (badmatch(vp->value, "TRUE")) break;
412     return;
413     case 'F':
414     if (badmatch(vp->value, "FALSE")) break;
415     return;
416     }
417     fprintf(stderr, "%s: illegal value for boolean variable '%s'\n",
418     progname, vp->name);
419     exit(1);
420     }
421    
422    
423     qualvalue(vp) /* check qualitative var. for legal values */
424     register VARIABLE *vp;
425     {
426     if (!vp->nass) return;
427     onevalue(vp);
428     switch (UPPER(vp->value[0])) {
429     case 'L':
430     if (badmatch(vp->value, "LOW")) break;
431     return;
432     case 'M':
433     if (badmatch(vp->value, "MEDIUM")) break;
434     return;
435     case 'H':
436     if (badmatch(vp->value, "HIGH")) break;
437     return;
438     }
439     fprintf(stderr, "%s: illegal value for qualitative variable '%s'\n",
440     progname, vp->name);
441     exit(1);
442     }
443    
444    
445     intvalue(vp) /* check integer variable for legal values */
446     register VARIABLE *vp;
447     {
448     if (!vp->nass) return;
449     onevalue(vp);
450     if (isint(vp->value)) return;
451     fprintf(stderr, "%s: illegal value for integer variable '%s'\n",
452     progname, vp->name);
453     exit(1);
454     }
455    
456    
457     fltvalue(vp) /* check float variable for legal values */
458     register VARIABLE *vp;
459     {
460     if (!vp->nass) return;
461     onevalue(vp);
462     if (isflt(vp->value)) return;
463     fprintf(stderr, "%s: illegal value for real variable '%s'\n",
464     progname, vp->name);
465     exit(1);
466     }
467    
468    
469 greg 2.35 time_t
470 greg 2.1 checklast(fnames) /* check files and find most recent */
471     register char *fnames;
472     {
473     char thisfile[MAXPATH];
474 greg 2.35 time_t thisdate, lastdate = 0;
475 greg 2.1 register char *cp;
476    
477 greg 2.26 if (fnames == NULL)
478     return(0);
479 greg 2.1 while (*fnames) {
480     while (isspace(*fnames)) fnames++;
481     cp = thisfile;
482 greg 2.4 while (*fnames && !isspace(*fnames))
483     *cp++ = *fnames++;
484 greg 2.1 *cp = '\0';
485 greg 2.26 if (!(thisdate = fdate(thisfile)))
486 greg 2.3 syserr(thisfile);
487 greg 2.1 if (thisdate > lastdate)
488     lastdate = thisdate;
489     }
490     return(lastdate);
491     }
492    
493    
494 greg 2.26 char *
495     newfname(orig, pred) /* create modified file name */
496     char *orig;
497     int pred;
498     {
499     extern char *rindex();
500     register char *cp;
501     register int n;
502     int suffix;
503    
504 greg 2.27 n = 0; cp = orig; suffix = -1; /* suffix position, length */
505     while (*cp) {
506     if (*cp == '.') suffix = n;
507     else if (ISDIRSEP(*cp)) suffix = -1;
508     cp++; n++;
509     }
510     if (suffix == -1) suffix = n;
511 greg 2.26 if ((cp = bmalloc(n+2)) == NULL)
512     syserr(progname);
513     strncpy(cp, orig, suffix);
514     cp[suffix] = pred; /* root name + pred + suffix */
515     strcpy(cp+suffix+1, orig+suffix);
516     return(cp);
517     }
518    
519    
520 greg 2.1 checkfiles() /* check for existence and modified times */
521     {
522 greg 2.35 time_t objdate;
523 greg 2.1
524 greg 2.2 if (!vdef(OCTREE)) {
525 greg 2.26 if ((vval(OCTREE) = bmalloc(strlen(radname)+5)) == NULL)
526 greg 2.3 syserr(progname);
527 greg 2.26 sprintf(vval(OCTREE), "%s.oct", radname);
528 greg 2.2 vdef(OCTREE)++;
529     }
530     octreedate = fdate(vval(OCTREE));
531 greg 2.26 if (vdef(ILLUM)) { /* illum requires secondary octrees */
532     oct0name = newfname(vval(OCTREE), '0');
533     oct1name = newfname(vval(OCTREE), '1');
534     oct0date = fdate(oct0name);
535     oct1date = fdate(oct1name);
536     } else
537     oct0name = oct1name = vval(OCTREE);
538     if ((scenedate = checklast(vval(SCENE))) &&
539     (objdate = checklast(vval(OBJECT))) > scenedate)
540     scenedate = objdate;
541     illumdate = checklast(vval(ILLUM));
542     if (!octreedate & !scenedate & !illumdate) {
543     fprintf(stderr, "%s: need '%s' or '%s' or '%s'\n", progname,
544     vnam(OCTREE), vnam(SCENE), vnam(ILLUM));
545 greg 2.1 exit(1);
546     }
547 greg 2.26 matdate = checklast(vval(MATERIAL));
548 greg 2.1 }
549    
550    
551 greg 2.2 getoctcube(org, sizp) /* get octree bounding cube */
552     double org[3], *sizp;
553 greg 2.1 {
554 greg 2.2 extern FILE *popen();
555     static double oorg[3], osiz = 0.;
556 greg 2.26 double min[3], max[3];
557     char buf[512];
558 greg 2.1 FILE *fp;
559 greg 2.26 register int i;
560 greg 2.1
561 greg 2.26 if (osiz <= FTINY)
562     if (noaction && fdate(oct1name) <
563     (scenedate>illumdate?scenedate:illumdate)) {
564     /* run getbbox */
565     sprintf(buf, "getbbox -w -h %s",
566     vdef(SCENE) ? vval(SCENE) : vval(ILLUM));
567     if ((fp = popen(buf, "r")) == NULL)
568     syserr("getbbox");
569     if (fscanf(fp, "%lf %lf %lf %lf %lf %lf",
570     &min[0], &max[0], &min[1], &max[1],
571     &min[2], &max[2]) != 6) {
572     fprintf(stderr,
573     "%s: error reading bounding box from getbbox\n",
574     progname);
575     exit(1);
576     }
577     for (i = 0; i < 3; i++)
578     if (max[i] - min[i] > osiz)
579     osiz = max[i] - min[i];
580     for (i = 0; i < 3; i++)
581     oorg[i] = (max[i]+min[i]-osiz)*.5;
582     pclose(fp);
583     } else { /* from octree */
584     oconv(); /* does nothing if done already */
585     sprintf(buf, "getinfo -d < %s", oct1name);
586     if ((fp = popen(buf, "r")) == NULL)
587     syserr("getinfo");
588     if (fscanf(fp, "%lf %lf %lf %lf", &oorg[0], &oorg[1],
589     &oorg[2], &osiz) != 4) {
590     fprintf(stderr,
591 greg 2.2 "%s: error reading bounding cube from getinfo\n",
592 greg 2.26 progname);
593     exit(1);
594     }
595     pclose(fp);
596 greg 2.2 }
597     org[0] = oorg[0]; org[1] = oorg[1]; org[2] = oorg[2]; *sizp = osiz;
598     }
599    
600    
601     setdefaults() /* set default values for unassigned var's */
602     {
603     double org[3], size;
604     char buf[128];
605    
606 greg 2.1 if (!vdef(ZONE)) {
607 greg 2.2 getoctcube(org, &size);
608     sprintf(buf, "E %g %g %g %g %g %g", org[0], org[0]+size,
609     org[1], org[1]+size, org[2], org[2]+size);
610 greg 2.1 vval(ZONE) = savqstr(buf);
611     vdef(ZONE)++;
612     }
613     if (!vdef(INDIRECT)) {
614     vval(INDIRECT) = "0";
615     vdef(INDIRECT)++;
616     }
617     if (!vdef(QUALITY)) {
618     vval(QUALITY) = "L";
619     vdef(QUALITY)++;
620     }
621     if (!vdef(RESOLUTION)) {
622     vval(RESOLUTION) = "512";
623     vdef(RESOLUTION)++;
624     }
625     if (!vdef(PICTURE)) {
626     vval(PICTURE) = radname;
627     vdef(PICTURE)++;
628     }
629     if (!vdef(VIEW)) {
630     vval(VIEW) = "X";
631     vdef(VIEW)++;
632     }
633     if (!vdef(DETAIL)) {
634     vval(DETAIL) = "M";
635     vdef(DETAIL)++;
636     }
637     if (!vdef(PENUMBRAS)) {
638     vval(PENUMBRAS) = "F";
639     vdef(PENUMBRAS)++;
640     }
641     if (!vdef(VARIABILITY)) {
642     vval(VARIABILITY) = "L";
643     vdef(VARIABILITY)++;
644     }
645     }
646    
647    
648     printvals() /* print variable values */
649     {
650 greg 2.36 int i, j, clipline;
651     register char *cp;
652     register int k;
653 greg 2.1
654 greg 2.36 for (i = 0; i < NVARS; i++) /* print each variable */
655     for (j = 0; j < vdef(i); j++) { /* print each assignment */
656     fputs(vnam(i), stdout);
657     fputs("= ", stdout);
658     k = clipline = ( vv[i].fixval == catvalues ? 64 : 320 )
659     - strlen(vnam(i)) ;
660     cp = nvalue(vv+i, j);
661     while (*cp) {
662     putchar(*cp++);
663     if (--k <= 0) { /* line too long */
664     while (*cp && !isspace(*cp))
665     putchar(*cp++); /* finish this word */
666     if (*cp) { /* start new line */
667     putchar('\n');
668     fputs(vnam(i), stdout);
669     putchar('=');
670     k = clipline;
671     }
672     }
673     }
674     putchar('\n');
675     }
676 greg 2.1 fflush(stdout);
677     }
678    
679    
680 greg 2.26 oconv() /* run oconv and mkillum if necessary */
681 greg 2.1 {
682 greg 2.26 static char illumtmp[] = "ilXXXXXX";
683     char combuf[512], ocopts[64], mkopts[64];
684 greg 2.1
685 greg 2.26 oconvopts(ocopts); /* get options */
686     if (octreedate < scenedate) { /* check date on original octree */
687     /* build command */
688     if (vdef(MATERIAL))
689     sprintf(combuf, "oconv%s %s %s > %s", ocopts,
690     vval(MATERIAL), vval(SCENE), vval(OCTREE));
691     else
692     sprintf(combuf, "oconv%s %s > %s", ocopts,
693     vval(SCENE), vval(OCTREE));
694    
695     if (runcom(combuf)) { /* run it */
696     fprintf(stderr,
697     "%s: error generating octree\n\t%s removed\n",
698     progname, vval(OCTREE));
699     unlink(vval(OCTREE));
700     exit(1);
701     }
702 greg 2.35 octreedate = time((time_t *)NULL);
703 greg 2.26 }
704     if (oct1name == vval(OCTREE)) /* no mkillum? */
705     oct1date = octreedate > matdate ? octreedate : matdate;
706     if (oct1date >= octreedate & oct1date >= matdate
707     & oct1date >= illumdate) /* all done */
708 greg 2.1 return;
709 greg 2.26 /* make octree0 */
710     if (oct0date < scenedate | oct0date < illumdate) {
711     /* build command */
712     if (octreedate)
713     sprintf(combuf, "oconv%s -i %s %s > %s", ocopts,
714     vval(OCTREE), vval(ILLUM), oct0name);
715     else if (vdef(MATERIAL))
716     sprintf(combuf, "oconv%s %s %s > %s", ocopts,
717     vval(MATERIAL), vval(ILLUM), oct0name);
718     else
719     sprintf(combuf, "oconv%s %s > %s", ocopts,
720     vval(ILLUM), oct0name);
721     if (runcom(combuf)) { /* run it */
722     fprintf(stderr,
723     "%s: error generating octree\n\t%s removed\n",
724     progname, oct0name);
725     unlink(oct0name);
726     exit(1);
727     }
728 greg 2.35 oct0date = time((time_t *)NULL);
729 greg 2.26 }
730     mkillumopts(mkopts); /* build mkillum command */
731     mktemp(illumtmp);
732     sprintf(combuf, "mkillum%s %s \"<\" %s > %s", mkopts,
733     oct0name, vval(ILLUM), illumtmp);
734     if (runcom(combuf)) { /* run it */
735     fprintf(stderr, "%s: error running mkillum\n", progname);
736     unlink(illumtmp);
737     exit(1);
738     }
739     /* make octree1 (frozen) */
740     if (octreedate)
741     sprintf(combuf, "oconv%s -f -i %s %s > %s", ocopts,
742     vval(OCTREE), illumtmp, oct1name);
743     else if (vdef(MATERIAL))
744     sprintf(combuf, "oconv%s -f %s %s > %s", ocopts,
745     vval(MATERIAL), illumtmp, oct1name);
746 greg 2.4 else
747 greg 2.26 sprintf(combuf, "oconv%s -f %s > %s", ocopts,
748     illumtmp, oct1name);
749 greg 2.4 if (runcom(combuf)) { /* run it */
750 greg 2.26 fprintf(stderr,
751     "%s: error generating octree\n\t%s removed\n",
752     progname, oct1name);
753     unlink(oct1name);
754 greg 2.1 exit(1);
755     }
756 greg 2.35 oct1date = time((time_t *)NULL);
757 greg 2.26 rmfile(illumtmp);
758 greg 2.1 }
759    
760    
761     char *
762     addarg(op, arg) /* add argument and advance pointer */
763     register char *op, *arg;
764     {
765     *op = ' ';
766     while (*++op = *arg++)
767     ;
768     return(op);
769     }
770    
771    
772     oconvopts(oo) /* get oconv options */
773 greg 2.2 register char *oo;
774 greg 2.1 {
775 greg 2.2 /* BEWARE: This may be called via setdefaults(), so no assumptions */
776    
777 greg 2.1 *oo = '\0';
778     if (vdef(OCONV))
779     addarg(oo, vval(OCONV));
780     }
781    
782    
783 greg 2.26 mkillumopts(mo) /* get mkillum options */
784     register char *mo;
785     {
786     /* BEWARE: This may be called via setdefaults(), so no assumptions */
787    
788     *mo = '\0';
789     if (vdef(MKILLUM))
790     addarg(mo, vval(MKILLUM));
791     }
792    
793    
794 greg 2.7 checkambfile() /* check date on ambient file */
795     {
796 greg 2.35 time_t afdate;
797 greg 2.7
798 greg 2.11 if (!vdef(AMBFILE))
799     return;
800 greg 2.26 if (!(afdate = fdate(vval(AMBFILE))))
801 greg 2.11 return;
802 greg 2.26 if (oct1date > afdate)
803 greg 2.11 rmfile(vval(AMBFILE));
804 greg 2.7 }
805    
806    
807 greg 2.2 double
808     ambval() /* compute ambient value */
809 greg 2.1 {
810 greg 2.3 if (vdef(EXPOSURE)) {
811 greg 2.2 if (vval(EXPOSURE)[0] == '+' || vval(EXPOSURE)[0] == '-')
812     return(.5/pow(2.,atof(vval(EXPOSURE))));
813 greg 2.20 return(.5/atof(vval(EXPOSURE)));
814 greg 2.3 }
815 greg 2.2 if (vlet(ZONE) == 'E')
816     return(10.);
817 greg 2.3 if (vlet(ZONE) == 'I')
818 greg 2.2 return(.01);
819 greg 2.3 badvalue(ZONE);
820 greg 2.30 }
821    
822    
823     renderopts(op) /* set rendering options */
824     char *op;
825     {
826     switch(vscale(QUALITY)) {
827     case LOW:
828     lowqopts(op);
829     break;
830     case MEDIUM:
831     medqopts(op);
832     break;
833     case HIGH:
834 greg 2.32 hiqopts(op);
835 greg 2.30 break;
836     }
837 greg 2.2 }
838 greg 2.1
839 greg 2.2
840     lowqopts(op) /* low quality rendering options */
841     register char *op;
842     {
843     double d, org[3], siz[3];
844    
845 greg 2.1 *op = '\0';
846 greg 2.2 if (sscanf(vval(ZONE), "%*s %lf %lf %lf %lf %lf %lf", &org[0],
847 greg 2.3 &siz[0], &org[1], &siz[1], &org[2], &siz[2]) != 6)
848     badvalue(ZONE);
849 greg 2.2 siz[0] -= org[0]; siz[1] -= org[1]; siz[2] -= org[2];
850     getoctcube(org, &d);
851     d *= 3./(siz[0]+siz[1]+siz[2]);
852     switch (vscale(DETAIL)) {
853     case LOW:
854 greg 2.23 op = addarg(op, "-ps 16 -dp 64");
855 greg 2.2 sprintf(op, " -ar %d", (int)(4*d));
856     op += strlen(op);
857     break;
858     case MEDIUM:
859 greg 2.23 op = addarg(op, "-ps 8 -dp 128");
860 greg 2.2 sprintf(op, " -ar %d", (int)(8*d));
861     op += strlen(op);
862     break;
863     case HIGH:
864 greg 2.23 op = addarg(op, "-ps 4 -dp 256");
865 greg 2.2 sprintf(op, " -ar %d", (int)(16*d));
866     op += strlen(op);
867     break;
868     }
869     op = addarg(op, "-pt .16");
870     if (vbool(PENUMBRAS))
871     op = addarg(op, "-ds .4");
872 greg 2.4 else
873     op = addarg(op, "-ds 0");
874 greg 2.17 op = addarg(op, "-dt .2 -dc .25 -dr 0 -sj 0 -st .5");
875 greg 2.2 if (vdef(AMBFILE)) {
876     sprintf(op, " -af %s", vval(AMBFILE));
877     op += strlen(op);
878     } else
879     overture = 0;
880     switch (vscale(VARIABILITY)) {
881     case LOW:
882 greg 2.16 op = addarg(op, "-aa .4 -ad 64");
883 greg 2.2 break;
884     case MEDIUM:
885 greg 2.16 op = addarg(op, "-aa .3 -ad 128");
886 greg 2.2 break;
887     case HIGH:
888 greg 2.16 op = addarg(op, "-aa .25 -ad 256");
889 greg 2.2 break;
890     }
891     op = addarg(op, "-as 0");
892     d = ambval();
893     sprintf(op, " -av %.2g %.2g %.2g", d, d, d);
894     op += strlen(op);
895 greg 2.4 op = addarg(op, "-lr 3 -lw .02");
896 greg 2.1 if (vdef(RENDER))
897     op = addarg(op, vval(RENDER));
898     }
899    
900    
901 greg 2.2 medqopts(op) /* medium quality rendering options */
902     register char *op;
903 greg 2.1 {
904 greg 2.2 double d, org[3], siz[3];
905 greg 2.1
906     *op = '\0';
907 greg 2.2 if (sscanf(vval(ZONE), "%*s %lf %lf %lf %lf %lf %lf", &org[0],
908 greg 2.3 &siz[0], &org[1], &siz[1], &org[2], &siz[2]) != 6)
909     badvalue(ZONE);
910 greg 2.2 siz[0] -= org[0]; siz[1] -= org[1]; siz[2] -= org[2];
911     getoctcube(org, &d);
912     d *= 3./(siz[0]+siz[1]+siz[2]);
913     switch (vscale(DETAIL)) {
914     case LOW:
915     op = addarg(op, vbool(PENUMBRAS) ? "-ps 4" : "-ps 8");
916 greg 2.23 op = addarg(op, "-dp 256");
917 greg 2.2 sprintf(op, " -ar %d", (int)(8*d));
918     op += strlen(op);
919     break;
920     case MEDIUM:
921     op = addarg(op, vbool(PENUMBRAS) ? "-ps 3" : "-ps 6");
922 greg 2.23 op = addarg(op, "-dp 512");
923 greg 2.2 sprintf(op, " -ar %d", (int)(16*d));
924     op += strlen(op);
925     break;
926     case HIGH:
927     op = addarg(op, vbool(PENUMBRAS) ? "-ps 2" : "-ps 4");
928 greg 2.23 op = addarg(op, "-dp 1024");
929 greg 2.2 sprintf(op, " -ar %d", (int)(32*d));
930     op += strlen(op);
931     break;
932     }
933     op = addarg(op, "-pt .08");
934 greg 2.4 if (vbool(PENUMBRAS))
935 greg 2.28 op = addarg(op, "-ds .2 -dj .5");
936 greg 2.4 else
937 greg 2.2 op = addarg(op, "-ds .3");
938 greg 2.17 op = addarg(op, "-dt .1 -dc .5 -dr 1 -sj .7 -st .1");
939 greg 2.5 if (overture = vint(INDIRECT)) {
940     sprintf(op, " -ab %d", overture);
941     op += strlen(op);
942     }
943 greg 2.2 if (vdef(AMBFILE)) {
944     sprintf(op, " -af %s", vval(AMBFILE));
945     op += strlen(op);
946     } else
947     overture = 0;
948     switch (vscale(VARIABILITY)) {
949     case LOW:
950 greg 2.16 op = addarg(op, "-aa .25 -ad 196 -as 0");
951 greg 2.2 break;
952     case MEDIUM:
953 greg 2.16 op = addarg(op, "-aa .2 -ad 400 -as 64");
954 greg 2.2 break;
955     case HIGH:
956 greg 2.16 op = addarg(op, "-aa .15 -ad 768 -as 196");
957 greg 2.2 break;
958     }
959     d = ambval();
960     sprintf(op, " -av %.2g %.2g %.2g", d, d, d);
961     op += strlen(op);
962 greg 2.4 op = addarg(op, "-lr 6 -lw .002");
963 greg 2.1 if (vdef(RENDER))
964     op = addarg(op, vval(RENDER));
965     }
966    
967    
968 greg 2.2 hiqopts(op) /* high quality rendering options */
969     register char *op;
970 greg 2.1 {
971 greg 2.2 double d, org[3], siz[3];
972 greg 2.1
973     *op = '\0';
974 greg 2.2 if (sscanf(vval(ZONE), "%*s %lf %lf %lf %lf %lf %lf", &org[0],
975 greg 2.3 &siz[0], &org[1], &siz[1], &org[2], &siz[2]) != 6)
976     badvalue(ZONE);
977 greg 2.2 siz[0] -= org[0]; siz[1] -= org[1]; siz[2] -= org[2];
978     getoctcube(org, &d);
979     d *= 3./(siz[0]+siz[1]+siz[2]);
980     switch (vscale(DETAIL)) {
981     case LOW:
982     op = addarg(op, vbool(PENUMBRAS) ? "-ps 1" : "-ps 8");
983 greg 2.23 op = addarg(op, "-dp 1024");
984 greg 2.2 sprintf(op, " -ar %d", (int)(16*d));
985     op += strlen(op);
986     break;
987     case MEDIUM:
988     op = addarg(op, vbool(PENUMBRAS) ? "-ps 1" : "-ps 5");
989 greg 2.23 op = addarg(op, "-dp 2048");
990 greg 2.2 sprintf(op, " -ar %d", (int)(32*d));
991     op += strlen(op);
992     break;
993     case HIGH:
994     op = addarg(op, vbool(PENUMBRAS) ? "-ps 1" : "-ps 3");
995 greg 2.23 op = addarg(op, "-dp 4096");
996 greg 2.2 sprintf(op, " -ar %d", (int)(64*d));
997     op += strlen(op);
998     break;
999     }
1000     op = addarg(op, "-pt .04");
1001 greg 2.4 if (vbool(PENUMBRAS))
1002     op = addarg(op, "-ds .1 -dj .7");
1003     else
1004 greg 2.2 op = addarg(op, "-ds .2");
1005 greg 2.17 op = addarg(op, "-dt .05 -dc .75 -dr 3 -sj 1 -st .01");
1006 greg 2.2 sprintf(op, " -ab %d", overture=vint(INDIRECT)+1);
1007     op += strlen(op);
1008     if (vdef(AMBFILE)) {
1009     sprintf(op, " -af %s", vval(AMBFILE));
1010     op += strlen(op);
1011     } else
1012     overture = 0;
1013     switch (vscale(VARIABILITY)) {
1014     case LOW:
1015 greg 2.16 op = addarg(op, "-aa .15 -ad 256 -as 0");
1016 greg 2.2 break;
1017     case MEDIUM:
1018 greg 2.16 op = addarg(op, "-aa .125 -ad 512 -as 256");
1019 greg 2.2 break;
1020     case HIGH:
1021 greg 2.16 op = addarg(op, "-aa .08 -ad 1024 -as 512");
1022 greg 2.2 break;
1023     }
1024     d = ambval();
1025     sprintf(op, " -av %.2g %.2g %.2g", d, d, d);
1026     op += strlen(op);
1027 greg 2.4 op = addarg(op, "-lr 12 -lw .0005");
1028 greg 2.1 if (vdef(RENDER))
1029     op = addarg(op, vval(RENDER));
1030     }
1031    
1032    
1033     xferopts(ro) /* transfer options if indicated */
1034     char *ro;
1035     {
1036     int fd, n;
1037 greg 2.10 register char *cp;
1038 greg 2.1
1039     n = strlen(ro);
1040     if (n < 2)
1041     return;
1042     if (vdef(OPTFILE)) {
1043 greg 2.10 for (cp = ro; cp[1]; cp++)
1044     if (isspace(cp[1]) && cp[2] == '-' && isalpha(cp[3]))
1045     *cp = '\n';
1046     else
1047     *cp = cp[1];
1048     *cp = '\n';
1049     fd = open(vval(OPTFILE), O_WRONLY|O_CREAT|O_TRUNC, 0666);
1050     if (fd < 0 || write(fd, ro, n) != n || close(fd) < 0)
1051 greg 2.3 syserr(vval(OPTFILE));
1052 greg 2.15 sprintf(ro, " @%s", vval(OPTFILE));
1053 greg 2.1 }
1054     #ifdef MSDOS
1055     else if (n > 50) {
1056 greg 2.8 setenv("ROPT", ro+1);
1057 greg 2.1 strcpy(ro, " $ROPT");
1058     }
1059     #endif
1060     }
1061    
1062    
1063     pfiltopts(po) /* get pfilt options */
1064     register char *po;
1065     {
1066     *po = '\0';
1067     if (vdef(EXPOSURE)) {
1068     po = addarg(po, "-1 -e");
1069     po = addarg(po, vval(EXPOSURE));
1070     }
1071 greg 2.12 switch (vscale(QUALITY)) {
1072     case MEDIUM:
1073     po = addarg(po, "-r 1");
1074     break;
1075     case HIGH:
1076 greg 2.14 po = addarg(po, "-m .25");
1077 greg 2.12 break;
1078     }
1079 greg 2.1 if (vdef(PFILT))
1080     po = addarg(po, vval(PFILT));
1081     }
1082    
1083    
1084     matchword(s1, s2) /* match white-delimited words */
1085     register char *s1, *s2;
1086     {
1087     while (isspace(*s1)) s1++;
1088     while (isspace(*s2)) s2++;
1089     while (*s1 && !isspace(*s1))
1090     if (*s1++ != *s2++)
1091     return(0);
1092     return(!*s2 || isspace(*s2));
1093     }
1094    
1095    
1096     char *
1097     specview(vs) /* get proper view spec from vs */
1098     register char *vs;
1099     {
1100 greg 2.3 static char vup[7][12] = {"-vu 0 0 -1","-vu 0 -1 0","-vu -1 0 0",
1101     "-vu 0 0 1", "-vu 1 0 0","-vu 0 1 0","-vu 0 0 1"};
1102 greg 2.1 static char viewopts[128];
1103     register char *cp;
1104 greg 2.3 int xpos, ypos, zpos, viewtype, upax;
1105     register int i;
1106 greg 2.1 double cent[3], dim[3], mult, d;
1107    
1108 greg 2.9 if (vs == NULL || *vs == '-')
1109 greg 2.1 return(vs);
1110 greg 2.3 upax = 0; /* get the up vector */
1111     if (vdef(UP)) {
1112     if (vval(UP)[0] == '-' || vval(UP)[0] == '+')
1113     upax = 1-'X'+UPPER(vval(UP)[1]);
1114     else
1115     upax = 1-'X'+vlet(UP);
1116     if (upax < 1 | upax > 3)
1117     badvalue(UP);
1118     if (vval(UP)[0] == '-')
1119     upax = -upax;
1120     }
1121 greg 2.1 /* check standard view names */
1122     xpos = ypos = zpos = 0;
1123     if (*vs == 'X') {
1124     xpos = 1; vs++;
1125     } else if (*vs == 'x') {
1126     xpos = -1; vs++;
1127     }
1128     if (*vs == 'Y') {
1129     ypos = 1; vs++;
1130     } else if (*vs == 'y') {
1131     ypos = -1; vs++;
1132     }
1133     if (*vs == 'Z') {
1134     zpos = 1; vs++;
1135     } else if (*vs == 'z') {
1136     zpos = -1; vs++;
1137     }
1138 greg 2.3 viewtype = 'v';
1139 greg 2.1 if (*vs == 'v' | *vs == 'l' | *vs == 'a' | *vs == 'h')
1140     viewtype = *vs++;
1141     cp = viewopts;
1142 greg 2.3 if ((!*vs || isspace(*vs)) && (xpos|ypos|zpos)) { /* got one! */
1143 greg 2.1 *cp++ = '-'; *cp++ = 'v'; *cp++ = 't'; *cp++ = viewtype;
1144     if (sscanf(vval(ZONE), "%*s %lf %lf %lf %lf %lf %lf",
1145     &cent[0], &dim[0], &cent[1], &dim[1],
1146 greg 2.3 &cent[2], &dim[2]) != 6)
1147     badvalue(ZONE);
1148     for (i = 0; i < 3; i++) {
1149     dim[i] -= cent[i];
1150     cent[i] += .5*dim[i];
1151 greg 2.1 }
1152 greg 2.3 mult = vlet(ZONE)=='E' ? 2. : .45 ;
1153 greg 2.1 sprintf(cp, " -vp %.2g %.2g %.2g -vd %.2g %.2g %.2g",
1154     cent[0]+xpos*mult*dim[0],
1155     cent[1]+ypos*mult*dim[1],
1156     cent[2]+zpos*mult*dim[2],
1157     -xpos*dim[0], -ypos*dim[1], -zpos*dim[2]);
1158     cp += strlen(cp);
1159 greg 2.3 /* redirect up axis if necessary */
1160     switch (upax) {
1161     case 3: /* plus or minus Z axis */
1162     case -3:
1163     case 0:
1164     if (!(xpos|ypos))
1165     upax = 2;
1166 greg 2.1 break;
1167 greg 2.3 case 2: /* plus or minus Y axis */
1168     case -2:
1169     if (!(xpos|zpos))
1170     upax = 1;
1171     break;
1172     case 1: /* plus or minus X axis */
1173     case -1:
1174     if (!(ypos|zpos))
1175     upax = 3;
1176     break;
1177 greg 2.1 }
1178 greg 2.3 cp = addarg(cp, vup[upax+3]);
1179 greg 2.1 switch (viewtype) {
1180     case 'v':
1181     cp = addarg(cp, "-vh 45 -vv 45");
1182     break;
1183     case 'l':
1184     d = sqrt(dim[0]*dim[0]+dim[1]*dim[1]+dim[2]*dim[2]);
1185     sprintf(cp, " -vh %.2g -vv %.2g", d, d);
1186     cp += strlen(cp);
1187     break;
1188     case 'a':
1189     case 'h':
1190     cp = addarg(cp, "-vh 180 -vv 180");
1191     break;
1192     }
1193 greg 2.3 } else {
1194 greg 2.4 while (!isspace(*vs)) /* else skip id */
1195     if (!*vs++)
1196     return(NULL);
1197 greg 2.3 if (upax) { /* specify up vector */
1198     strcpy(cp, vup[upax+3]);
1199     cp += strlen(cp);
1200     }
1201     }
1202 greg 2.26 if (cp == viewopts) /* append any additional options */
1203     vs++; /* skip prefixed space if unneeded */
1204     strcpy(cp, vs);
1205 greg 2.8 #ifdef MSDOS
1206     if (strlen(viewopts) > 40) {
1207     setenv("VIEW", viewopts);
1208     return("$VIEW");
1209     }
1210     #endif
1211 greg 2.1 return(viewopts);
1212     }
1213    
1214    
1215     char *
1216     getview(n, vn) /* get view n, or NULL if none */
1217     int n;
1218 greg 2.8 char *vn; /* returned view name */
1219 greg 2.1 {
1220 greg 2.19 register char *mv;
1221 greg 2.1
1222 greg 2.8 if (viewselect != NULL) { /* command-line selected */
1223 greg 2.1 if (n) /* only do one */
1224     return(NULL);
1225     if (viewselect[0] == '-') { /* already specified */
1226     if (vn != NULL) *vn = '\0';
1227     return(viewselect);
1228     }
1229     if (vn != NULL) {
1230     for (mv = viewselect; *mv && !isspace(*mv);
1231     *vn++ = *mv++)
1232     ;
1233     *vn = '\0';
1234     }
1235 greg 2.19 /* view number? */
1236 greg 2.20 if (isint(viewselect))
1237 greg 2.19 return(specview(nvalue(vv+VIEW, atoi(viewselect)-1)));
1238 greg 2.1 /* check list */
1239     while ((mv = nvalue(vv+VIEW, n++)) != NULL)
1240     if (matchword(viewselect, mv))
1241     return(specview(mv));
1242     return(specview(viewselect)); /* standard view? */
1243     }
1244 greg 2.8 mv = nvalue(vv+VIEW, n); /* use view n */
1245     if (vn != NULL & mv != NULL) {
1246 greg 2.19 register char *mv2 = mv;
1247     if (*mv2 != '-')
1248     while (*mv2 && !isspace(*mv2))
1249     *vn++ = *mv2++;
1250 greg 2.1 *vn = '\0';
1251     }
1252 greg 2.8 return(specview(mv));
1253 greg 2.20 }
1254    
1255    
1256 greg 2.21 printview(vopts) /* print out selected view */
1257     register char *vopts;
1258 greg 2.20 {
1259 greg 2.24 extern char *atos(), *getenv();
1260 greg 2.20 char buf[256];
1261     FILE *fp;
1262 greg 2.21 register char *cp;
1263 greg 2.20
1264     if (vopts == NULL)
1265     return(-1);
1266     fputs("VIEW=", stdout);
1267     do {
1268     if (matchword(vopts, "-vf")) { /* expand view file */
1269     vopts = sskip(vopts);
1270     if (!*atos(buf, sizeof(buf), vopts))
1271     return(-1);
1272     if ((fp = fopen(buf, "r")) == NULL)
1273     return(-1);
1274     for (buf[sizeof(buf)-2] = '\n';
1275     fgets(buf, sizeof(buf), fp) != NULL &&
1276     buf[0] != '\n';
1277     buf[sizeof(buf)-2] = '\n') {
1278     if (buf[sizeof(buf)-2] != '\n') {
1279     ungetc(buf[sizeof(buf)-2], fp);
1280     buf[sizeof(buf)-2] = '\0';
1281     }
1282     if (matchword(buf, "VIEW=") ||
1283     matchword(buf, "rview")) {
1284     for (cp = sskip(buf); *cp && *cp != '\n'; cp++)
1285     putchar(*cp);
1286     }
1287     }
1288     fclose(fp);
1289     vopts = sskip(vopts);
1290     } else {
1291     while (isspace(*vopts))
1292     vopts++;
1293     putchar(' ');
1294 greg 2.24 #ifdef MSDOS
1295     if (*vopts == '$') { /* expand env. var. */
1296     if (!*atos(buf, sizeof(buf), vopts+1))
1297     return(-1);
1298     if ((cp = getenv(buf)) == NULL)
1299     return(-1);
1300     fputs(cp, stdout);
1301     vopts = sskip(vopts);
1302     } else
1303     #endif
1304     while (*vopts && !isspace(*vopts))
1305     putchar(*vopts++);
1306 greg 2.20 }
1307     } while (*vopts++);
1308     putchar('\n');
1309     return(0);
1310 greg 2.1 }
1311    
1312    
1313     rview(opts) /* run rview with first view */
1314     char *opts;
1315     {
1316 greg 2.21 char *vw;
1317 greg 2.1 char combuf[512];
1318     /* build command */
1319 greg 2.21 if ((vw = getview(0, NULL)) == NULL)
1320     return;
1321     if (sayview)
1322     printview(vw);
1323 greg 2.22 sprintf(combuf, "rview %s%s -R %s ", vw, opts, rifname);
1324 greg 2.1 if (rvdevice != NULL)
1325     sprintf(combuf+strlen(combuf), "-o %s ", rvdevice);
1326 greg 2.29 if (vdef(EXPOSURE))
1327     sprintf(combuf+strlen(combuf), "-pe %s ", vval(EXPOSURE));
1328 greg 2.26 strcat(combuf, oct1name);
1329 greg 2.4 if (runcom(combuf)) { /* run it */
1330 greg 2.1 fprintf(stderr, "%s: error running rview\n", progname);
1331     exit(1);
1332     }
1333     }
1334    
1335    
1336     rpict(opts) /* run rpict and pfilt for each view */
1337     char *opts;
1338     {
1339 greg 2.2 char combuf[1024];
1340 greg 2.3 char rawfile[MAXPATH], picfile[MAXPATH], rep[MAXPATH+16], res[32];
1341     char pfopts[128];
1342 greg 2.1 char vs[32], *vw;
1343     int vn, mult;
1344     /* get pfilt options */
1345     pfiltopts(pfopts);
1346     /* get resolution, reporting */
1347 greg 2.31 switch (vscale(QUALITY)) {
1348     case LOW:
1349     mult = 1;
1350     break;
1351     case MEDIUM:
1352     mult = 2;
1353     break;
1354     case HIGH:
1355     mult = 3;
1356     break;
1357     }
1358 greg 2.1 {
1359     int xres, yres;
1360     double aspect;
1361     int n;
1362     n = sscanf(vval(RESOLUTION), "%d %d %lf", &xres, &yres, &aspect);
1363     if (n == 3)
1364     sprintf(res, "-x %d -y %d -pa %.3f",
1365     mult*xres, mult*yres, aspect);
1366     else if (n) {
1367     if (n == 1) yres = xres;
1368     sprintf(res, "-x %d -y %d", mult*xres, mult*yres);
1369 greg 2.3 } else
1370     badvalue(RESOLUTION);
1371 greg 2.1 }
1372     rep[0] = '\0';
1373     if (vdef(REPORT)) {
1374     double minutes;
1375     int n;
1376     n = sscanf(vval(REPORT), "%lf %s", &minutes, rawfile);
1377     if (n == 2)
1378     sprintf(rep, " -t %d -e %s", (int)(minutes*60), rawfile);
1379     else if (n == 1)
1380     sprintf(rep, " -t %d", (int)(minutes*60));
1381 greg 2.3 else
1382     badvalue(REPORT);
1383 greg 2.1 }
1384     /* do each view */
1385     vn = 0;
1386     while ((vw = getview(vn++, vs)) != NULL) {
1387 greg 2.21 if (sayview)
1388     printview(vw);
1389 greg 2.1 if (!vs[0])
1390     sprintf(vs, "%d", vn);
1391     sprintf(picfile, "%s_%s.pic", vval(PICTURE), vs);
1392     /* check date on picture */
1393 greg 2.26 if (fdate(picfile) >= oct1date)
1394 greg 2.1 continue;
1395     /* build rpict command */
1396     sprintf(rawfile, "%s_%s.raw", vval(PICTURE), vs);
1397 greg 2.26 if (fdate(rawfile) >= oct1date) /* recover */
1398 greg 2.1 sprintf(combuf, "rpict%s%s -ro %s %s",
1399 greg 2.26 rep, opts, rawfile, oct1name);
1400 greg 2.1 else {
1401     if (overture) { /* run overture calculation */
1402     sprintf(combuf,
1403     "rpict%s %s%s -x 64 -y 64 -ps 1 %s > %s",
1404     rep, vw, opts,
1405 greg 2.26 oct1name, overfile);
1406 greg 2.4 if (runcom(combuf)) {
1407 greg 2.1 fprintf(stderr,
1408 greg 2.6 "%s: error in overture for view %s\n",
1409     progname, vs);
1410 greg 2.1 exit(1);
1411     }
1412 greg 2.6 #ifdef NIX
1413     rmfile(overfile);
1414     #endif
1415 greg 2.1 }
1416     sprintf(combuf, "rpict%s %s %s%s %s > %s",
1417     rep, vw, res, opts,
1418 greg 2.29 oct1name, rawfile);
1419 greg 2.1 }
1420 greg 2.4 if (runcom(combuf)) { /* run rpict */
1421 greg 2.1 fprintf(stderr, "%s: error rendering view %s\n",
1422     progname, vs);
1423     exit(1);
1424     }
1425     /* build pfilt command */
1426     if (mult > 1)
1427     sprintf(combuf, "pfilt%s -x /%d -y /%d %s > %s",
1428     pfopts, mult, mult, rawfile, picfile);
1429     else
1430     sprintf(combuf, "pfilt%s %s > %s", pfopts,
1431     rawfile, picfile);
1432 greg 2.4 if (runcom(combuf)) { /* run pfilt */
1433 greg 2.1 fprintf(stderr,
1434     "%s: error filtering view %s\n\t%s removed\n",
1435     progname, vs, picfile);
1436     unlink(picfile);
1437     exit(1);
1438     }
1439     /* remove raw file */
1440 greg 2.4 rmfile(rawfile);
1441     }
1442     }
1443    
1444    
1445     runcom(cs) /* run command */
1446     char *cs;
1447     {
1448     if (!silent) /* echo it */
1449     printf("\t%s\n", cs);
1450     if (noaction)
1451     return(0);
1452     fflush(stdout); /* flush output and pass to shell */
1453     return(system(cs));
1454     }
1455    
1456    
1457     rmfile(fn) /* remove a file */
1458     char *fn;
1459     {
1460     if (!silent)
1461 greg 2.1 #ifdef MSDOS
1462 greg 2.4 printf("\tdel %s\n", fn);
1463 greg 2.1 #else
1464 greg 2.4 printf("\trm -f %s\n", fn);
1465 greg 2.1 #endif
1466 greg 2.4 if (noaction)
1467     return(0);
1468     return(unlink(fn));
1469 greg 2.3 }
1470 greg 2.8
1471    
1472     #ifdef MSDOS
1473     setenv(vname, value) /* set an environment variable */
1474     char *vname, *value;
1475     {
1476     register char *evp;
1477    
1478     evp = bmalloc(strlen(vname)+strlen(value)+2);
1479     if (evp == NULL)
1480     syserr(progname);
1481     sprintf(evp, "%s=%s", vname, value);
1482     if (putenv(evp) != 0) {
1483     fprintf(stderr, "%s: out of environment space\n", progname);
1484     exit(1);
1485     }
1486     if (!silent)
1487     printf("set %s\n", evp);
1488     }
1489     #endif
1490 greg 2.3
1491    
1492     badvalue(vc) /* report bad variable value and exit */
1493     int vc;
1494     {
1495     fprintf(stderr, "%s: bad value for variable '%s'\n",
1496     progname, vnam(vc));
1497     exit(1);
1498     }
1499    
1500    
1501     syserr(s) /* report a system error and exit */
1502     char *s;
1503     {
1504     perror(s);
1505     exit(1);
1506 greg 2.1 }