ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rpmain.c
Revision: 2.24
Committed: Mon Feb 6 20:34:17 2023 UTC (15 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.23: +2 -2 lines
Log Message:
fix: fixed crash when executed with no arguments

File Contents

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