ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rpmain.c
Revision: 2.36
Committed: Fri Nov 15 20:47:42 2024 UTC (6 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.35: +64 -6 lines
Log Message:
feat(rpict): Experimental source skipping option with -DSSKIPOPT compile flag

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rpmain.c,v 2.35 2024/10/30 16:47:03 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 *errfile = NULL; /* error output file */
34 #ifdef SSKIPOPT
35 int *ssndx_map = NULL; /* loaded source index map */
36 float *scorr_map = NULL; /* loaded source correction map */
37 #endif
38 extern time_t time();
39 extern time_t tstart; /* start time */
40
41 extern int ralrm; /* seconds between reports */
42
43 extern VIEW ourview; /* viewing parameters */
44
45 extern int hresolu; /* horizontal resolution */
46 extern int vresolu; /* vertical resolution */
47 extern double pixaspect; /* pixel aspect ratio */
48
49 extern int psample; /* pixel sample size */
50 extern double maxdiff; /* max. sample difference */
51 extern double dstrpix; /* square pixel distribution */
52
53 extern double mblur; /* motion blur parameter */
54
55 extern double dblur; /* depth-of-field blur parameter */
56
57 RGBPRIMP out_prims = stdprims; /* output color primitives */
58 static RGBPRIMS our_prims; /* private output color primitives */
59
60 static void onsig(int signo);
61 static void sigdie(int signo, char *msg);
62 static void printdefaults(void);
63 /* rpict additional features */
64 #ifdef PERSIST
65 #define RPICT_FEATURES "Persist\nParallelPersist\n" \
66 "ParticipatingMedia=Mist\n" \
67 "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 "OutputCS=RGB,XYZ,prims\n"
73 #else
74 #define RPICT_FEATURES "Recovery\nIrradianceCalc\nViewTypes=v,l,a,h,s,c\n" \
75 "ParticipatingMedia=Mist\n" \
76 "HessianAmbientCache\nAmbientAveraging\nAmbientValueSharing\n" \
77 "PixelJitter\nPixelSampling\nPixelMotion\nPixelDepthOfField\n" \
78 "SmallSourceDrawing\nViewSequence\nProgressReporting\n" \
79 "AdaptiveShadowTesting\nOutputs=v,l\n" \
80 "OutputCS=RGB,XYZ,prims\n"
81 #endif
82
83
84 int
85 main(int argc, char *argv[])
86 {
87 #define check(ol,al) if (argv[i][ol] || \
88 badarg(argc-i-1,argv+i+1,al)) \
89 goto badopt
90 #define check_bool(olen,var) switch (argv[i][olen]) { \
91 case '\0': var = !var; break; \
92 case 'y': case 'Y': case 't': case 'T': \
93 case '+': case '1': var = 1; break; \
94 case 'n': case 'N': case 'f': case 'F': \
95 case '-': case '0': var = 0; break; \
96 default: goto badopt; }
97 char *err;
98 char *recover = NULL;
99 char *outfile = NULL;
100 char *zfile = NULL;
101 #ifdef SSKIPOPT
102 char *sskipspec = NULL;
103 char *scorrfile = NULL;
104 #endif
105 int loadflags = ~IO_FILES;
106 int seqstart = 0;
107 int persist = 0;
108 int duped1 = -1;
109 int rval;
110 int i;
111 /* record start time */
112 tstart = time((time_t *)NULL);
113 /* global program name */
114 progname = argv[0] = fixargv0(argv[0]);
115 /* feature check only? */
116 strcat(RFeatureList, RPICT_FEATURES);
117 if (argc > 1 && !strcmp(argv[1], "-features"))
118 return feature_status(argc-2, argv+2);
119 /* option city */
120 for (i = 1; i < argc; i++) {
121 /* expand arguments */
122 while ((rval = expandarg(&argc, &argv, i)) > 0)
123 ;
124 if (rval < 0) {
125 sprintf(errmsg, "cannot expand '%s'", argv[i]);
126 error(SYSTEM, errmsg);
127 }
128 if (argv[i] == NULL || argv[i][0] != '-')
129 break; /* break from options */
130 if (!strcmp(argv[i], "-version")) {
131 puts(VersionID);
132 quit(0);
133 }
134 if (!strcmp(argv[i], "-defaults") ||
135 !strcmp(argv[i], "-help")) {
136 printdefaults();
137 quit(0);
138 }
139 rval = getrenderopt(argc-i, argv+i);
140 if (rval >= 0) {
141 i += rval;
142 continue;
143 }
144 rval = getviewopt(&ourview, argc-i, argv+i);
145 if (rval >= 0) {
146 i += rval;
147 continue;
148 }
149 /* rpict options */
150 switch (argv[i][1]) {
151 case 'v': /* view file */
152 if (argv[i][2] != 'f')
153 goto badopt;
154 check(3,"s");
155 rval = viewfile(argv[++i], &ourview, NULL);
156 if (rval < 0) {
157 sprintf(errmsg,
158 "cannot open view file \"%s\"",
159 argv[i]);
160 error(SYSTEM, errmsg);
161 } else if (rval == 0) {
162 sprintf(errmsg,
163 "bad view file \"%s\"",
164 argv[i]);
165 error(USER, errmsg);
166 }
167 break;
168 case 'p': /* pixel */
169 switch (argv[i][2]) {
170 case 's': /* sample */
171 check(3,"i");
172 psample = atoi(argv[++i]);
173 break;
174 case 't': /* threshold */
175 check(3,"f");
176 maxdiff = atof(argv[++i]);
177 break;
178 case 'j': /* jitter */
179 check(3,"f");
180 dstrpix = atof(argv[++i]);
181 break;
182 case 'a': /* aspect */
183 check(3,"f");
184 pixaspect = atof(argv[++i]);
185 break;
186 case 'm': /* motion */
187 check(3,"f");
188 mblur = atof(argv[++i]);
189 break;
190 case 'd': /* aperture */
191 check(3,"f");
192 dblur = atof(argv[++i]);
193 break;
194 case 'R': /* standard RGB output */
195 if (strcmp(argv[i]+2, "RGB"))
196 goto badopt;
197 out_prims = stdprims;
198 break;
199 case 'X': /* XYZ output */
200 if (strcmp(argv[i]+2, "XYZ"))
201 goto badopt;
202 out_prims = xyzprims;
203 break;
204 case 'c': { /* chromaticities */
205 int j;
206 check(3,"ffffffff");
207 rval = 0;
208 for (j = 0; j < 8; j++) {
209 our_prims[0][j] = atof(argv[++i]);
210 rval |= fabs(our_prims[0][j]-stdprims[0][j]) > .001;
211 }
212 if (rval) {
213 if (!colorprimsOK(our_prims))
214 error(USER, "illegal primary chromaticities");
215 out_prims = our_prims;
216 } else
217 out_prims = stdprims;
218 } break;
219 default:
220 goto badopt;
221 }
222 break;
223 case 'x': /* x resolution */
224 check(2,"i");
225 hresolu = atoi(argv[++i]);
226 break;
227 case 'y': /* y resolution */
228 check(2,"i");
229 vresolu = atoi(argv[++i]);
230 break;
231 case 'S': /* slave index */
232 check(2,"i");
233 seqstart = atoi(argv[++i]);
234 break;
235 case 'o': /* output file */
236 check(2,"s");
237 outfile = argv[++i];
238 break;
239 case 'z': /* z file */
240 check(2,"s");
241 zfile = argv[++i];
242 break;
243 case 'r': /* recover file */
244 if (argv[i][2] == 'o') { /* +output */
245 check(3,"s");
246 outfile = argv[i+1];
247 } else
248 check(2,"s");
249 recover = argv[++i];
250 break;
251 #ifdef SSKIPOPT
252 case 'd':
253 switch (argv[i][2]) {
254 case 'S': /* direct skip */
255 check(3,"s");
256 sskipspec = argv[++i];
257 break;
258 case 'C': /* direct correction */
259 check(3,"s");
260 scorrfile = argv[++i];
261 break;
262 default:
263 goto badopt;
264 }
265 break;
266 #endif
267 #ifdef PERSIST
268 case 'P': /* persist file */
269 if (argv[i][2] == 'P') {
270 check(3,"s");
271 persist = PARALLEL;
272 } else {
273 check(2,"s");
274 persist = PERSIST;
275 }
276 persistfile(argv[++i]);
277 break;
278 #endif
279 case 't': /* timer */
280 check(2,"i");
281 ralrm = atoi(argv[++i]);
282 break;
283 case 'w': /* warnings */
284 rval = erract[WARNING].pf != NULL;
285 check_bool(2,rval);
286 if (rval) erract[WARNING].pf = wputs;
287 else erract[WARNING].pf = NULL;
288 break;
289 case 'e': /* error file */
290 check(2,"s");
291 errfile = argv[++i];
292 break;
293 default:
294 goto badopt;
295 }
296 }
297 /* set/check spectral sampling */
298 if (setspectrsamp(CNDX, WLPART) <= 0)
299 error(USER, "unsupported spectral sampling");
300
301 err = setview(&ourview); /* set viewing parameters */
302 if (err != NULL)
303 error(USER, err);
304 /* initialize object types */
305 initotypes();
306 /* initialize urand */
307 if (rand_samp) {
308 srandom((long)time(0));
309 initurand(0);
310 } else {
311 srandom(0L);
312 initurand(2048);
313 }
314 /* set up signal handling */
315 sigdie(SIGINT, "Interrupt");
316 #ifdef SIGHUP
317 sigdie(SIGHUP, "Hangup");
318 #endif
319 sigdie(SIGTERM, "Terminate");
320 #ifdef SIGPIPE
321 sigdie(SIGPIPE, "Broken pipe");
322 #endif
323 #ifdef SIGALRM
324 sigdie(SIGALRM, "Alarm clock");
325 #endif
326 #ifdef SIGXCPU
327 sigdie(SIGXCPU, "CPU limit exceeded");
328 sigdie(SIGXFSZ, "File size exceeded");
329 #endif
330 /* open error file */
331 if (errfile != NULL) {
332 if (freopen(errfile, "a", stderr) == NULL)
333 quit(2);
334 fprintf(stderr, "**************\n*** PID %5d: ",
335 getpid());
336 printargs(argc, argv, stderr);
337 putc('\n', stderr);
338 fflush(stderr);
339 }
340 #ifdef NICE
341 nice(NICE); /* lower priority */
342 #endif
343 /* get octree */
344 if (i == argc)
345 octname = NULL;
346 else if (i == argc-1)
347 octname = argv[i];
348 else
349 goto badopt;
350 if (seqstart > 0 && octname == NULL)
351 error(USER, "missing octree argument");
352 /* set up output */
353 #ifdef PERSIST
354 if (persist) {
355 if (recover != NULL)
356 error(USER, "persist option used with recover file");
357 if (seqstart <= 0)
358 error(USER, "persist option only for sequences");
359 if (outfile == NULL)
360 duped1 = dup(fileno(stdout)); /* don't lose our output */
361 openheader();
362 } else
363 #endif
364 if (outfile != NULL)
365 openheader();
366 SET_FILE_BINARY(stdout);
367 if (octname == NULL)
368 SET_FILE_BINARY(stdin);
369 readoct(octname, loadflags, &thescene, NULL);
370 nsceneobjs = nobjects;
371
372 if (loadflags & IO_INFO) { /* print header */
373 printargs(i, argv, stdout);
374 printf("SOFTWARE= %s\n", VersionID);
375 }
376
377 ray_init_pmap(); /* PMAP: set up & load photon maps */
378
379 marksources(); /* find and mark sources */
380 #ifdef SSKIPOPT
381 if (sskipspec != NULL) { /* load source skip maps? */
382 if ((seqstart > 0) | (persist > 0))
383 error(USER,
384 "source skip map incompatible with -S/-P/-PP");
385 if (srcskip_open(sskipspec, scorrfile) <= 0)
386 quit(1);
387 if ((ssndx_map = srcskip_ndxmap()) == NULL)
388 quit(1);
389 if (scorrfile != NULL &&
390 (scorr_map = srcskip_corrmap()) == NULL)
391 quit(1);
392 srcskip_close(); /* leaves maps loaded */
393 }
394 #endif
395 setambient(); /* initialize ambient calculation */
396
397 fflush(stdout); /* in case we're duplicating header */
398
399 #ifdef PERSIST
400 if (persist) {
401 if (outfile == NULL) { /* reconnect stdout */
402 dup2(duped1, fileno(stdout));
403 close(duped1);
404 }
405 if (persist == PARALLEL) { /* multiprocessing */
406 cow_memshare(); /* preloads scene */
407 while ((rval=fork()) == 0) { /* keep on forkin' */
408 pflock(1);
409 pfhold();
410 tstart = time((time_t *)NULL);
411 ambsync(); /* load new values */
412 }
413 if (rval < 0)
414 error(SYSTEM, "cannot fork child for persist function");
415 pfdetach(); /* parent will run then exit */
416 }
417 }
418 runagain:
419 if (persist) {
420 if (outfile == NULL) /* if out to stdout */
421 dupheader(); /* send header */
422 else /* if out to file */
423 duped1 = dup(fileno(stdout)); /* hang onto pipe */
424 }
425 #endif
426 /* batch render picture(s) */
427 rpict(seqstart, outfile, zfile, recover);
428 /* flush ambient file */
429 ambsync();
430 #ifdef PERSIST
431 if (persist == PERSIST) { /* first run-through */
432 if ((rval=fork()) == 0) { /* child loops until killed */
433 pflock(1);
434 persist = PCHILD;
435 } else { /* original process exits */
436 if (rval < 0)
437 error(SYSTEM, "cannot fork child for persist function");
438 pfdetach(); /* parent exits */
439 }
440 }
441 if (persist == PCHILD) { /* wait for a signal then go again */
442 if (outfile != NULL)
443 close(duped1); /* release output handle */
444 pfhold();
445 tstart = time((time_t *)NULL); /* reinitialize */
446 raynum = nrays = 0;
447 goto runagain;
448 }
449 #endif
450
451
452 ray_done_pmap(); /* PMAP: free photon maps */
453
454 quit(0);
455
456 badopt:
457 sprintf(errmsg, "command line error at '%s'", argv[i]);
458 error(USER, errmsg);
459 return 1; /* pro forma return */
460
461 #undef check
462 #undef check_bool
463 }
464
465 #ifdef SSKIPOPT
466 void /* source skip parameters for primary */
467 sskip_ray(RAY *r, double h, double v)
468 {
469 size_t ssi;
470
471 if (ssndx_map == NULL)
472 return; /* nothing to do */
473
474 /* rows counted from the top! */
475 ssi = (size_t)((1.-v)*sskip_dim[1])*sskip_dim[0] +
476 (size_t)(h*sskip_dim[0]);
477
478 if (ssi >= sskip_dim[0]*sskip_dim[1])
479 error(CONSISTENCY, "bad index in sskip_ray()");
480
481 r->rsrc = ssndx_map[ssi];
482 if (scorr_map != NULL)
483 r->scorr = scorr_map[ssi];
484 }
485 #endif
486
487 void
488 wputs( /* warning output function */
489 const char *s
490 )
491 {
492 int lasterrno = errno;
493 if (erract[WARNING].pf == NULL)
494 return; /* called by calcomp or someone */
495 eputs(s);
496 errno = lasterrno;
497 }
498
499
500 void
501 eputs( /* put string to stderr */
502 const char *s
503 )
504 {
505 static int midline = 0;
506
507 if (!*s)
508 return;
509 if (!midline++) {
510 fputs(progname, stderr);
511 fputs(": ", stderr);
512 }
513 fputs(s, stderr);
514 if (s[strlen(s)-1] == '\n') {
515 fflush(stderr);
516 midline = 0;
517 }
518 }
519
520
521 static void
522 onsig( /* fatal signal */
523 int signo
524 )
525 {
526 static int gotsig = 0;
527
528 if (gotsig++) /* two signals and we're gone! */
529 _exit(signo);
530
531 #ifdef SIGALRM /* XXX how critical is this? */
532 alarm(15); /* allow 15 seconds to clean up */
533 signal(SIGALRM, SIG_DFL); /* make certain we do die */
534 #endif
535 eputs("signal - ");
536 eputs(sigerr[signo]);
537 eputs("\n");
538 quit(3);
539 }
540
541
542 static void
543 sigdie( /* set fatal signal */
544 int signo,
545 char *msg
546 )
547 {
548 if (signal(signo, onsig) == SIG_IGN)
549 signal(signo, SIG_IGN);
550 sigerr[signo] = msg;
551 }
552
553
554 static void
555 printdefaults(void) /* print default values to stdout */
556 {
557 printf("-vt%c\t\t\t\t# view type %s\n", ourview.type,
558 ourview.type==VT_PER ? "perspective" :
559 ourview.type==VT_PAR ? "parallel" :
560 ourview.type==VT_HEM ? "hemispherical" :
561 ourview.type==VT_ANG ? "angular" :
562 ourview.type==VT_CYL ? "cylindrical" :
563 ourview.type==VT_PLS ? "planisphere" :
564 "unknown");
565 printf("-vp %f %f %f\t# view point\n",
566 ourview.vp[0], ourview.vp[1], ourview.vp[2]);
567 printf("-vd %f %f %f\t# view direction\n",
568 ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
569 printf("-vu %f %f %f\t# view up\n",
570 ourview.vup[0], ourview.vup[1], ourview.vup[2]);
571 printf("-vh %f\t\t\t# view horizontal size\n", ourview.horiz);
572 printf("-vv %f\t\t\t# view vertical size\n", ourview.vert);
573 printf("-vo %f\t\t\t# view fore clipping plane\n", ourview.vfore);
574 printf("-va %f\t\t\t# view aft clipping plane\n", ourview.vaft);
575 printf("-vs %f\t\t\t# view shift\n", ourview.hoff);
576 printf("-vl %f\t\t\t# view lift\n", ourview.voff);
577 printf("-x %-9d\t\t\t# x resolution\n", hresolu);
578 printf("-y %-9d\t\t\t# y resolution\n", vresolu);
579 if (out_prims == stdprims)
580 printf("-pRGB\t\t\t\t# standard RGB color output\n");
581 else if (out_prims == xyzprims)
582 printf("-pXYZ\t\t\t\t# CIE XYZ color output\n");
583 else if (out_prims != NULL)
584 printf("-pc %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\t# output color primaries and white point\n",
585 out_prims[RED][0], out_prims[RED][1],
586 out_prims[GRN][0], out_prims[GRN][1],
587 out_prims[BLU][0], out_prims[BLU][1],
588 out_prims[WHT][0], out_prims[WHT][1]);
589 printf("-pa %f\t\t\t# pixel aspect ratio\n", pixaspect);
590 printf("-pj %f\t\t\t# pixel jitter\n", dstrpix);
591 printf("-pm %f\t\t\t# pixel motion\n", mblur);
592 printf("-pd %f\t\t\t# pixel depth-of-field\n", dblur);
593 printf("-ps %-9d\t\t\t# pixel sample\n", psample);
594 printf("-pt %f\t\t\t# pixel threshold\n", maxdiff);
595 printf("-t %-9d\t\t\t# time between reports\n", ralrm);
596 printf(erract[WARNING].pf != NULL ?
597 "-w+\t\t\t\t# warning messages on\n" :
598 "-w-\t\t\t\t# warning messages off\n");
599 print_rdefaults();
600 }