ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtmain.c
Revision: 2.1
Committed: Sat Feb 22 02:07:29 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * rtmain.c - main for rtrace per-ray calculation program
6     */
7    
8     /* ====================================================================
9     * The Radiance Software License, Version 1.0
10     *
11     * Copyright (c) 1990 - 2002 The Regents of the University of California,
12     * through Lawrence Berkeley National Laboratory. All rights reserved.
13     *
14     * Redistribution and use in source and binary forms, with or without
15     * modification, are permitted provided that the following conditions
16     * are met:
17     *
18     * 1. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 2. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in
23     * the documentation and/or other materials provided with the
24     * distribution.
25     *
26     * 3. The end-user documentation included with the redistribution,
27     * if any, must include the following acknowledgment:
28     * "This product includes Radiance software
29     * (http://radsite.lbl.gov/)
30     * developed by the Lawrence Berkeley National Laboratory
31     * (http://www.lbl.gov/)."
32     * Alternately, this acknowledgment may appear in the software itself,
33     * if and wherever such third-party acknowledgments normally appear.
34     *
35     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36     * and "The Regents of the University of California" must
37     * not be used to endorse or promote products derived from this
38     * software without prior written permission. For written
39     * permission, please contact [email protected].
40     *
41     * 5. Products derived from this software may not be called "Radiance",
42     * nor may "Radiance" appear in their name, without prior written
43     * permission of Lawrence Berkeley National Laboratory.
44     *
45     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56     * SUCH DAMAGE.
57     * ====================================================================
58     *
59     * This software consists of voluntary contributions made by many
60     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61     * information on Lawrence Berkeley National Laboratory, please see
62     * <http://www.lbl.gov/>.
63     */
64    
65     #include "ray.h"
66    
67     #include "source.h"
68    
69     #include "ambient.h"
70    
71     #include "random.h"
72    
73     #include "paths.h"
74    
75     #include <sys/types.h>
76    
77     #include <signal.h>
78     /* persistent processes define */
79     #ifdef F_SETLKW
80     #define PERSIST 1 /* normal persist */
81     #define PARALLEL 2 /* parallel persist */
82     #define PCHILD 3 /* child of normal persist */
83     #endif
84    
85     char *progname; /* argv[0] */
86    
87     char *octname; /* octree name */
88    
89     char *sigerr[NSIG]; /* signal error messages */
90    
91     char *shm_boundary = NULL; /* boundary of shared memory */
92    
93     char *errfile = NULL; /* error output file */
94    
95     extern char *formstr(); /* string from format */
96     extern int inform; /* input format */
97     extern int outform; /* output format */
98     extern char *outvals; /* output values */
99    
100     extern int hresolu; /* horizontal resolution */
101     extern int vresolu; /* vertical resolution */
102    
103     extern int imm_irrad; /* compute immediate irradiance? */
104     extern int lim_dist; /* limit distance? */
105    
106     extern char *tralist[]; /* list of modifers to trace (or no) */
107     extern int traincl; /* include == 1, exclude == 0 */
108    
109     void onsig();
110     void sigdie();
111     void printdefaults();
112    
113    
114     int
115     main(argc, argv)
116     int argc;
117     char *argv[];
118     {
119     #define check(ol,al) if (argv[i][ol] || \
120     badarg(argc-i-1,argv+i+1,al)) \
121     goto badopt
122     #define bool(olen,var) switch (argv[i][olen]) { \
123     case '\0': var = !var; break; \
124     case 'y': case 'Y': case 't': case 'T': \
125     case '+': case '1': var = 1; break; \
126     case 'n': case 'N': case 'f': case 'F': \
127     case '-': case '0': var = 0; break; \
128     default: goto badopt; }
129     int loadflags = ~IO_FILES;
130     int persist = 0;
131     char **tralp;
132     int duped1;
133     int rval;
134     int i;
135     /* global program name */
136     progname = argv[0] = fixargv0(argv[0]);
137     /* option city */
138     for (i = 1; i < argc; i++) {
139     /* expand arguments */
140     while ((rval = expandarg(&argc, &argv, i)) > 0)
141     ;
142     if (rval < 0) {
143     sprintf(errmsg, "cannot expand '%s'", argv[i]);
144     error(SYSTEM, errmsg);
145     }
146     if (argv[i] == NULL || argv[i][0] != '-')
147     break; /* break from options */
148     if (!strcmp(argv[i], "-version")) {
149     puts(VersionID);
150     quit(0);
151     }
152     if (!strcmp(argv[i], "-defaults") ||
153     !strcmp(argv[i], "-help")) {
154     printdefaults();
155     quit(0);
156     }
157     rval = getrenderopt(argc-i, argv+i);
158     if (rval >= 0) {
159     i += rval;
160     continue;
161     }
162     switch (argv[i][1]) {
163     case 'x': /* x resolution */
164     check(2,"i");
165     hresolu = atoi(argv[++i]);
166     break;
167     case 'y': /* y resolution */
168     check(2,"i");
169     vresolu = atoi(argv[++i]);
170     break;
171     case 'w': /* warnings */
172     rval = erract[WARNING].pf != NULL;
173     bool(2,rval);
174     if (rval) erract[WARNING].pf = wputs;
175     else erract[WARNING].pf = NULL;
176     break;
177     case 'e': /* error file */
178     check(2,"s");
179     errfile = argv[++i];
180     break;
181     case 'l': /* limit distance */
182     if (argv[i][2] != 'd')
183     goto badopt;
184     bool(3,lim_dist);
185     break;
186     case 'I': /* immed. irradiance */
187     bool(2,imm_irrad);
188     break;
189     case 'f': /* format i/o */
190     switch (argv[i][2]) {
191     case 'a': /* ascii */
192     case 'f': /* float */
193     case 'd': /* double */
194     inform = argv[i][2];
195     break;
196     default:
197     goto badopt;
198     }
199     switch (argv[i][3]) {
200     case '\0':
201     outform = inform;
202     break;
203     case 'a': /* ascii */
204     case 'f': /* float */
205     case 'd': /* double */
206     case 'c': /* color */
207     check(4,"");
208     outform = argv[i][3];
209     break;
210     default:
211     goto badopt;
212     }
213     break;
214     case 'o': /* output */
215     outvals = argv[i]+2;
216     break;
217     case 'h': /* header output */
218     rval = loadflags & IO_INFO;
219     bool(2,rval);
220     loadflags = rval ? loadflags | IO_INFO :
221     loadflags & ~IO_INFO;
222     break;
223     case 't': /* trace */
224     switch (argv[i][2]) {
225     case 'i': /* include */
226     case 'I':
227     check(3,"s");
228     if (traincl != 1) {
229     traincl = 1;
230     tralp = tralist;
231     }
232     if (argv[i][2] == 'I') { /* file */
233     rval = wordfile(tralp,
234     getpath(argv[++i],getlibpath(),R_OK));
235     if (rval < 0) {
236     sprintf(errmsg,
237     "cannot open trace include file \"%s\"",
238     argv[i]);
239     error(SYSTEM, errmsg);
240     }
241     tralp += rval;
242     } else {
243     *tralp++ = argv[++i];
244     *tralp = NULL;
245     }
246     break;
247     case 'e': /* exclude */
248     case 'E':
249     check(3,"s");
250     if (traincl != 0) {
251     traincl = 0;
252     tralp = tralist;
253     }
254     if (argv[i][2] == 'E') { /* file */
255     rval = wordfile(tralp,
256     getpath(argv[++i],getlibpath(),R_OK));
257     if (rval < 0) {
258     sprintf(errmsg,
259     "cannot open trace exclude file \"%s\"",
260     argv[i]);
261     error(SYSTEM, errmsg);
262     }
263     tralp += rval;
264     } else {
265     *tralp++ = argv[++i];
266     *tralp = NULL;
267     }
268     break;
269     default:
270     goto badopt;
271     }
272     break;
273     #ifdef PERSIST
274     case 'P': /* persist file */
275     if (argv[i][2] == 'P') {
276     check(3,"s");
277     persist = PARALLEL;
278     } else {
279     check(2,"s");
280     persist = PERSIST;
281     }
282     persistfile(argv[++i]);
283     break;
284     #endif
285     default:
286     goto badopt;
287     }
288     }
289     /* initialize object types */
290     initotypes();
291     /* initialize urand */
292     initurand(2048);
293     /* set up signal handling */
294     sigdie(SIGINT, "Interrupt");
295     sigdie(SIGHUP, "Hangup");
296     sigdie(SIGTERM, "Terminate");
297     sigdie(SIGPIPE, "Broken pipe");
298     sigdie(SIGALRM, "Alarm clock");
299     #ifdef SIGXCPU
300     sigdie(SIGXCPU, "CPU limit exceeded");
301     sigdie(SIGXFSZ, "File size exceeded");
302     #endif
303     /* open error file */
304     if (errfile != NULL) {
305     if (freopen(errfile, "a", stderr) == NULL)
306     quit(2);
307     fprintf(stderr, "**************\n*** PID %5d: ",
308     getpid());
309     printargs(argc, argv, stderr);
310     putc('\n', stderr);
311     fflush(stderr);
312     }
313     #ifdef NICE
314     nice(NICE); /* lower priority */
315     #endif
316     /* get octree */
317     if (i == argc)
318     octname = NULL;
319     else if (i == argc-1)
320     octname = argv[i];
321     else
322     goto badopt;
323     if (octname == NULL)
324     error(USER, "missing octree argument");
325     /* set up output */
326     #ifdef PERSIST
327     if (persist) {
328     duped1 = dup(fileno(stdout)); /* don't lose our output */
329     openheader();
330     }
331     #endif
332     #ifdef MSDOS
333     if (outform != 'a')
334     setmode(fileno(stdout), O_BINARY);
335     if (octname == NULL)
336     setmode(fileno(stdin), O_BINARY);
337     #endif
338     readoct(octname, loadflags, &thescene, NULL);
339     nsceneobjs = nobjects;
340    
341     if (loadflags & IO_INFO) { /* print header */
342     printargs(i, argv, stdout);
343     printf("SOFTWARE= %s\n", VersionID);
344     fputnow(stdout);
345     fputformat(formstr(outform), stdout);
346     putchar('\n');
347     }
348    
349     marksources(); /* find and mark sources */
350    
351     setambient(); /* initialize ambient calculation */
352    
353     #ifdef PERSIST
354     if (persist) {
355     fflush(stdout);
356     /* reconnect stdout */
357     dup2(duped1, fileno(stdout));
358     close(duped1);
359     if (persist == PARALLEL) { /* multiprocessing */
360     preload_objs(); /* preload scene */
361     shm_boundary = (char *)malloc(16);
362     strcpy(shm_boundary, "SHM_BOUNDARY");
363     while ((rval=fork()) == 0) { /* keep on forkin' */
364     pflock(1);
365     pfhold();
366     }
367     if (rval < 0)
368     error(SYSTEM, "cannot fork child for persist function");
369     pfdetach(); /* parent exits */
370     }
371     }
372     runagain:
373     if (persist)
374     dupheader(); /* send header to stdout */
375     #endif
376     /* trace rays */
377     rtrace(NULL);
378     /* flush ambient file */
379     ambsync();
380     #ifdef PERSIST
381     if (persist == PERSIST) { /* first run-through */
382     if ((rval=fork()) == 0) { /* child loops until killed */
383     pflock(1);
384     persist = PCHILD;
385     } else { /* original process exits */
386     if (rval < 0)
387     error(SYSTEM, "cannot fork child for persist function");
388     pfdetach(); /* parent exits */
389     }
390     }
391     if (persist == PCHILD) { /* wait for a signal then go again */
392     close(duped1); /* release output handle */
393     pfhold();
394     raynum = nrays = 0; /* reinitialize */
395     goto runagain;
396     }
397     #endif
398     quit(0);
399    
400     badopt:
401     sprintf(errmsg, "command line error at '%s'", argv[i]);
402     error(USER, errmsg);
403    
404     #undef check
405     #undef bool
406     }
407    
408    
409     void
410     wputs(s) /* warning output function */
411     char *s;
412     {
413     int lasterrno = errno;
414     eputs(s);
415     errno = lasterrno;
416     }
417    
418    
419     void
420     eputs(s) /* put string to stderr */
421     register char *s;
422     {
423     static int midline = 0;
424    
425     if (!*s)
426     return;
427     if (!midline++) {
428     fputs(progname, stderr);
429     fputs(": ", stderr);
430     }
431     fputs(s, stderr);
432     if (s[strlen(s)-1] == '\n') {
433     fflush(stderr);
434     midline = 0;
435     }
436     }
437    
438    
439     void
440     onsig(signo) /* fatal signal */
441     int signo;
442     {
443     static int gotsig = 0;
444    
445     if (gotsig++) /* two signals and we're gone! */
446     _exit(signo);
447    
448     alarm(15); /* allow 15 seconds to clean up */
449     signal(SIGALRM, SIG_DFL); /* make certain we do die */
450     eputs("signal - ");
451     eputs(sigerr[signo]);
452     eputs("\n");
453     quit(3);
454     }
455    
456    
457     void
458     sigdie(signo, msg) /* set fatal signal */
459     int signo;
460     char *msg;
461     {
462     if (signal(signo, onsig) == SIG_IGN)
463     signal(signo, SIG_IGN);
464     sigerr[signo] = msg;
465     }
466    
467    
468     void
469     printdefaults() /* print default values to stdout */
470     {
471     register char *cp;
472    
473     if (imm_irrad)
474     printf("-I+\t\t\t\t# immediate irradiance on\n");
475     printf("-x %-9d\t\t\t# x resolution\n", hresolu);
476     printf("-y %-9d\t\t\t# y resolution\n", vresolu);
477     printf(lim_dist ? "-ld+\t\t\t\t# limit distance on\n" :
478     "-ld-\t\t\t\t# limit distance off\n");
479     printf("-f%c%c\t\t\t\t# format input/output = %s/%s\n",
480     inform, outform, formstr(inform), formstr(outform));
481     printf("-o%s\t\t\t\t# output", outvals);
482     for (cp = outvals; *cp; cp++)
483     switch (*cp) {
484     case 't': printf(" trace"); break;
485     case 'o': printf(" origin"); break;
486     case 'd': printf(" direction"); break;
487     case 'v': printf(" value"); break;
488     case 'l': printf(" length"); break;
489     case 'L': printf(" first_length"); break;
490     case 'p': printf(" point"); break;
491     case 'n': printf(" normal"); break;
492     case 'N': printf(" unperturbed_normal"); break;
493     case 's': printf(" surface"); break;
494     case 'w': printf(" weight"); break;
495     case 'm': printf(" modifier"); break;
496     }
497     putchar('\n');
498     printf(erract[WARNING].pf != NULL ?
499     "-w+\t\t\t\t# warning messages on\n" :
500     "-w-\t\t\t\t# warning messages off\n");
501     print_rdefaults();
502     }