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

# Content
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 }