ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rpmain.c
Revision: 2.21
Committed: Wed Oct 19 21:25:20 2022 UTC (19 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.20: +19 -2 lines
Log Message:
feat(rpict,rtrace,rcontrib): Added -features option to check for method support

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rpmain.c,v 2.20 2022/04/05 03:02:15 greg Exp $";
3 #endif
4 /*
5 * rpmain.c - main for rpict batch rendering program
6 */
7
8 #include "copyright.h"
9
10 #include <time.h>
11 #include <signal.h>
12
13 #include "platform.h"
14 #include "rtprocess.h" /* getpid() */
15 #include "ray.h"
16 #include "source.h"
17 #include "ambient.h"
18 #include "random.h"
19 #include "paths.h"
20 #include "view.h"
21 #include "pmapray.h"
22
23 /* persistent processes define */
24 #ifdef F_SETLKW
25 #define PERSIST 1 /* normal persist */
26 #define PARALLEL 2 /* parallel persist */
27 #define PCHILD 3 /* child of normal persist */
28 #endif
29
30 char *progname; /* argv[0] */
31 char *octname; /* octree name */
32 char *sigerr[NSIG]; /* signal error messages */
33 char *shm_boundary = NULL; /* boundary of shared memory */
34 char *errfile = NULL; /* error output file */
35
36 extern time_t time();
37 extern time_t tstart; /* start time */
38
39 extern int ralrm; /* seconds between reports */
40
41 extern VIEW ourview; /* viewing parameters */
42
43 extern int hresolu; /* horizontal resolution */
44 extern int vresolu; /* vertical resolution */
45 extern double pixaspect; /* pixel aspect ratio */
46
47 extern int psample; /* pixel sample size */
48 extern double maxdiff; /* max. sample difference */
49 extern double dstrpix; /* square pixel distribution */
50
51 extern double mblur; /* motion blur parameter */
52
53 extern double dblur; /* depth-of-field blur parameter */
54
55 static void onsig(int signo);
56 static void sigdie(int signo, char *msg);
57 static void printdefaults(void);
58 /* rpict additional features */
59 #ifdef PERSIST
60 #define RPICT_FEATURES "Persist\nParallelPersist\n" \
61 "Recovery\nIrradianceCalc\nViewTypes=v,l,a,h,s,c\n" \
62 "HessianAmbientCache\nAmbientAveraging\nAmbientValueSharing\n" \
63 "PixelJitter\nPixelSampling\nPixelMotion\nPixelDepthOfField\n" \
64 "SmallSourceDrawing\nViewSequence\nProgressReporting\n"
65 #else
66 #define RPICT_FEATURES "Recovery\nIrradianceCalc\nViewTypes=v,l,a,h,s,c\n" \
67 "HessianAmbientCache\nAmbientAveraging\nAmbientValueSharing\n" \
68 "PixelJitter\nPixelSampling\nPixelMotion\nPixelDepthOfField\n" \
69 "SmallSourceDrawing\nViewSequence\nProgressReporting\n"
70 #endif
71
72
73 int
74 main(int argc, char *argv[])
75 {
76 #define check(ol,al) if (argv[i][ol] || \
77 badarg(argc-i-1,argv+i+1,al)) \
78 goto badopt
79 #define check_bool(olen,var) switch (argv[i][olen]) { \
80 case '\0': var = !var; break; \
81 case 'y': case 'Y': case 't': case 'T': \
82 case '+': case '1': var = 1; break; \
83 case 'n': case 'N': case 'f': case 'F': \
84 case '-': case '0': var = 0; break; \
85 default: goto badopt; }
86 char *err;
87 char *recover = NULL;
88 char *outfile = NULL;
89 char *zfile = NULL;
90 int loadflags = ~IO_FILES;
91 int seqstart = 0;
92 int persist = 0;
93 int duped1 = -1;
94 int rval;
95 int i;
96 /* record start time */
97 tstart = time((time_t *)NULL);
98 /* global program name */
99 progname = argv[0] = fixargv0(argv[0]);
100 /* feature check only? */
101 strcat(RFeatureList, RPICT_FEATURES);
102 if (!strcmp(argv[1], "-features"))
103 return feature_status(argc-2, argv+2);
104 /* option city */
105 for (i = 1; i < argc; i++) {
106 /* expand arguments */
107 while ((rval = expandarg(&argc, &argv, i)) > 0)
108 ;
109 if (rval < 0) {
110 sprintf(errmsg, "cannot expand '%s'", argv[i]);
111 error(SYSTEM, errmsg);
112 }
113 if (argv[i] == NULL || argv[i][0] != '-')
114 break; /* break from options */
115 if (!strcmp(argv[i], "-version")) {
116 puts(VersionID);
117 quit(0);
118 }
119 if (!strcmp(argv[i], "-defaults") ||
120 !strcmp(argv[i], "-help")) {
121 printdefaults();
122 quit(0);
123 }
124 rval = getrenderopt(argc-i, argv+i);
125 if (rval >= 0) {
126 i += rval;
127 continue;
128 }
129 rval = getviewopt(&ourview, argc-i, argv+i);
130 if (rval >= 0) {
131 i += rval;
132 continue;
133 }
134 /* rpict options */
135 switch (argv[i][1]) {
136 case 'v': /* view file */
137 if (argv[i][2] != 'f')
138 goto badopt;
139 check(3,"s");
140 rval = viewfile(argv[++i], &ourview, NULL);
141 if (rval < 0) {
142 sprintf(errmsg,
143 "cannot open view file \"%s\"",
144 argv[i]);
145 error(SYSTEM, errmsg);
146 } else if (rval == 0) {
147 sprintf(errmsg,
148 "bad view file \"%s\"",
149 argv[i]);
150 error(USER, errmsg);
151 }
152 break;
153 case 'p': /* pixel */
154 switch (argv[i][2]) {
155 case 's': /* sample */
156 check(3,"i");
157 psample = atoi(argv[++i]);
158 break;
159 case 't': /* threshold */
160 check(3,"f");
161 maxdiff = atof(argv[++i]);
162 break;
163 case 'j': /* jitter */
164 check(3,"f");
165 dstrpix = atof(argv[++i]);
166 break;
167 case 'a': /* aspect */
168 check(3,"f");
169 pixaspect = atof(argv[++i]);
170 break;
171 case 'm': /* motion */
172 check(3,"f");
173 mblur = atof(argv[++i]);
174 break;
175 case 'd': /* aperture */
176 check(3,"f");
177 dblur = atof(argv[++i]);
178 break;
179 default:
180 goto badopt;
181 }
182 break;
183 case 'x': /* x resolution */
184 check(2,"i");
185 hresolu = atoi(argv[++i]);
186 break;
187 case 'y': /* y resolution */
188 check(2,"i");
189 vresolu = atoi(argv[++i]);
190 break;
191 case 'S': /* slave index */
192 check(2,"i");
193 seqstart = atoi(argv[++i]);
194 break;
195 case 'o': /* output file */
196 check(2,"s");
197 outfile = argv[++i];
198 break;
199 case 'z': /* z file */
200 check(2,"s");
201 zfile = argv[++i];
202 break;
203 case 'r': /* recover file */
204 if (argv[i][2] == 'o') { /* +output */
205 check(3,"s");
206 outfile = argv[i+1];
207 } else
208 check(2,"s");
209 recover = argv[++i];
210 break;
211 case 't': /* timer */
212 check(2,"i");
213 ralrm = atoi(argv[++i]);
214 break;
215 #ifdef PERSIST
216 case 'P': /* persist file */
217 if (argv[i][2] == 'P') {
218 check(3,"s");
219 persist = PARALLEL;
220 } else {
221 check(2,"s");
222 persist = PERSIST;
223 }
224 persistfile(argv[++i]);
225 break;
226 #endif
227 case 'w': /* warnings */
228 rval = erract[WARNING].pf != NULL;
229 check_bool(2,rval);
230 if (rval) erract[WARNING].pf = wputs;
231 else erract[WARNING].pf = NULL;
232 break;
233 case 'e': /* error file */
234 check(2,"s");
235 errfile = argv[++i];
236 break;
237 default:
238 goto badopt;
239 }
240 }
241 err = setview(&ourview); /* set viewing parameters */
242 if (err != NULL)
243 error(USER, err);
244 /* initialize object types */
245 initotypes();
246 /* initialize urand */
247 if (rand_samp) {
248 srandom((long)time(0));
249 initurand(0);
250 } else {
251 srandom(0L);
252 initurand(2048);
253 }
254 /* set up signal handling */
255 sigdie(SIGINT, "Interrupt");
256 #ifdef SIGHUP
257 sigdie(SIGHUP, "Hangup");
258 #endif
259 sigdie(SIGTERM, "Terminate");
260 #ifdef SIGPIPE
261 sigdie(SIGPIPE, "Broken pipe");
262 #endif
263 #ifdef SIGALRM
264 sigdie(SIGALRM, "Alarm clock");
265 #endif
266 #ifdef SIGXCPU
267 sigdie(SIGXCPU, "CPU limit exceeded");
268 sigdie(SIGXFSZ, "File size exceeded");
269 #endif
270 /* open error file */
271 if (errfile != NULL) {
272 if (freopen(errfile, "a", stderr) == NULL)
273 quit(2);
274 fprintf(stderr, "**************\n*** PID %5d: ",
275 getpid());
276 printargs(argc, argv, stderr);
277 putc('\n', stderr);
278 fflush(stderr);
279 }
280 #ifdef NICE
281 nice(NICE); /* lower priority */
282 #endif
283 /* get octree */
284 if (i == argc)
285 octname = NULL;
286 else if (i == argc-1)
287 octname = argv[i];
288 else
289 goto badopt;
290 if (seqstart > 0 && octname == NULL)
291 error(USER, "missing octree argument");
292 /* set up output */
293 #ifdef PERSIST
294 if (persist) {
295 if (recover != NULL)
296 error(USER, "persist option used with recover file");
297 if (seqstart <= 0)
298 error(USER, "persist option only for sequences");
299 if (outfile == NULL)
300 duped1 = dup(fileno(stdout)); /* don't lose our output */
301 openheader();
302 } else
303 #endif
304 if (outfile != NULL)
305 openheader();
306 SET_FILE_BINARY(stdout);
307 if (octname == NULL)
308 SET_FILE_BINARY(stdin);
309 readoct(octname, loadflags, &thescene, NULL);
310 nsceneobjs = nobjects;
311
312 if (loadflags & IO_INFO) { /* print header */
313 printargs(i, argv, stdout);
314 printf("SOFTWARE= %s\n", VersionID);
315 }
316
317 ray_init_pmap(); /* PMAP: set up & load photon maps */
318
319 marksources(); /* find and mark sources */
320
321 setambient(); /* initialize ambient calculation */
322
323 fflush(stdout); /* in case we're duplicating header */
324
325 #ifdef PERSIST
326 if (persist) {
327 if (outfile == NULL) { /* reconnect stdout */
328 dup2(duped1, fileno(stdout));
329 close(duped1);
330 }
331 if (persist == PARALLEL) { /* multiprocessing */
332 preload_objs(); /* preload scene */
333 shm_boundary = (char *)malloc(16);
334 strcpy(shm_boundary, "SHM_BOUNDARY");
335 while ((rval=fork()) == 0) { /* keep on forkin' */
336 pflock(1);
337 pfhold();
338 tstart = time((time_t *)NULL);
339 ambsync(); /* load new values */
340 }
341 if (rval < 0)
342 error(SYSTEM, "cannot fork child for persist function");
343 pfdetach(); /* parent will run then exit */
344 }
345 }
346 runagain:
347 if (persist) {
348 if (outfile == NULL) /* if out to stdout */
349 dupheader(); /* send header */
350 else /* if out to file */
351 duped1 = dup(fileno(stdout)); /* hang onto pipe */
352 }
353 #endif
354 /* batch render picture(s) */
355 rpict(seqstart, outfile, zfile, recover);
356 /* flush ambient file */
357 ambsync();
358 #ifdef PERSIST
359 if (persist == PERSIST) { /* first run-through */
360 if ((rval=fork()) == 0) { /* child loops until killed */
361 pflock(1);
362 persist = PCHILD;
363 } else { /* original process exits */
364 if (rval < 0)
365 error(SYSTEM, "cannot fork child for persist function");
366 pfdetach(); /* parent exits */
367 }
368 }
369 if (persist == PCHILD) { /* wait for a signal then go again */
370 if (outfile != NULL)
371 close(duped1); /* release output handle */
372 pfhold();
373 tstart = time((time_t *)NULL); /* reinitialize */
374 raynum = nrays = 0;
375 goto runagain;
376 }
377 #endif
378
379
380 ray_done_pmap(); /* PMAP: free photon maps */
381
382 quit(0);
383
384 badopt:
385 sprintf(errmsg, "command line error at '%s'", argv[i]);
386 error(USER, errmsg);
387 return 1; /* pro forma return */
388
389 #undef check
390 #undef check_bool
391 }
392
393
394 void
395 wputs( /* warning output function */
396 char *s
397 )
398 {
399 int lasterrno = errno;
400 eputs(s);
401 errno = lasterrno;
402 }
403
404
405 void
406 eputs( /* put string to stderr */
407 char *s
408 )
409 {
410 static int midline = 0;
411
412 if (!*s)
413 return;
414 if (!midline++) {
415 fputs(progname, stderr);
416 fputs(": ", stderr);
417 }
418 fputs(s, stderr);
419 if (s[strlen(s)-1] == '\n') {
420 fflush(stderr);
421 midline = 0;
422 }
423 }
424
425
426 static void
427 onsig( /* fatal signal */
428 int signo
429 )
430 {
431 static int gotsig = 0;
432
433 if (gotsig++) /* two signals and we're gone! */
434 _exit(signo);
435
436 #ifdef SIGALRM /* XXX how critical is this? */
437 alarm(15); /* allow 15 seconds to clean up */
438 signal(SIGALRM, SIG_DFL); /* make certain we do die */
439 #endif
440 eputs("signal - ");
441 eputs(sigerr[signo]);
442 eputs("\n");
443 quit(3);
444 }
445
446
447 static void
448 sigdie( /* set fatal signal */
449 int signo,
450 char *msg
451 )
452 {
453 if (signal(signo, onsig) == SIG_IGN)
454 signal(signo, SIG_IGN);
455 sigerr[signo] = msg;
456 }
457
458
459 static void
460 printdefaults(void) /* print default values to stdout */
461 {
462 printf("-vt%c\t\t\t\t# view type %s\n", ourview.type,
463 ourview.type==VT_PER ? "perspective" :
464 ourview.type==VT_PAR ? "parallel" :
465 ourview.type==VT_HEM ? "hemispherical" :
466 ourview.type==VT_ANG ? "angular" :
467 ourview.type==VT_CYL ? "cylindrical" :
468 ourview.type==VT_PLS ? "planisphere" :
469 "unknown");
470 printf("-vp %f %f %f\t# view point\n",
471 ourview.vp[0], ourview.vp[1], ourview.vp[2]);
472 printf("-vd %f %f %f\t# view direction\n",
473 ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
474 printf("-vu %f %f %f\t# view up\n",
475 ourview.vup[0], ourview.vup[1], ourview.vup[2]);
476 printf("-vh %f\t\t\t# view horizontal size\n", ourview.horiz);
477 printf("-vv %f\t\t\t# view vertical size\n", ourview.vert);
478 printf("-vo %f\t\t\t# view fore clipping plane\n", ourview.vfore);
479 printf("-va %f\t\t\t# view aft clipping plane\n", ourview.vaft);
480 printf("-vs %f\t\t\t# view shift\n", ourview.hoff);
481 printf("-vl %f\t\t\t# view lift\n", ourview.voff);
482 printf("-x %-9d\t\t\t# x resolution\n", hresolu);
483 printf("-y %-9d\t\t\t# y resolution\n", vresolu);
484 printf("-pa %f\t\t\t# pixel aspect ratio\n", pixaspect);
485 printf("-pj %f\t\t\t# pixel jitter\n", dstrpix);
486 printf("-pm %f\t\t\t# pixel motion\n", mblur);
487 printf("-pd %f\t\t\t# pixel depth-of-field\n", dblur);
488 printf("-ps %-9d\t\t\t# pixel sample\n", psample);
489 printf("-pt %f\t\t\t# pixel threshold\n", maxdiff);
490 printf("-t %-9d\t\t\t# time between reports\n", ralrm);
491 printf(erract[WARNING].pf != NULL ?
492 "-w+\t\t\t\t# warning messages on\n" :
493 "-w-\t\t\t\t# warning messages off\n");
494 print_rdefaults();
495 }