ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rad.c
Revision: 2.21
Committed: Tue Aug 24 22:14:21 1993 UTC (30 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.20: +14 -10 lines
Log Message:
changed -V so it doesn't take view option or cancel other options

File Contents

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