ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rad.c
Revision: 2.28
Committed: Thu Oct 28 11:48:29 1993 UTC (30 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.27: +1 -1 lines
Log Message:
increased direct jitter for medium quality penumbras

File Contents

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