ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rxpmain.cpp
Revision: 2.9
Committed: Thu Jun 5 18:26:46 2025 UTC (35 hours, 5 minutes ago) by greg
Branch: MAIN
CVS Tags: HEAD
Changes since 2.8: +1 -2 lines
Log Message:
fix: Removed unnecessary or redundant progname declarations

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rxpmain.cpp,v 2.8 2025/04/22 17:12:25 greg Exp $";
3 #endif
4 /*
5 * rxpmain.cpp - main for rxpict batch rendering program
6 */
7
8 #include "copyright.h"
9
10 #include <time.h>
11 #include <signal.h>
12
13 #include "rtprocess.h" /* getpid() */
14 #include "platform.h"
15 #include "RpictSimulManager.h"
16 #include "func.h"
17
18 const char *sigerr[NSIG]; /* signal error messages */
19 char *errfile = NULL; /* error output file */
20
21 VIEW ourview = STDVIEW; /* view parameters */
22 int hresolu = 512; /* horizontal resolution */
23 int vresolu = 512; /* vertical resolution */
24 double pixaspect = 1.0; /* pixel aspect ratio */
25 int hres, vres; /* current image resolution for srcdraw.c */
26
27 int psample = 4; /* pixel sample size */
28 double maxdiff = .05; /* max. difference for interpolation */
29 double dstrpix = 0.67; /* square pixel distribution */
30
31 double mblur = 0.; /* motion blur parameter */
32
33 double dblur = 0.; /* depth-of-field blur parameter */
34
35 int nproc = 1; /* number of processes to run */
36
37 int ralrm = 0; /* seconds between reports */
38
39 double pctdone = 0.0; /* percentage done */
40 time_t tlastrept = 0L; /* time at last report */
41 time_t tstart; /* starting time */
42
43 RenderDataType dtype = RDTrgbe; // output data flags
44
45 RpictSimulManager myRPmanager; // global simulation manager
46
47 static void onsig(int signo);
48 static void sigdie(int signo, const char *msg);
49 static void printdefaults(void);
50
51 /* rxpict additional features */
52 #define RXPICT_FEATURES "Recovery\nIrradianceCalc\nViewTypes=v,l,a,h,s,c\n" \
53 "ParticipatingMedia=Mist\n" \
54 "HessianAmbientCache\nAmbientAveraging\nAmbientValueSharing\n" \
55 "PixelJitter\nPixelSampling\nPixelMotion\nPixelDepthOfField\n" \
56 "SmallSourceDrawing\nViewSequence\nProgressReporting\n" \
57 "AdaptiveShadowTesting\nOutputs=v,l\n" \
58 "OutputCS=RGB,XYZ,prims,spec\n"
59
60 void
61 quit(int code) /* quit program */
62 {
63 exit(code); // don't bother about freeing anything
64 }
65
66 /* Set default options */
67 static void
68 default_options(void)
69 {
70 shadthresh = .05;
71 shadcert = .5;
72 srcsizerat = .25;
73 directrelay = 1;
74 ambacc = 0.2;
75 ambres = 64;
76 ambdiv = 512;
77 ambssamp = 128;
78 maxdepth = 7;
79 }
80
81 int
82 main(int argc, char *argv[])
83 {
84 #define check(ol,al) if (argv[i][ol] || \
85 badarg(argc-i-1,argv+i+1,al)) \
86 goto badopt
87 #define check_bool(olen,var) switch (argv[i][olen]) { \
88 case '\0': var = !var; break; \
89 case 'y': case 'Y': case 't': case 'T': \
90 case '+': case '1': var = 1; break; \
91 case 'n': case 'N': case 'f': case 'F': \
92 case '-': case '0': var = 0; break; \
93 default: goto badopt; }
94 RGBPRIMS our_prims; /* private output color primitives */
95 int seqstart = 0;
96 char *recover = NULL;
97 char *outfile = NULL;
98 char *zfile = NULL;
99 int outfmt = 'c';
100 int rval;
101 int i;
102 /* record start time */
103 tstart = time(NULL);
104 /* global program name */
105 progname = argv[0];
106 /* feature check only? */
107 strcat(RFeatureList, RXPICT_FEATURES);
108 if (argc > 1 && !strcmp(argv[1], "-features"))
109 return feature_status(argc-2, argv+2);
110 /* initialize calcomp routines */
111 initfunc();
112 /* set defaults */
113 default_options();
114 /* option city */
115 for (i = 1; i < argc; i++) {
116 /* expand arguments */
117 while ((rval = expandarg(&argc, &argv, i)) > 0)
118 ;
119 if (rval < 0) {
120 sprintf(errmsg, "cannot expand '%s'", argv[i]);
121 error(SYSTEM, errmsg);
122 }
123 if (argv[i] == NULL || argv[i][0] != '-')
124 break; /* break from options */
125 if (!strcmp(argv[i], "-version")) {
126 puts(VersionID);
127 quit(0);
128 }
129 if (!strcmp(argv[i], "-defaults") ||
130 !strcmp(argv[i], "-help")) {
131 printdefaults();
132 quit(0);
133 }
134 rval = getrenderopt(argc-i, argv+i);
135 if (rval >= 0) {
136 i += rval;
137 continue;
138 }
139 rval = getviewopt(&ourview, argc-i, argv+i);
140 if (rval >= 0) {
141 i += rval;
142 continue;
143 }
144 /* rxpict options */
145 switch (argv[i][1]) {
146 case 'v': /* view file */
147 if (argv[i][2] != 'f')
148 goto badopt;
149 check(3,"s");
150 rval = viewfile(argv[++i], &ourview, NULL);
151 if (rval < 0) {
152 sprintf(errmsg,
153 "cannot open view file \"%s\"",
154 argv[i]);
155 error(SYSTEM, errmsg);
156 } else if (rval == 0) {
157 sprintf(errmsg,
158 "bad view file \"%s\"",
159 argv[i]);
160 error(USER, errmsg);
161 }
162 break;
163 case 'n': /* number of processes */
164 check(2,"i");
165 nproc = atoi(argv[++i]);
166 if (nproc < 0 && (nproc += RadSimulManager::GetNCores()) <= 0)
167 nproc = 1;
168 break;
169 case 'f': /* output format */
170 if ((argv[i][2] != 'c') & (argv[i][2] != 'f')
171 || argv[i][3])
172 goto badopt;
173 outfmt = argv[i][2];
174 break;
175 case 'p': /* pixel */
176 switch (argv[i][2]) {
177 case 's': /* sample */
178 check(3,"i");
179 psample = atoi(argv[++i]);
180 if (psample < 1) psample = 1;
181 break;
182 case 't': /* threshold */
183 check(3,"f");
184 maxdiff = atof(argv[++i]);
185 break;
186 case 'j': /* jitter */
187 check(3,"f");
188 dstrpix = atof(argv[++i]);
189 break;
190 case 'a': /* aspect */
191 check(3,"f");
192 pixaspect = atof(argv[++i]);
193 break;
194 case 'm': /* motion */
195 check(3,"f");
196 mblur = atof(argv[++i]);
197 mblur *= (mblur > 0);
198 break;
199 case 'd': /* aperture */
200 check(3,"f");
201 dblur = atof(argv[++i]);
202 dblur *= (dblur > 0);
203 break;
204 case 'R': /* standard RGB output */
205 if (strcmp(argv[i]+2, "RGB"))
206 goto badopt;
207 myRPmanager.prims = stdprims;
208 dtype = RDTnewCT(dtype, RDTrgbe);
209 break;
210 case 'X': /* XYZ output */
211 if (strcmp(argv[i]+2, "XYZ"))
212 goto badopt;
213 myRPmanager.prims = xyzprims;
214 dtype = RDTnewCT(dtype, RDTxyze);
215 break;
216 case 'c': /* chromaticities */
217 check(3,"ffffffff");
218 rval = 0;
219 for (int j = 0; j < 8; j++) {
220 our_prims[0][j] = atof(argv[++i]);
221 rval |= fabs(our_prims[0][j]-stdprims[0][j]) > .001;
222 }
223 if (rval) {
224 if (!colorprimsOK(our_prims))
225 error(USER, "illegal primary chromaticities");
226 myRPmanager.prims = our_prims;
227 } else
228 myRPmanager.prims = stdprims;
229 dtype = RDTnewCT(dtype, RDTrgbe);
230 break;
231 default:
232 goto badopt;
233 }
234 break;
235 case 'd': /* reference depth */
236 if (argv[i][2] || !myRPmanager.SetReferenceDepth(argv[++i]))
237 goto badopt;
238 dtype = RDTnewDT(dtype, RDTdshort);
239 break;
240 case 'x': /* x resolution */
241 check(2,"i");
242 hresolu = atoi(argv[++i]);
243 break;
244 case 'y': /* y resolution */
245 check(2,"i");
246 vresolu = atoi(argv[++i]);
247 break;
248 case 'S': /* start index */
249 check(2,"i");
250 seqstart = atoi(argv[++i]);
251 seqstart *= (seqstart > 0);
252 break;
253 case 'o': /* output file */
254 check(2,"s");
255 outfile = argv[++i];
256 break;
257 case 'z': /* z file */
258 check(2,"s");
259 zfile = argv[++i];
260 break;
261 case 'r': /* recover file */
262 if (argv[i][2] == 'o') { /* +output */
263 check(3,"s");
264 outfile = argv[i+1];
265 } else
266 check(2,"s");
267 recover = argv[++i];
268 break;
269 #if MAXCSAMP>3
270 case 'c': /* output spectral results */
271 if (argv[i][2] != 'o')
272 goto badopt;
273 rval = (myRPmanager.prims == NULL);
274 check_bool(3,rval);
275 if (rval)
276 myRPmanager.prims = NULL;
277 else if (myRPmanager.prims == NULL)
278 myRPmanager.prims = stdprims;
279 dtype = RDTnewCT(dtype, rval ? RDTscolr : RDTrgbe);
280 break;
281 #endif
282 case 't': /* timer */
283 check(2,"i");
284 ralrm = atoi(argv[++i]);
285 break;
286 case 'w': /* warnings */
287 rval = erract[WARNING].pf != NULL;
288 check_bool(2,rval);
289 if (rval) erract[WARNING].pf = wputs;
290 else erract[WARNING].pf = NULL;
291 break;
292 case 'e': /* error file */
293 check(2,"s");
294 errfile = argv[++i];
295 break;
296 default:
297 goto badopt;
298 }
299 }
300 if (maxdiff <= FTINY) /* check for useless sampling */
301 psample = 1;
302 if (zfile == NULL) /* set up depth output */
303 dtype = RDTnewDT(dtype, RDTnone);
304 else if (!RDTdepthT(dtype))
305 dtype = RDTnewDT(dtype, RDTdfloat);
306 /* check pixel output type */
307 if ((myRPmanager.prims == NULL) & (NCSAMP == 3)) {
308 myRPmanager.prims = stdprims;
309 dtype = RDTnewCT(dtype, RDTrgbe);
310 }
311 if (outfmt == 'f')
312 switch (RDTcolorT(dtype)) {
313 case RDTrgbe:
314 dtype = RDTnewCT(dtype, RDTrgb);
315 break;
316 case RDTxyze:
317 dtype = RDTnewCT(dtype, RDTxyz);
318 break;
319 case RDTscolr:
320 dtype = RDTnewCT(dtype, RDTscolor);
321 break;
322 case RDTrgb:
323 case RDTxyz:
324 case RDTscolor:
325 break;
326 default:
327 error(INTERNAL, "botched color output type");
328 }
329 /* set up signal handling */
330 sigdie(SIGINT, "Interrupt");
331 #ifdef SIGHUP
332 sigdie(SIGHUP, "Hangup");
333 #endif
334 sigdie(SIGTERM, "Terminate");
335 #ifdef SIGPIPE
336 sigdie(SIGPIPE, "Broken pipe");
337 #endif
338 #ifdef SIGALRM
339 sigdie(SIGALRM, "Alarm clock");
340 #endif
341 #ifdef SIGXCPU
342 sigdie(SIGXCPU, "CPU limit exceeded");
343 sigdie(SIGXFSZ, "File size exceeded");
344 #endif
345 /* open error file */
346 if (errfile != NULL) {
347 if (freopen(errfile, "a", stderr) == NULL)
348 quit(2);
349 fprintf(stderr, "**************\n*** PID %5d: ",
350 getpid());
351 printargs(argc, argv, stderr);
352 putc('\n', stderr);
353 fflush(stderr);
354 }
355 #ifdef NICE
356 nice(NICE); /* lower priority */
357 #endif
358 if (i < argc-1)
359 goto badopt;
360 // load octree
361 if (!myRPmanager.LoadOctree(argv[i]))
362 error(USER, "missing octree argument");
363 // add new header info
364 myRPmanager.AddHeader(i, argv);
365 {
366 char buf[128] = "SOFTWARE= ";
367 strcpy(buf+10, VersionID);
368 myRPmanager.AddHeader(buf);
369 }
370 // start our engines
371 nproc = myRPmanager.SetThreadCount(nproc);
372 // batch render picture(s)
373 rpict(seqstart, outfile, zfile, recover);
374
375 quit(0); // clean up and exit
376
377 badopt:
378 sprintf(errmsg, "command line error at '%s'", argv[i]);
379 error(USER, errmsg);
380 return 1; /* pro forma return */
381
382 #undef check
383 #undef check_bool
384 }
385
386
387 void
388 wputs( /* warning output function */
389 const char *s
390 )
391 {
392 int lasterrno = errno;
393 eputs(s);
394 errno = lasterrno;
395 }
396
397
398 void
399 eputs( /* put string to stderr */
400 const char *s
401 )
402 {
403 static int midline = 0;
404
405 if (!*s)
406 return;
407 if (!midline++) {
408 fputs(progname, stderr);
409 fputs(": ", stderr);
410 }
411 fputs(s, stderr);
412 if (s[strlen(s)-1] == '\n') {
413 fflush(stderr);
414 midline = 0;
415 }
416 }
417
418
419 static void
420 onsig( /* fatal signal */
421 int signo
422 )
423 {
424 static int gotsig = 0;
425
426 if (gotsig++) /* two signals and we're gone! */
427 _exit(signo);
428
429 #ifdef SIGALRM /* XXX how critical is this? */
430 alarm(30); /* allow 30 seconds to clean up */
431 signal(SIGALRM, SIG_DFL); /* make certain we do die */
432 #endif
433 eputs("signal - ");
434 eputs(sigerr[signo]);
435 eputs("\n");
436 quit(3);
437 }
438
439
440 static void
441 sigdie( /* set fatal signal */
442 int signo,
443 const char *msg
444 )
445 {
446 if (signal(signo, onsig) == SIG_IGN)
447 signal(signo, SIG_IGN);
448 sigerr[signo] = msg;
449 }
450
451
452 static void
453 printdefaults(void) /* print default values to stdout */
454 {
455 printf("-n %-2d\t\t\t\t# number of rendering processes\n", nproc);
456 printf("-vt%c\t\t\t\t# view type %s\n", ourview.type,
457 ourview.type==VT_PER ? "perspective" :
458 ourview.type==VT_PAR ? "parallel" :
459 ourview.type==VT_HEM ? "hemispherical" :
460 ourview.type==VT_ANG ? "angular" :
461 ourview.type==VT_CYL ? "cylindrical" :
462 ourview.type==VT_PLS ? "planisphere" :
463 "unknown");
464 printf("-vp %f %f %f\t# view point\n",
465 ourview.vp[0], ourview.vp[1], ourview.vp[2]);
466 printf("-vd %f %f %f\t# view direction\n",
467 ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
468 printf("-vu %f %f %f\t# view up\n",
469 ourview.vup[0], ourview.vup[1], ourview.vup[2]);
470 printf("-vh %f\t\t\t# view horizontal size\n", ourview.horiz);
471 printf("-vv %f\t\t\t# view vertical size\n", ourview.vert);
472 printf("-vo %f\t\t\t# view fore clipping plane\n", ourview.vfore);
473 printf("-va %f\t\t\t# view aft clipping plane\n", ourview.vaft);
474 printf("-vs %f\t\t\t# view shift\n", ourview.hoff);
475 printf("-vl %f\t\t\t# view lift\n", ourview.voff);
476 printf("-x %-9d\t\t\t# x resolution\n", hresolu);
477 printf("-y %-9d\t\t\t# y resolution\n", vresolu);
478 if (myRPmanager.prims == stdprims)
479 printf("-pRGB\t\t\t\t# standard RGB color output\n");
480 else if (myRPmanager.prims == xyzprims)
481 printf("-pXYZ\t\t\t\t# CIE XYZ color output\n");
482 else if (myRPmanager.prims != NULL)
483 printf("-pc %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\t# output color primaries and white point\n",
484 myRPmanager.prims[RED][0], myRPmanager.prims[RED][1],
485 myRPmanager.prims[GRN][0], myRPmanager.prims[GRN][1],
486 myRPmanager.prims[BLU][0], myRPmanager.prims[BLU][1],
487 myRPmanager.prims[WHT][0], myRPmanager.prims[WHT][1]);
488 if (NCSAMP > 3)
489 printf(myRPmanager.prims != NULL ? "-co-\t\t\t\t# output tristimulus colors\n" :
490 "-co+\t\t\t\t# output spectral values\n");
491 printf("-pa %f\t\t\t# pixel aspect ratio\n", pixaspect);
492 printf("-pj %f\t\t\t# pixel jitter\n", dstrpix);
493 printf("-pm %f\t\t\t# pixel motion\n", mblur);
494 printf("-pd %f\t\t\t# pixel depth-of-field\n", dblur);
495 printf("-ps %-9d\t\t\t# pixel sample\n", psample);
496 printf("-pt %f\t\t\t# pixel threshold\n", maxdiff);
497 printf("-t %-9d\t\t\t# time between reports\n", ralrm);
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 }
503
504
505 // my progress report call-back
506 static void
507 progReporter(double pct)
508 {
509 static time_t lastReportTime = 0;
510 time_t tnow = time(NULL);
511
512 if (pct < 100.-FTINY && tnow - lastReportTime < ralrm)
513 return; // too soon, my Precious...
514
515 sprintf(errmsg, "%7.3f%% done after %7.3f hours\n", pct, (tnow-tstart)/3600.);
516 eputs(errmsg);
517 // reset timer at 100%
518 lastReportTime = tnow * (pct < 100.-FTINY);
519 }
520
521
522 // Principal function for rpict execution (prototype in ray.h for some reason)
523 void
524 rpict(int seq, char *pout, char *zout, char *prvr)
525 /*
526 * If seq is greater than zero, we will render a sequence of
527 * images based on view parameter strings read from the standard input.
528 * If pout is NULL, then all images will be sent to the standard ouput.
529 * If seq is greater than zero and prvr is an integer, then it is the
530 * frame number at which rendering should begin. Preceeding view parameter
531 * strings will be skipped in the input.
532 * Note that pout and zout should contain %d format specifications for
533 * sequenced file naming.
534 */
535 {
536 char fbuf[256], dbuf[256];
537
538 if (!zout ^ !RDTdepthT(dtype))
539 error(INTERNAL, "output depth type requires spec and vice versa");
540
541 if (prvr && isint(prvr)) { // sequence recovery?
542 if (!seq)
543 error(USER, "sequence recovery requires starting frame");
544 if (!pout)
545 error(USER, "need output spec for sequence recovery");
546 int rno = atoi(prvr);
547 if (rno < seq)
548 error(USER, "recovery frame before starting frame");
549 while (seq <= rno) {
550 if (!fgets(fbuf, sizeof(fbuf), stdin))
551 error(USER, "recovery frame past end of sequence");
552 seq += (isview(fbuf) && sscanview(&ourview, fbuf) > 0);
553 }
554 sprintf(prvr=fbuf, pout, rno);
555 }
556 if (ralrm > 0)
557 myRPmanager.prCB = progReporter;
558 else
559 myRPmanager.prCB = NULL;
560 if (prvr) { // recovering partial render?
561 if ((seq > 0) & (prvr != fbuf))
562 error(USER, "recover spec must be number in sequence");
563 if (zout) sprintf(dbuf, zout, seq);
564 if (ralrm > 0) {
565 sprintf(errmsg, "resuming partial rendering '%s'\n", prvr);
566 eputs(errmsg);
567 }
568 dtype = myRPmanager.ResumeFrame(prvr, zout ? dbuf : zout);
569 if (!dtype)
570 error(USER, "ResumeFrame() failed");
571 if (!seq)
572 return; // all done if not a sequence
573 }
574 do {
575 if (prvr) // have view from sequence recovery?
576 prvr = NULL;
577 else if (seq) { // else read next view in sequence
578 while (fgets(fbuf, sizeof(fbuf), stdin))
579 if (isview(fbuf) && sscanview(&ourview, fbuf) > 0)
580 break;
581 if (feof(stdin))
582 return; // reached end of view input
583 }
584 // get (indexed) output file name(s)
585 if (pout) sprintf(fbuf, pout, seq);
586 if (zout) sprintf(dbuf, zout, seq);
587
588 if (ralrm > 0) { // start report if requested
589 if (myRPmanager.NThreads() > 1)
590 sprintf(errmsg, "%2d processes ", myRPmanager.NThreads());
591 else
592 sprintf(errmsg, "PID %6d ", getpid());
593 eputs(errmsg);
594 if (seq) {
595 sprintf(errmsg, "rendering frame %5d ", seq);
596 eputs(errmsg);
597 } else
598 eputs("rendering picture ");
599 if (pout) {
600 sprintf(errmsg, "to '%s'\n", fbuf);
601 eputs(errmsg);
602 } else
603 eputs("to stdout\n");
604 if (zout) {
605 sprintf(errmsg, "\twith %s depth map in '%s'\n",
606 RDTdepthT(dtype)==RDTdshort ?
607 "encoded 16-bit" : "raw float",
608 dbuf);
609 eputs(errmsg);
610 }
611 }
612 // set up view and size
613 int xydim[2] = {hresolu, vresolu};
614 if (!myRPmanager.NewFrame(ourview, xydim, &pixaspect))
615 error(USER, "NewFrame() failed");
616
617 myRPmanager.frameNo = seq;
618
619 errno = 0; // render frame, skipping if it exists
620 if (!myRPmanager.RenderFrame(pout ? fbuf : pout, dtype,
621 zout ? dbuf : zout)
622 && !seq | (errno != EEXIST))
623 error(USER, "RenderFrame() failed");
624 } while (seq++); // all done if not a sequence
625 }