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 (33 hours, 22 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.9 static const char RCSid[] = "$Id: rxpmain.cpp,v 2.8 2025/04/22 17:12:25 greg Exp $";
3 greg 2.1 #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 greg 2.8 #include "func.h"
17 greg 2.1
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 greg 2.3 quit(int code) /* quit program */
62 greg 2.1 {
63 greg 2.7 exit(code); // don't bother about freeing anything
64 greg 2.1 }
65    
66 greg 2.5 /* 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 greg 2.1
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 greg 2.8 /* initialize calcomp routines */
111     initfunc();
112 greg 2.5 /* set defaults */
113     default_options();
114 greg 2.1 /* 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 greg 2.2 if (pct < 100.-FTINY && tnow - lastReportTime < ralrm)
513 greg 2.1 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 greg 2.6 * If seq is greater than zero, we will render a sequence of
527 greg 2.1 * 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 greg 2.6 return; // all done if not a sequence
573 greg 2.1 }
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 greg 2.6 } while (seq++); // all done if not a sequence
625 greg 2.1 }