ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rad.c
Revision: 2.3
Committed: Thu Mar 11 17:23:33 1993 UTC (31 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +116 -109 lines
Log Message:
various bug fixes and improvements

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