ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rmain.c
Revision: 2.44
Committed: Tue Nov 11 19:55:05 1997 UTC (27 years, 6 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.43: +10 -33 lines
Log Message:
created erract structure containing error messages and actions

File Contents

# User Rev Content
1 greg 2.41 /* Copyright (c) 1996 Regents of the University of California */
2 greg 1.1
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * rmain.c - main for ray tracing programs
9     *
10     * 3/24/87
11     */
12    
13     /* for flaky pre-processors */
14 greg 2.10 #ifndef RPICT
15     #define RPICT 0
16 greg 1.1 #endif
17 greg 2.10 #ifndef RTRACE
18     #define RTRACE 0
19 greg 1.1 #endif
20 greg 2.10 #ifndef RVIEW
21     #define RVIEW 0
22 greg 1.1 #endif
23    
24     #include "ray.h"
25    
26 greg 1.50 #include "resolu.h"
27    
28 greg 1.1 #include "octree.h"
29    
30 greg 2.32 #include <sys/types.h>
31    
32 greg 1.1 #include <signal.h>
33    
34     #include "view.h"
35    
36 greg 2.10 #include "paths.h"
37 greg 2.23 /* persistent processes define */
38     #ifdef F_SETLKW
39     #if RPICT|RTRACE
40 greg 2.27 #define PERSIST 1 /* normal persist */
41     #define PARALLEL 2 /* parallel persist */
42     #define PCHILD 3 /* child of normal persist */
43 greg 2.23 #endif
44     #endif
45 greg 1.1
46     char *progname; /* argv[0] */
47    
48 greg 1.19 char *octname; /* octree name */
49    
50 greg 2.33 char *getlibpath(); /* library directory list */
51 greg 1.1
52     char *sigerr[NSIG]; /* signal error messages */
53    
54 greg 2.36 char *shm_boundary = NULL; /* boundary of shared memory */
55    
56 greg 1.46 extern char VersionID[]; /* version ID string */
57    
58 greg 1.1 int (*trace)() = NULL; /* trace call */
59 greg 1.36 int do_irrad = 0; /* compute irradiance? */
60 greg 1.1
61 greg 2.41 char *errfile = NULL; /* error output file */
62    
63 greg 2.32 extern time_t time();
64     time_t tstart; /* start time */
65 greg 1.34
66 greg 1.24 extern int ambnotify(); /* new object notify functions */
67 greg 2.25 #if RTRACE
68     extern int tranotify();
69     int (*addobjnotify[])() = {ambnotify, tranotify, NULL};
70     extern char *tralist[]; /* trace include/exclude list */
71     extern int traincl; /* include == 1, exclude == 0 */
72     #else
73 greg 1.24 int (*addobjnotify[])() = {ambnotify, NULL};
74 greg 2.25 #endif
75 greg 1.24
76 greg 1.1 CUBE thescene; /* our scene */
77 greg 2.10 OBJECT nsceneobjs; /* number of objects in our scene */
78 greg 1.1
79 greg 2.24 extern unsigned long raynum, nrays; /* ray counts */
80 greg 2.22
81 greg 1.36 extern int imm_irrad; /* calculate immediate irradiance? */
82 gregl 2.42 extern int lim_dist; /* limit distance? */
83 greg 1.36
84 greg 1.1 extern int ralrm; /* seconds between reports */
85    
86     extern int greyscale; /* map colors to brightness? */
87     extern char *devname; /* output device name */
88 greg 2.30 extern double exposure; /* exposure compensation */
89 greg 1.1
90 greg 2.8 extern char *formstr(); /* string from format */
91 greg 1.1 extern int inform; /* input format */
92     extern int outform; /* output format */
93     extern char *outvals; /* output values */
94    
95     extern VIEW ourview; /* viewing parameters */
96    
97 greg 2.28 extern char rifname[]; /* rad input file name */
98    
99 greg 1.1 extern int hresolu; /* horizontal resolution */
100     extern int vresolu; /* vertical resolution */
101 greg 1.22 extern double pixaspect; /* pixel aspect ratio */
102 greg 1.1
103     extern int psample; /* pixel sample size */
104     extern double maxdiff; /* max. sample difference */
105 greg 1.11 extern double dstrpix; /* square pixel distribution */
106 greg 1.1
107     extern double dstrsrc; /* square source distribution */
108 greg 1.11 extern double shadthresh; /* shadow threshold */
109 greg 1.15 extern double shadcert; /* shadow testing certainty */
110 greg 1.39 extern int directrelay; /* number of source relays */
111 greg 1.40 extern int vspretest; /* virtual source pretest density */
112 greg 2.17 extern int directvis; /* light sources visible to eye? */
113 greg 1.47 extern double srcsizerat; /* maximum source size/dist. ratio */
114 greg 1.1
115 greg 2.4 extern double specthresh; /* specular sampling threshold */
116     extern double specjitter; /* specular sampling jitter */
117    
118 greg 2.38 extern COLOR cextinction; /* global extinction coefficient */
119 greg 2.40 extern COLOR salbedo; /* global scattering albedo */
120 greg 2.38 extern double seccg; /* global scattering eccentricity */
121     extern double ssampdist; /* scatter sampling distance */
122    
123 greg 2.35 extern int backvis; /* back face visibility */
124    
125 greg 1.1 extern int maxdepth; /* maximum recursion depth */
126     extern double minweight; /* minimum ray weight */
127    
128     extern COLOR ambval; /* ambient value */
129 greg 2.39 extern int ambvwt; /* initial weight for ambient value */
130 greg 1.1 extern double ambacc; /* ambient accuracy */
131     extern int ambres; /* ambient resolution */
132     extern int ambdiv; /* ambient divisions */
133     extern int ambssamp; /* ambient super-samples */
134     extern int ambounce; /* ambient bounces */
135     extern char *amblist[]; /* ambient include/exclude list */
136     extern int ambincl; /* include == 1, exclude == 0 */
137    
138    
139     main(argc, argv)
140     int argc;
141     char *argv[];
142     {
143 greg 2.10 #define check(ol,al) if (argv[i][ol] || \
144 greg 1.49 badarg(argc-i-1,argv+i+1,al)) \
145     goto badopt
146 greg 2.10 #define bool(olen,var) switch (argv[i][olen]) { \
147 greg 1.43 case '\0': var = !var; break; \
148     case 'y': case 'Y': case 't': case 'T': \
149     case '+': case '1': var = 1; break; \
150     case 'n': case 'N': case 'f': case 'F': \
151     case '-': case '0': var = 0; break; \
152     default: goto badopt; }
153 greg 1.1 char *err;
154     char *recover = NULL;
155 greg 2.7 char *outfile = NULL;
156 greg 1.20 char *zfile = NULL;
157 greg 1.1 char *ambfile = NULL;
158     int loadflags = ~IO_FILES;
159 greg 2.7 int seqstart = 0;
160 greg 2.29 int persist = 0;
161 greg 2.25 char **amblp;
162     char **tralp;
163 greg 2.18 int duped1;
164 greg 2.7 int rval;
165 greg 1.1 int i;
166 greg 1.34 /* record start time */
167 greg 2.32 tstart = time((time_t *)NULL);
168 greg 1.1 /* global program name */
169 greg 2.11 progname = argv[0] = fixargv0(argv[0]);
170 greg 1.31 /* initialize object types */
171     initotypes();
172 greg 1.37 /* initialize urand */
173 greg 1.41 initurand(2048);
174 greg 1.10 /* option city */
175 greg 2.12 for (i = 1; i < argc; i++) {
176 greg 2.13 /* expand arguments */
177     while (rval = expandarg(&argc, &argv, i))
178     if (rval < 0) {
179     sprintf(errmsg, "cannot expand '%s'", argv[i]);
180     error(SYSTEM, errmsg);
181     }
182 greg 2.15 if (argv[i] == NULL || argv[i][0] != '-')
183 greg 2.12 break; /* break from options */
184 greg 1.46 if (!strcmp(argv[i], "-version")) {
185     puts(VersionID);
186     quit(0);
187     }
188 greg 1.18 if (!strcmp(argv[i], "-defaults") ||
189     !strcmp(argv[i], "-help")) {
190 greg 1.1 printdefaults();
191     quit(0);
192     }
193     #if RVIEW
194     if (!strcmp(argv[i], "-devices")) {
195     printdevices();
196     quit(0);
197     }
198     #endif
199 greg 1.21 #if RPICT|RVIEW
200     rval = getviewopt(&ourview, argc-i, argv+i);
201     if (rval >= 0) {
202     i += rval;
203     continue;
204     }
205     #endif
206 greg 1.1 switch (argv[i][1]) {
207     #if RPICT|RVIEW
208 greg 1.21 case 'v': /* view file */
209     if (argv[i][2] != 'f')
210 greg 1.10 goto badopt;
211 greg 1.49 check(3,"s");
212 greg 1.50 rval = viewfile(argv[++i], &ourview, NULL);
213 greg 1.21 if (rval < 0) {
214     sprintf(errmsg,
215     "cannot open view file \"%s\"",
216     argv[i]);
217     error(SYSTEM, errmsg);
218     } else if (rval == 0) {
219     sprintf(errmsg,
220     "bad view file \"%s\"",
221     argv[i]);
222     error(USER, errmsg);
223 greg 2.7 }
224 greg 1.1 break;
225     #endif
226 greg 2.35 case 'b': /* back face vis. */
227     if (argv[i][2] == 'v') {
228     bool(3,backvis);
229     break;
230     }
231     #if RVIEW
232     bool(2,greyscale);
233     break;
234     #else
235     goto badopt;
236     #endif
237 greg 1.11 case 'd': /* direct */
238 greg 1.1 switch (argv[i][2]) {
239 greg 1.13 case 't': /* threshold */
240 greg 1.49 check(3,"f");
241 greg 1.11 shadthresh = atof(argv[++i]);
242 greg 1.1 break;
243 greg 1.15 case 'c': /* certainty */
244 greg 1.49 check(3,"f");
245 greg 1.15 shadcert = atof(argv[++i]);
246     break;
247 greg 1.11 case 'j': /* jitter */
248 greg 1.49 check(3,"f");
249 greg 1.1 dstrsrc = atof(argv[++i]);
250     break;
251 greg 1.47 case 'r': /* relays */
252 greg 1.49 check(3,"i");
253 greg 1.39 directrelay = atoi(argv[++i]);
254     break;
255 greg 1.47 case 'p': /* pretest */
256 greg 1.49 check(3,"i");
257 greg 1.40 vspretest = atoi(argv[++i]);
258 greg 1.42 break;
259 greg 2.17 case 'v': /* visibility */
260     bool(3,directvis);
261 greg 1.40 break;
262 greg 1.47 case 's': /* size */
263 greg 1.49 check(3,"f");
264 greg 1.47 srcsizerat = atof(argv[++i]);
265     break;
266 greg 1.1 default:
267 greg 1.10 goto badopt;
268 greg 1.1 }
269     break;
270 greg 2.4 case 's': /* specular */
271     switch (argv[i][2]) {
272     case 't': /* threshold */
273     check(3,"f");
274     specthresh = atof(argv[++i]);
275     break;
276     case 'j': /* jitter */
277     check(3,"f");
278     specjitter = atof(argv[++i]);
279     break;
280     default:
281     goto badopt;
282     }
283     break;
284 greg 1.1 #if RPICT|RVIEW
285 greg 2.4 case 'p': /* pixel */
286 greg 1.1 switch (argv[i][2]) {
287 greg 2.4 case 's': /* sample */
288 greg 1.49 check(3,"i");
289 greg 1.1 psample = atoi(argv[++i]);
290     break;
291 greg 1.13 case 't': /* threshold */
292 greg 1.49 check(3,"f");
293 greg 1.1 maxdiff = atof(argv[++i]);
294     break;
295 greg 1.11 #if RPICT
296     case 'j': /* jitter */
297 greg 1.49 check(3,"f");
298 greg 1.11 dstrpix = atof(argv[++i]);
299     break;
300 greg 2.4 case 'a': /* aspect */
301     check(3,"f");
302     pixaspect = atof(argv[++i]);
303     break;
304 greg 1.11 #endif
305 greg 2.30 #if RVIEW
306     case 'e': /* exposure */
307     check(3,"f");
308     exposure = atof(argv[++i]);
309     if (argv[i][0] == '+' || argv[i][0] == '-')
310     exposure = pow(2.0, exposure);
311     break;
312     #endif
313 greg 1.1 default:
314 greg 1.10 goto badopt;
315 greg 1.1 }
316     break;
317     #endif
318 greg 1.22 #if RPICT|RTRACE
319 greg 1.1 case 'x': /* x resolution */
320 greg 1.49 check(2,"i");
321 greg 1.1 hresolu = atoi(argv[++i]);
322     break;
323     case 'y': /* y resolution */
324 greg 1.49 check(2,"i");
325 greg 1.1 vresolu = atoi(argv[++i]);
326     break;
327 greg 1.22 #endif
328 greg 1.1 case 'w': /* warnings */
329 gregl 2.44 rval = erract[WARNING].pf != NULL;
330 greg 1.43 bool(2,rval);
331 gregl 2.44 if (rval) erract[WARNING].pf = wputs;
332     else erract[WARNING].pf = NULL;
333 greg 1.1 break;
334     case 'e': /* error file */
335 greg 1.49 check(2,"s");
336 greg 1.1 errfile = argv[++i];
337     break;
338     case 'l': /* limit */
339     switch (argv[i][2]) {
340     case 'r': /* recursion */
341 greg 1.49 check(3,"i");
342 greg 1.1 maxdepth = atoi(argv[++i]);
343     break;
344     case 'w': /* weight */
345 greg 1.49 check(3,"f");
346 greg 1.1 minweight = atof(argv[++i]);
347     break;
348 gregl 2.42 #if RTRACE
349     case 'd': /* distance */
350     bool(3,lim_dist);
351     break;
352     #endif
353 greg 1.1 default:
354 greg 1.10 goto badopt;
355 greg 1.1 }
356     break;
357 greg 1.36 case 'i': /* irradiance */
358 greg 1.43 bool(2,do_irrad);
359 greg 1.36 break;
360 greg 1.1 #if RPICT
361 greg 2.7 case 'S': /* slave index */
362     check(2,"i");
363     seqstart = atoi(argv[++i]);
364     break;
365     case 'o': /* output file */
366     check(2,"s");
367     outfile = argv[++i];
368     break;
369 greg 1.20 case 'z': /* z file */
370 greg 1.49 check(2,"s");
371 greg 1.20 zfile = argv[++i];
372     break;
373 greg 1.1 case 'r': /* recover file */
374 greg 2.16 if (argv[i][2] == 'o') { /* +output */
375     check(3,"s");
376     outfile = argv[i+1];
377     } else
378     check(2,"s");
379 greg 1.1 recover = argv[++i];
380     break;
381     case 't': /* timer */
382 greg 1.49 check(2,"i");
383 greg 1.1 ralrm = atoi(argv[++i]);
384     break;
385     #endif
386     case 'a': /* ambient */
387     switch (argv[i][2]) {
388     case 'v': /* value */
389 greg 1.49 check(3,"fff");
390 greg 1.1 setcolor(ambval, atof(argv[i+1]),
391     atof(argv[i+2]),
392     atof(argv[i+3]));
393     i += 3;
394     break;
395 greg 2.39 case 'w': /* weight */
396     check(3,"i");
397     ambvwt = atoi(argv[++i]);
398     break;
399 greg 1.1 case 'a': /* accuracy */
400 greg 1.49 check(3,"f");
401 greg 1.1 ambacc = atof(argv[++i]);
402     break;
403     case 'r': /* resolution */
404 greg 1.49 check(3,"i");
405 greg 1.1 ambres = atoi(argv[++i]);
406     break;
407     case 'd': /* divisions */
408 greg 1.49 check(3,"i");
409 greg 1.1 ambdiv = atoi(argv[++i]);
410     break;
411     case 's': /* super-samp */
412 greg 1.49 check(3,"i");
413 greg 1.1 ambssamp = atoi(argv[++i]);
414     break;
415     case 'b': /* bounces */
416 greg 1.49 check(3,"i");
417 greg 1.1 ambounce = atoi(argv[++i]);
418     break;
419     case 'i': /* include */
420 greg 2.5 case 'I':
421 greg 1.49 check(3,"s");
422 greg 1.1 if (ambincl != 1) {
423     ambincl = 1;
424     amblp = amblist;
425     }
426 greg 2.5 if (argv[i][2] == 'I') { /* file */
427 greg 2.13 rval = wordfile(amblp,
428 greg 2.33 getpath(argv[++i],getlibpath(),R_OK));
429 greg 2.5 if (rval < 0) {
430     sprintf(errmsg,
431     "cannot open ambient include file \"%s\"",
432     argv[i]);
433     error(SYSTEM, errmsg);
434     }
435     amblp += rval;
436 greg 2.25 } else {
437 greg 2.5 *amblp++ = argv[++i];
438 greg 2.25 *amblp = NULL;
439     }
440 greg 1.1 break;
441     case 'e': /* exclude */
442 greg 2.5 case 'E':
443 greg 1.49 check(3,"s");
444 greg 1.1 if (ambincl != 0) {
445     ambincl = 0;
446     amblp = amblist;
447     }
448 greg 2.5 if (argv[i][2] == 'E') { /* file */
449 greg 2.13 rval = wordfile(amblp,
450 greg 2.33 getpath(argv[++i],getlibpath(),R_OK));
451 greg 2.5 if (rval < 0) {
452     sprintf(errmsg,
453     "cannot open ambient exclude file \"%s\"",
454     argv[i]);
455     error(SYSTEM, errmsg);
456     }
457     amblp += rval;
458 greg 2.25 } else {
459 greg 2.5 *amblp++ = argv[++i];
460 greg 2.25 *amblp = NULL;
461     }
462 greg 1.1 break;
463     case 'f': /* file */
464 greg 1.49 check(3,"s");
465 greg 1.1 ambfile= argv[++i];
466     break;
467     default:
468 greg 1.10 goto badopt;
469 greg 1.1 }
470     break;
471 greg 2.38 case 'm': /* medium */
472     switch (argv[i][2]) {
473     case 'e': /* extinction */
474     check(3,"fff");
475     setcolor(cextinction, atof(argv[i+1]),
476     atof(argv[i+2]),
477     atof(argv[i+3]));
478     i += 3;
479     break;
480     case 'a': /* albedo */
481 greg 2.40 check(3,"fff");
482     setcolor(salbedo, atof(argv[i+1]),
483     atof(argv[i+2]),
484     atof(argv[i+3]));
485     i += 3;
486 greg 2.38 break;
487     case 'g': /* eccentr. */
488     check(3,"f");
489     seccg = atof(argv[++i]);
490     break;
491     case 's': /* sampling */
492     check(3,"f");
493     ssampdist = atof(argv[++i]);
494     break;
495     default:
496     goto badopt;
497     }
498     break;
499 greg 1.1 #if RTRACE
500 greg 1.36 case 'I': /* immed. irradiance */
501 greg 1.43 bool(2,imm_irrad);
502 greg 1.36 break;
503 greg 1.1 case 'f': /* format i/o */
504     switch (argv[i][2]) {
505     case 'a': /* ascii */
506     case 'f': /* float */
507     case 'd': /* double */
508     inform = argv[i][2];
509     break;
510     default:
511 greg 1.10 goto badopt;
512 greg 1.1 }
513     switch (argv[i][3]) {
514     case '\0':
515     outform = inform;
516     break;
517     case 'a': /* ascii */
518     case 'f': /* float */
519     case 'd': /* double */
520 greg 2.7 case 'c': /* color */
521 greg 1.49 check(4,"");
522 greg 1.1 outform = argv[i][3];
523     break;
524     default:
525 greg 1.10 goto badopt;
526 greg 1.1 }
527     break;
528     case 'o': /* output */
529     outvals = argv[i]+2;
530     break;
531 greg 1.44 case 'h': /* header output */
532     rval = loadflags & IO_INFO;
533     bool(2,rval);
534     loadflags = rval ? loadflags | IO_INFO :
535     loadflags & ~IO_INFO;
536 greg 1.1 break;
537 greg 2.25 case 't': /* trace */
538     switch (argv[i][2]) {
539     case 'i': /* include */
540     case 'I':
541     check(3,"s");
542     if (traincl != 1) {
543     traincl = 1;
544     tralp = tralist;
545     }
546     if (argv[i][2] == 'I') { /* file */
547     rval = wordfile(tralp,
548 greg 2.33 getpath(argv[++i],getlibpath(),R_OK));
549 greg 2.25 if (rval < 0) {
550     sprintf(errmsg,
551     "cannot open trace include file \"%s\"",
552     argv[i]);
553     error(SYSTEM, errmsg);
554     }
555     tralp += rval;
556     } else {
557     *tralp++ = argv[++i];
558     *tralp = NULL;
559     }
560     break;
561     case 'e': /* exclude */
562     case 'E':
563     check(3,"s");
564     if (traincl != 0) {
565     traincl = 0;
566     tralp = tralist;
567     }
568     if (argv[i][2] == 'E') { /* file */
569     rval = wordfile(tralp,
570 greg 2.33 getpath(argv[++i],getlibpath(),R_OK));
571 greg 2.25 if (rval < 0) {
572     sprintf(errmsg,
573     "cannot open trace exclude file \"%s\"",
574     argv[i]);
575     error(SYSTEM, errmsg);
576     }
577     tralp += rval;
578     } else {
579     *tralp++ = argv[++i];
580     *tralp = NULL;
581     }
582     break;
583     default:
584     goto badopt;
585     }
586     break;
587 greg 1.1 #endif
588     #if RVIEW
589     case 'o': /* output device */
590 greg 1.49 check(2,"s");
591 greg 1.1 devname = argv[++i];
592 greg 2.28 break;
593     case 'R': /* render input file */
594     check(2,"s");
595     strcpy(rifname, argv[++i]);
596 greg 1.1 break;
597     #endif
598 greg 2.18 #ifdef PERSIST
599     case 'P': /* persist file */
600     if (argv[i][2] == 'P') {
601     check(3,"s");
602 greg 2.27 persist = PARALLEL;
603 greg 2.18 } else {
604     check(2,"s");
605 greg 2.27 persist = PERSIST;
606 greg 2.18 }
607     persistfile(argv[++i]);
608     break;
609     #endif
610 greg 1.1 default:
611 greg 1.19 goto badopt;
612 greg 1.1 }
613     }
614     #if RPICT|RVIEW
615     err = setview(&ourview); /* set viewing parameters */
616     if (err != NULL)
617     error(USER, err);
618     #endif
619     /* set up signal handling */
620     sigdie(SIGINT, "Interrupt");
621     sigdie(SIGHUP, "Hangup");
622     sigdie(SIGTERM, "Terminate");
623     sigdie(SIGPIPE, "Broken pipe");
624 greg 1.45 sigdie(SIGALRM, "Alarm clock");
625 greg 2.10 #ifdef SIGXCPU
626 greg 1.1 sigdie(SIGXCPU, "CPU limit exceeded");
627     sigdie(SIGXFSZ, "File size exceeded");
628     #endif
629     /* open error file */
630     if (errfile != NULL) {
631     if (freopen(errfile, "a", stderr) == NULL)
632 greg 1.14 quit(2);
633 greg 1.1 fprintf(stderr, "**************\n*** PID %5d: ",
634     getpid());
635     printargs(argc, argv, stderr);
636 greg 2.12 putc('\n', stderr);
637 greg 1.1 fflush(stderr);
638     }
639 greg 2.10 #ifdef NICE
640 greg 1.1 nice(NICE); /* lower priority */
641     #endif
642 greg 1.19 /* get octree */
643 greg 1.1 #if RVIEW
644     loadflags &= ~IO_INFO;
645     #endif
646     if (i == argc)
647 greg 1.19 octname = NULL;
648     else if (i == argc-1)
649     octname = argv[i];
650 greg 1.1 else
651 greg 1.19 goto badopt;
652 greg 2.7 if (
653     #if RPICT
654     seqstart > 0 &&
655     #endif
656     octname == NULL)
657 greg 1.19 error(USER, "missing octree argument");
658 greg 2.26 /* set up output */
659 greg 2.18 #ifdef PERSIST
660     if (persist) {
661 greg 2.7 #if RPICT
662 greg 2.26 if (recover != NULL)
663     error(USER, "persist option used with recover file");
664 greg 2.18 if (seqstart <= 0)
665     error(USER, "persist option only for sequences");
666 greg 2.26 if (outfile == NULL)
667 greg 2.18 #endif
668     duped1 = dup(fileno(stdout)); /* don't lose our output */
669     openheader();
670     }
671     #if RPICT
672 greg 2.27 else
673     #endif
674     #endif
675     #if RPICT
676 greg 2.7 if (outfile != NULL)
677     openheader();
678 greg 1.1 #endif
679 greg 2.10 #ifdef MSDOS
680     #if RTRACE
681     if (outform != 'a')
682     #endif
683     setmode(fileno(stdout), O_BINARY);
684     if (octname == NULL)
685     setmode(fileno(stdin), O_BINARY);
686     #endif
687 greg 1.19 readoct(octname, loadflags, &thescene, NULL);
688 greg 2.9 nsceneobjs = nobjects;
689 greg 1.1
690     if (loadflags & IO_INFO) { /* print header */
691     printargs(i, argv, stdout);
692 greg 1.46 printf("SOFTWARE= %s\n", VersionID);
693 greg 2.8 #if RTRACE
694     fputformat(formstr(outform), stdout);
695     putchar('\n');
696     #endif
697 greg 1.1 }
698    
699     marksources(); /* find and mark sources */
700    
701 greg 1.24 setambient(ambfile); /* initialize ambient calculation */
702 greg 1.1
703 greg 2.18 #ifdef PERSIST
704     if (persist) {
705 greg 2.26 fflush(stdout);
706     if (outfile == NULL) { /* reconnect stdout */
707     dup2(duped1, fileno(stdout));
708     close(duped1);
709     }
710 greg 2.27 if (persist == PARALLEL) { /* multiprocessing */
711 greg 2.18 preload_objs(); /* preload scene */
712 greg 2.36 strcpy(shm_boundary=bmalloc(16), "SHM_BOUNDARY");
713 greg 2.18 while ((rval=fork()) == 0) { /* keep on forkin' */
714     pflock(1);
715     pfhold();
716 greg 2.32 tstart = time((time_t *)NULL);
717 greg 2.18 }
718     if (rval < 0)
719     error(SYSTEM, "cannot fork child for persist function");
720 greg 2.27 pfdetach(); /* parent exits */
721 greg 2.18 }
722     }
723     runagain:
724 greg 2.27 if (persist)
725     if (outfile == NULL) /* if out to stdout */
726     dupheader(); /* send header */
727     else /* if out to file */
728     duped1 = dup(fileno(stdout)); /* hang onto pipe */
729 greg 2.18 #endif
730 greg 1.1 #if RPICT
731 greg 2.7 rpict(seqstart, outfile, zfile, recover);
732 greg 1.1 #endif
733     #if RTRACE
734 greg 2.8 rtrace(NULL);
735 greg 1.1 #endif
736     #if RVIEW
737 greg 2.8 rview();
738 greg 2.18 #endif
739 greg 2.21 ambsync(); /* flush ambient file */
740 greg 2.18 #ifdef PERSIST
741 greg 2.27 if (persist == PERSIST) { /* first run-through */
742 greg 2.20 if ((rval=fork()) == 0) { /* child loops until killed */
743     pflock(1);
744 greg 2.27 persist = PCHILD;
745 greg 2.20 } else { /* original process exits */
746     if (rval < 0)
747     error(SYSTEM, "cannot fork child for persist function");
748 greg 2.27 pfdetach(); /* parent exits */
749 greg 2.20 }
750     }
751 greg 2.27 if (persist == PCHILD) { /* wait for a signal then go again */
752     if (outfile != NULL)
753     close(duped1); /* release output handle */
754 greg 2.20 pfhold();
755 greg 2.32 tstart = time((time_t *)NULL); /* reinitialize */
756 greg 2.22 raynum = nrays = 0;
757 greg 2.18 goto runagain;
758     }
759 greg 1.1 #endif
760     quit(0);
761 greg 1.19
762     badopt:
763     sprintf(errmsg, "command line error at '%s'", argv[i]);
764     error(USER, errmsg);
765    
766 greg 2.10 #undef check
767     #undef bool
768 greg 1.1 }
769    
770    
771 gregl 2.44 wputs(s) /* warning output function */
772     char *s;
773 greg 1.1 {
774 gregl 2.44 int lasterrno = errno;
775     eputs(s);
776 greg 2.3 errno = lasterrno;
777 greg 1.1 }
778    
779    
780 gregl 2.44 eputs(s) /* put string to stderr */
781 greg 1.1 register char *s;
782     {
783 greg 1.26 static int midline = 0;
784 greg 1.1
785 greg 1.27 if (!*s)
786     return;
787 greg 1.26 if (!midline++) {
788 greg 1.1 fputs(progname, stderr);
789     fputs(": ", stderr);
790     }
791     fputs(s, stderr);
792 greg 1.27 if (s[strlen(s)-1] == '\n') {
793 greg 1.1 fflush(stderr);
794 greg 1.26 midline = 0;
795 greg 1.1 }
796     }
797    
798    
799     onsig(signo) /* fatal signal */
800     int signo;
801     {
802 greg 1.8 static int gotsig = 0;
803    
804     if (gotsig++) /* two signals and we're gone! */
805 greg 1.9 _exit(signo);
806 greg 1.8
807 greg 1.48 alarm(15); /* allow 15 seconds to clean up */
808     signal(SIGALRM, SIG_DFL); /* make certain we do die */
809 greg 1.1 eputs("signal - ");
810     eputs(sigerr[signo]);
811     eputs("\n");
812 greg 1.14 quit(3);
813 greg 1.1 }
814    
815    
816     sigdie(signo, msg) /* set fatal signal */
817     int signo;
818     char *msg;
819     {
820     if (signal(signo, onsig) == SIG_IGN)
821     signal(signo, SIG_IGN);
822     sigerr[signo] = msg;
823     }
824    
825    
826     printdefaults() /* print default values to stdout */
827     {
828     register char *cp;
829    
830 greg 1.43 #if RTRACE
831     if (imm_irrad)
832     printf("-I+\t\t\t\t# immediate irradiance on\n");
833     else
834     #endif
835     printf(do_irrad ? "-i+\t\t\t\t# irradiance calculation on\n" :
836     "-i-\t\t\t\t# irradiance calculation off\n");
837 greg 1.49 #if RVIEW
838     printf(greyscale ? "-b+\t\t\t\t# greyscale on\n" :
839     "-b-\t\t\t\t# greyscale off\n");
840     #endif
841 greg 1.1 #if RPICT|RVIEW
842 greg 1.7 printf("-vt%c\t\t\t\t# view type %s\n", ourview.type,
843 greg 1.1 ourview.type==VT_PER ? "perspective" :
844     ourview.type==VT_PAR ? "parallel" :
845 greg 1.28 ourview.type==VT_HEM ? "hemispherical" :
846     ourview.type==VT_ANG ? "angular" :
847 greg 2.37 ourview.type==VT_CYL ? "cylindrical" :
848 greg 1.1 "unknown");
849     printf("-vp %f %f %f\t# view point\n",
850     ourview.vp[0], ourview.vp[1], ourview.vp[2]);
851 greg 2.11 printf("-vd %f %f %f\t# view direction\n",
852 greg 1.1 ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
853 greg 2.11 printf("-vu %f %f %f\t# view up\n",
854 greg 1.1 ourview.vup[0], ourview.vup[1], ourview.vup[2]);
855     printf("-vh %f\t\t\t# view horizontal size\n", ourview.horiz);
856     printf("-vv %f\t\t\t# view vertical size\n", ourview.vert);
857 greg 2.34 printf("-vo %f\t\t\t# view fore clipping plane\n", ourview.vfore);
858     printf("-va %f\t\t\t# view aft clipping plane\n", ourview.vaft);
859 greg 1.22 printf("-vs %f\t\t\t# view shift\n", ourview.hoff);
860     printf("-vl %f\t\t\t# view lift\n", ourview.voff);
861 greg 1.1 #endif
862 greg 1.22 #if RPICT|RTRACE
863 greg 1.1 printf("-x %-9d\t\t\t# x resolution\n", hresolu);
864     printf("-y %-9d\t\t\t# y resolution\n", vresolu);
865 greg 1.22 #endif
866     #if RPICT
867 greg 2.4 printf("-pa %f\t\t\t# pixel aspect ratio\n", pixaspect);
868     printf("-pj %f\t\t\t# pixel jitter\n", dstrpix);
869 greg 2.30 #endif
870     #if RVIEW
871     printf("-pe %f\t\t\t# pixel exposure\n", exposure);
872 greg 1.22 #endif
873 greg 1.1 #if RPICT|RVIEW
874 greg 2.4 printf("-ps %-9d\t\t\t# pixel sample\n", psample);
875     printf("-pt %f\t\t\t# pixel threshold\n", maxdiff);
876 greg 1.22 #endif
877 greg 2.35 printf(backvis ? "-bv+\t\t\t\t# back face visibility on\n" :
878     "-bv-\t\t\t\t# back face visibility off\n");
879 greg 1.29 printf("-dt %f\t\t\t# direct threshold\n", shadthresh);
880     printf("-dc %f\t\t\t# direct certainty\n", shadcert);
881     printf("-dj %f\t\t\t# direct jitter\n", dstrsrc);
882 greg 1.47 printf("-ds %f\t\t\t# direct sampling\n", srcsizerat);
883 greg 1.39 printf("-dr %-9d\t\t\t# direct relays\n", directrelay);
884 greg 1.40 printf("-dp %-9d\t\t\t# direct pretest density\n", vspretest);
885 greg 2.17 printf(directvis ? "-dv+\t\t\t\t# direct visibility on\n" :
886     "-dv-\t\t\t\t# direct visibility off\n");
887 greg 2.4 printf("-sj %f\t\t\t# specular jitter\n", specjitter);
888     printf("-st %f\t\t\t# specular threshold\n", specthresh);
889 greg 1.1 printf("-av %f %f %f\t# ambient value\n", colval(ambval,RED),
890     colval(ambval,GRN), colval(ambval, BLU));
891 greg 2.39 printf("-aw %-9d\t\t\t# ambient value weight\n", ambvwt);
892 greg 1.1 printf("-ab %-9d\t\t\t# ambient bounces\n", ambounce);
893     printf("-aa %f\t\t\t# ambient accuracy\n", ambacc);
894     printf("-ar %-9d\t\t\t# ambient resolution\n", ambres);
895     printf("-ad %-9d\t\t\t# ambient divisions\n", ambdiv);
896     printf("-as %-9d\t\t\t# ambient super-samples\n", ambssamp);
897 gregl 2.43 printf("-me %.2e %.2e %.2e\t# mist extinction coefficient\n",
898 greg 2.38 colval(cextinction,RED),
899     colval(cextinction,GRN),
900     colval(cextinction,BLU));
901 gregl 2.43 printf("-ma %f %f %f\t# mist scattering albedo\n", colval(salbedo,RED),
902 greg 2.40 colval(salbedo,GRN), colval(salbedo,BLU));
903 gregl 2.43 printf("-mg %f\t\t\t# mist scattering eccentricity\n", seccg);
904 greg 2.38 printf("-ms %f\t\t\t# mist sampling distance\n", ssampdist);
905 greg 1.1 printf("-lr %-9d\t\t\t# limit reflection\n", maxdepth);
906     printf("-lw %f\t\t\t# limit weight\n", minweight);
907 gregl 2.42 #if RTRACE
908     printf(lim_dist ? "-ld+\t\t\t\t# limit distance on\n" :
909     "-ld-\t\t\t\t# limit distance off\n");
910     #endif
911 greg 1.1 #if RPICT
912     printf("-t %-9d\t\t\t# time between reports\n", ralrm);
913     #endif
914     #if RVIEW
915     printf("-o %s\t\t\t\t# output device\n", devname);
916     #endif
917     #if RTRACE
918     printf("-f%c%c\t\t\t\t# format input/output = %s/%s\n",
919 greg 2.7 inform, outform, formstr(inform), formstr(outform));
920 greg 1.1 printf("-o%s\t\t\t\t# output", outvals);
921     for (cp = outvals; *cp; cp++)
922     switch (*cp) {
923     case 't': printf(" trace"); break;
924     case 'o': printf(" origin"); break;
925     case 'd': printf(" direction"); break;
926     case 'v': printf(" value"); break;
927     case 'l': printf(" length"); break;
928 greg 2.14 case 'L': printf(" first_length"); break;
929 greg 1.1 case 'p': printf(" point"); break;
930     case 'n': printf(" normal"); break;
931 greg 2.14 case 'N': printf(" unperturbed_normal"); break;
932 greg 1.1 case 's': printf(" surface"); break;
933     case 'w': printf(" weight"); break;
934     case 'm': printf(" modifier"); break;
935     }
936 greg 2.7 putchar('\n');
937 greg 1.1 #endif
938 gregl 2.44 printf(erract[WARNING].pf != NULL ?
939     "-w+\t\t\t\t# warning messages on\n" :
940 greg 1.43 "-w-\t\t\t\t# warning messages off\n");
941 greg 1.1 }