ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rad.c
Revision: 2.18
Committed: Fri Aug 13 09:19:30 1993 UTC (30 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.17: +4 -3 lines
Log Message:
bug fix in standard view specification with rpict

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