ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/rt/rxtmain.cpp
Revision: 2.16
Committed: Fri Dec 5 17:51:34 2025 UTC (11 days, 21 hours ago) by greg
Branch: MAIN
CVS Tags: HEAD
Changes since 2.15: +10 -4 lines
Log Message:
feat(rtrace,rxtrace): Added -pA output option for radiometric flux

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.16 static const char RCSid[] = "$Id: rxtmain.cpp,v 2.15 2025/08/03 18:20:44 greg Exp $";
3 greg 2.1 #endif
4     /*
5 greg 2.7 * rxtmain.cpp - main for per-ray calculation program
6 greg 2.1 */
7    
8     #include "copyright.h"
9    
10     #include <signal.h>
11    
12     #include "rtprocess.h" /* getpid() */
13     #include "platform.h"
14     #include "RtraceSimulManager.h"
15 greg 2.13 #include "func.h"
16 greg 2.1
17     static const char *sigerr[NSIG]; /* signal error messages */
18     char *errfile = NULL; /* error output file */
19    
20     extern const char *formstr(int f); /* string from format */
21     extern int setrtoutput(const char *outvals); /* set output values */
22    
23     int inform = 'a'; /* input format */
24     int outform = 'a'; /* output format */
25    
26     int hresolu = 0; /* horizontal (scan) size */
27     int vresolu = 0; /* vertical resolution */
28    
29     RtraceSimulManager myRTmanager; // global simulation manager
30    
31     static const char *outvals = "v"; /* output specification */
32     static int nproc = 1; /* number of requested threads */
33     static int doheader = 1; /* include information header? */
34    
35     #ifndef MAXMODLIST
36     #define MAXMODLIST 1024 /* maximum modifiers we'll track */
37     #endif
38    
39     extern void (*addobjnotify[])(OBJECT); /* object notification calls */
40     extern void tranotify(OBJECT obj);
41    
42     char *tralist[MAXMODLIST]; /* list of modifers to trace (or no) */
43     int traincl = -1; /* include == 1, exclude == 0 */
44    
45 greg 2.7 double (*sens_curve)(const SCOLOR scol) = NULL; /* spectral conversion for 1-channel */
46 greg 2.3 double out_scalefactor = 1; /* output calibration scale factor */
47     RGBPRIMP out_prims = stdprims; /* output color primitives (NULL if spectral) */
48     static RGBPRIMS our_prims; /* private output color primitives */
49    
50 greg 2.1 static void onsig(int signo);
51     static void sigdie(int signo, const char *msg);
52     static void printdefaults(void);
53    
54 greg 2.10 #define RXTRACE_FEATURES "IrradianceCalc\nMultiprocessing\nDistanceLimiting\n" \
55 greg 2.3 "HessianAmbientCache\nAmbientAveraging\n" \
56     "AmbientValueSharing\nAdaptiveShadowTesting\n" \
57 greg 2.15 "InputFormats=a,f,d\nOutputFormats=a,f,d,c\n" \
58 greg 2.3 "Outputs=o,d,v,V,w,W,l,L,c,p,n,N,s,m,M,r,x,R,X,~\n" \
59     "OutputCS=RGB,XYZ,Y,S,M,prims,spec\n"
60 greg 2.1
61     int
62     main(int argc, char *argv[])
63     {
64     #define check(ol,al) if (argv[i][ol] || \
65     badarg(argc-i-1,argv+i+1,al)) \
66     goto badopt
67     #define check_bool(olen,var) switch (argv[i][olen]) { \
68     case '\0': var = !var; break; \
69     case 'y': case 'Y': case 't': case 'T': \
70     case '+': case '1': var = 1; break; \
71     case 'n': case 'N': case 'f': case 'F': \
72     case '-': case '0': var = 0; break; \
73     default: goto badopt; }
74     char **tralp = NULL;
75     int rval;
76     int i;
77     /* global program name */
78 greg 2.3 progname = argv[0];
79 greg 2.1 /* feature check only? */
80 greg 2.3 strcat(RFeatureList, RXTRACE_FEATURES);
81 greg 2.1 if (argc > 1 && !strcmp(argv[1], "-features"))
82     return feature_status(argc-2, argv+2);
83 greg 2.13 /* initialize calcomp routines */
84     initfunc();
85 greg 2.1 /* add trace notify function */
86     for (i = 0; addobjnotify[i] != NULL; i++)
87     ;
88     addobjnotify[i] = tranotify;
89     /* option city */
90     for (i = 1; i < argc; i++) {
91     /* expand arguments */
92     while ((rval = expandarg(&argc, &argv, i)) > 0)
93     ;
94     if (rval < 0) {
95     sprintf(errmsg, "cannot expand '%s'", argv[i]);
96     error(SYSTEM, errmsg);
97     }
98     if (argv[i] == NULL || argv[i][0] != '-')
99     break; /* break from options */
100     if (!strcmp(argv[i], "-version")) {
101     puts(VersionID);
102     quit(0);
103     }
104     if (!strcmp(argv[i], "-defaults") ||
105     !strcmp(argv[i], "-help")) {
106     printdefaults();
107     quit(0);
108     }
109     rval = getrenderopt(argc-i, argv+i);
110     if (rval >= 0) {
111     i += rval;
112     continue;
113     }
114     switch (argv[i][1]) {
115     case 'n': /* number of cores */
116     check(2,"i");
117     nproc = atoi(argv[++i]);
118     break;
119     case 'x': /* x resolution */
120     check(2,"i");
121     hresolu = atoi(argv[++i]);
122     break;
123     case 'y': /* y resolution */
124     check(2,"i");
125     vresolu = atoi(argv[++i]);
126     break;
127     case 'w': /* warnings */
128     rval = erract[WARNING].pf != NULL;
129     check_bool(2,rval);
130     if (rval) erract[WARNING].pf = wputs;
131     else erract[WARNING].pf = NULL;
132     break;
133     case 'e': /* error file */
134     check(2,"s");
135     errfile = argv[++i];
136     break;
137     case 'l': /* limit distance */
138     if (argv[i][2] != 'd')
139     goto badopt;
140     rval = myRTmanager.rtFlags & RTlimDist;
141     check_bool(3,rval);
142     if (rval) myRTmanager.rtFlags |= RTlimDist;
143     else myRTmanager.rtFlags &= ~RTlimDist;
144     break;
145     case 'I': /* immed. irradiance */
146     rval = myRTmanager.rtFlags & RTimmIrrad;
147 greg 2.11 check_bool(2,rval);
148 greg 2.1 if (rval) myRTmanager.rtFlags |= RTimmIrrad;
149     else myRTmanager.rtFlags &= ~RTimmIrrad;
150     break;
151     case 'f': /* format i/o */
152     switch (argv[i][2]) {
153     case 'a': /* ascii */
154     case 'f': /* float */
155     case 'd': /* double */
156     inform = argv[i][2];
157     break;
158     default:
159     goto badopt;
160     }
161     switch (argv[i][3]) {
162     case '\0':
163     outform = inform;
164     break;
165     case 'a': /* ascii */
166     case 'f': /* float */
167     case 'd': /* double */
168     case 'c': /* color */
169     check(4,"");
170     outform = argv[i][3];
171     break;
172     default:
173     goto badopt;
174     }
175     break;
176     case 'o': /* output */
177     outvals = argv[i]+2;
178     break;
179     case 'h': /* header output */
180     check_bool(2,doheader);
181     break;
182     case 't': /* trace */
183     switch (argv[i][2]) {
184     case 'i': /* include */
185     case 'I':
186     check(3,"s");
187     if (traincl != 1) {
188     traincl = 1;
189     tralp = tralist;
190     }
191     if (argv[i][2] == 'I') { /* file */
192     rval = wordfile(tralp, MAXMODLIST-(tralp-tralist),
193     getpath(argv[++i],getrlibpath(),R_OK));
194     if (rval < 0) {
195     sprintf(errmsg,
196     "cannot open trace include file \"%s\"",
197     argv[i]);
198     error(SYSTEM, errmsg);
199     }
200     tralp += rval;
201     } else {
202     *tralp++ = argv[++i];
203     *tralp = NULL;
204     }
205     break;
206     case 'e': /* exclude */
207     case 'E':
208     check(3,"s");
209     if (traincl != 0) {
210     traincl = 0;
211     tralp = tralist;
212     }
213     if (argv[i][2] == 'E') { /* file */
214     rval = wordfile(tralp, MAXMODLIST-(tralp-tralist),
215     getpath(argv[++i],getrlibpath(),R_OK));
216     if (rval < 0) {
217     sprintf(errmsg,
218     "cannot open trace exclude file \"%s\"",
219     argv[i]);
220     error(SYSTEM, errmsg);
221     }
222     tralp += rval;
223     } else {
224     *tralp++ = argv[++i];
225     *tralp = NULL;
226     }
227     break;
228     default:
229     goto badopt;
230     }
231     break;
232 greg 2.3 case 'p': /* value output */
233     switch (argv[i][2]) {
234     case 'R': /* standard RGB output */
235     if (strcmp(argv[i]+2, "RGB"))
236     goto badopt;
237     out_prims = stdprims;
238     out_scalefactor = 1;
239     sens_curve = NULL;
240     break;
241     case 'X': /* XYZ output */
242     if (strcmp(argv[i]+2, "XYZ"))
243     goto badopt;
244     out_prims = xyzprims;
245     out_scalefactor = WHTEFFICACY;
246     sens_curve = NULL;
247     break;
248     case 'c': {
249     int j;
250     check(3,"ffffffff");
251     rval = 0;
252     for (j = 0; j < 8; j++) {
253     our_prims[0][j] = atof(argv[++i]);
254     rval |= fabs(our_prims[0][j]-stdprims[0][j]) > .001;
255     }
256     if (rval) {
257     if (!colorprimsOK(our_prims))
258     error(USER, "illegal primary chromaticities");
259     out_prims = our_prims;
260     } else
261     out_prims = stdprims;
262     out_scalefactor = 1;
263     sens_curve = NULL;
264     } break;
265     case 'Y': /* photopic response */
266     if (argv[i][3])
267     goto badopt;
268 greg 2.16 out_scalefactor = WHTEFFICACY;
269 greg 2.3 sens_curve = scolor_photopic;
270     break;
271     case 'S': /* scotopic response */
272     if (argv[i][3])
273     goto badopt;
274 greg 2.16 out_scalefactor = WHTSCOTOPIC;
275 greg 2.3 sens_curve = scolor_scotopic;
276     break;
277     case 'M': /* melanopic response */
278     if (argv[i][3])
279     goto badopt;
280 greg 2.16 out_scalefactor = WHTMELANOPIC;
281 greg 2.3 sens_curve = scolor_melanopic;
282 greg 2.16 break;
283     case 'A': /* radiometric average */
284     if (argv[i][3])
285     goto badopt;
286     out_scalefactor = 1;
287     sens_curve = scolor_mean;
288 greg 2.3 break;
289     default:
290     goto badopt;
291     }
292     break;
293     #if MAXCSAMP>3
294     case 'c': /* output spectral results */
295     if (argv[i][2] != 'o')
296     goto badopt;
297     rval = (out_prims == NULL) & (sens_curve == NULL);
298     check_bool(3,rval);
299     if (rval) {
300     out_prims = NULL;
301     sens_curve = NULL;
302     } else if (out_prims == NULL)
303     out_prims = stdprims;
304     break;
305     #endif
306 greg 2.1 default:
307     goto badopt;
308     }
309     }
310 greg 2.4 /* set/check spectral sampling */
311     rval = setspectrsamp(CNDX, WLPART);
312     if (rval < 0)
313     error(USER, "unsupported spectral sampling");
314 greg 2.12 if (sens_curve != NULL)
315     out_prims = NULL;
316     else if (out_prims != NULL) {
317 greg 2.4 if (!rval)
318     error(WARNING, "spectral range incompatible with color output");
319     } else if (NCSAMP == 3)
320     out_prims = stdprims; /* 3 samples do not a spectrum make */
321 greg 2.1 /* set up signal handling */
322     sigdie(SIGINT, "Interrupt");
323     #ifdef SIGHUP
324     sigdie(SIGHUP, "Hangup");
325     #endif
326     sigdie(SIGTERM, "Terminate");
327     #ifdef SIGPIPE
328     sigdie(SIGPIPE, "Broken pipe");
329     #endif
330     #ifdef SIGALRM
331     sigdie(SIGALRM, "Alarm clock");
332     #endif
333     #ifdef SIGXCPU
334     sigdie(SIGXCPU, "CPU limit exceeded");
335     sigdie(SIGXFSZ, "File size exceeded");
336     #endif
337     /* open error file */
338     if (errfile != NULL) {
339     if (freopen(errfile, "a", stderr) == NULL)
340     quit(2);
341     fprintf(stderr, "**************\n*** PID %5d: ",
342     getpid());
343     printargs(argc, argv, stderr);
344     putc('\n', stderr);
345     fflush(stderr);
346     }
347     #ifdef NICE
348     nice(NICE); /* lower priority */
349     #endif
350     /* get octree name */
351     if (i == argc)
352     error(USER, "missing octree argument");
353     if (i != argc-1)
354     goto badopt;
355     /* set output options */
356     rval = setrtoutput(outvals);
357     /* load octree */
358     if (!myRTmanager.LoadOctree(argv[i]))
359     quit(1);
360     /* set up output */
361     if (outform != 'a')
362     SET_FILE_BINARY(stdout);
363     if (doheader) { /* print header? */
364 greg 2.5 newheader("RADIANCE", stdout);
365 greg 2.9 fputs(myRTmanager.GetHeadStr(), stdout);
366 greg 2.1 printargs(i, argv, stdout);
367     printf("SOFTWARE= %s\n", VersionID);
368     fputnow(stdout);
369     if (rval > 0) /* saved from setrtoutput() call */
370 greg 2.12 fputncomp(rval, stdout);
371     if (NCSAMP > 3)
372     fputwlsplit(WLPART, stdout);
373     if ((out_prims != stdprims) & (out_prims != NULL))
374     fputprims(out_prims, stdout);
375 greg 2.1 if ((outform == 'f') | (outform == 'd'))
376     fputendian(stdout);
377     fputformat(formstr(outform), stdout);
378 greg 2.4 fputc('\n', stdout); /* end of header */
379 greg 2.1 }
380     rtrace(NULL, nproc); /* trace rays */
381     quit(0); /* clean up & exit */
382    
383     badopt:
384     sprintf(errmsg, "command line error at '%s'", argv[i]);
385     error(USER, errmsg);
386     return 1; /* pro forma return */
387    
388     #undef check
389     #undef check_bool
390     }
391    
392     void
393     wputs( /* warning output function */
394     char *s
395     )
396     {
397     int lasterrno = errno;
398     eputs(s);
399     errno = lasterrno;
400     }
401    
402     void
403     eputs( /* put string to stderr */
404 greg 2.8 const char *s
405 greg 2.1 )
406     {
407     static int midline = 0;
408    
409     if (!*s)
410     return;
411     if (!midline++) {
412     fputs(progname, stderr);
413     fputs(": ", stderr);
414     }
415     fputs(s, stderr);
416     if (s[strlen(s)-1] == '\n') {
417     fflush(stderr);
418     midline = 0;
419     }
420     }
421    
422     static void
423     onsig( /* fatal signal */
424     int signo
425     )
426     {
427     static int gotsig = 0;
428    
429     if (gotsig++) /* two signals and we're gone! */
430     _exit(signo);
431    
432     #ifdef SIGALRM
433     alarm(15); /* allow 15 seconds to clean up */
434     signal(SIGALRM, SIG_DFL); /* make certain we do die */
435     #endif
436     eputs("signal - ");
437     eputs(sigerr[signo]);
438     eputs("\n");
439     quit(3);
440     }
441    
442     static void
443     sigdie( /* set fatal signal */
444     int signo,
445     const char *msg
446     )
447     {
448     if (signal(signo, onsig) == SIG_IGN)
449     signal(signo, SIG_IGN);
450     sigerr[signo] = msg;
451     }
452    
453     static void
454     printdefaults(void) /* print default values to stdout */
455     {
456     const char *cp;
457    
458     if (myRTmanager.rtFlags & RTimmIrrad)
459     printf("-I+\t\t\t\t# immediate irradiance on\n");
460     printf("-n %-2d\t\t\t\t# number of rendering processes\n", nproc);
461     printf("-x %-9d\t\t\t# %s\n", hresolu,
462     vresolu && hresolu ? "x resolution" : "flush interval");
463     printf("-y %-9d\t\t\t# y resolution\n", vresolu);
464     printf(myRTmanager.rtFlags&RTlimDist ? "-ld+\t\t\t\t# limit distance on\n" :
465     "-ld-\t\t\t\t# limit distance off\n");
466     printf("-h%c\t\t\t\t# %s header\n", doheader ? '+' : '-',
467     doheader ? "output" : "no");
468     printf("-f%c%c\t\t\t\t# format input/output = %s/%s\n",
469     inform, outform, formstr(inform), formstr(outform));
470     printf("-o%-9s\t\t\t# output", outvals);
471     for (cp = outvals; *cp; cp++)
472     switch (*cp) {
473     case 't': case 'T': printf(" trace"); break;
474     case 'o': printf(" origin"); break;
475     case 'd': printf(" direction"); break;
476     case 'r': printf(" reflect_contrib"); break;
477     case 'R': printf(" reflect_length"); break;
478     case 'x': printf(" unreflect_contrib"); break;
479     case 'X': printf(" unreflect_length"); break;
480     case 'v': printf(" value"); break;
481     case 'V': printf(" contribution"); break;
482     case 'l': printf(" length"); break;
483     case 'L': printf(" first_length"); break;
484     case 'p': printf(" point"); break;
485     case 'n': printf(" normal"); break;
486     case 'N': printf(" unperturbed_normal"); break;
487     case 's': printf(" surface"); break;
488     case 'w': printf(" weight"); break;
489     case 'W': printf(" coefficient"); break;
490     case 'm': printf(" modifier"); break;
491     case 'M': printf(" material"); break;
492     case '~': printf(" tilde"); break;
493     }
494     putchar('\n');
495 greg 2.3 if (sens_curve == scolor_photopic)
496     printf("-pY\t\t\t\t# photopic output\n");
497     else if (sens_curve == scolor_scotopic)
498     printf("-pS\t\t\t\t# scotopic output\n");
499     else if (sens_curve == scolor_melanopic)
500     printf("-pM\t\t\t\t# melanopic output\n");
501     else if (out_prims == stdprims)
502     printf("-pRGB\t\t\t\t# standard RGB color output\n");
503     else if (out_prims == xyzprims)
504     printf("-pXYZ\t\t\t\t# CIE XYZ color output\n");
505     else if (out_prims != NULL)
506     printf("-pc %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\t# output color primaries and white point\n",
507     out_prims[RED][0], out_prims[RED][1],
508     out_prims[GRN][0], out_prims[GRN][1],
509     out_prims[BLU][0], out_prims[BLU][1],
510     out_prims[WHT][0], out_prims[WHT][1]);
511     if ((sens_curve == NULL) & (NCSAMP > 3))
512     printf(out_prims != NULL ? "-co-\t\t\t\t# output tristimulus colors\n" :
513     "-co+\t\t\t\t# output spectral values\n");
514 greg 2.1 printf(erract[WARNING].pf != NULL ?
515     "-w+\t\t\t\t# warning messages on\n" :
516     "-w-\t\t\t\t# warning messages off\n");
517     print_rdefaults();
518     }