| 35 |  |  | 
| 36 |  | int  nproc = 1;                         /* number of processes */ | 
| 37 |  |  | 
| 38 | < | extern char  *formstr();                /* string from format */ | 
| 38 | > | extern int  setrtoutput(void);          /* set output values */ | 
| 39 | > |  | 
| 40 |  | int  inform = 'a';                      /* input format */ | 
| 41 |  | int  outform = 'a';                     /* output format */ | 
| 42 |  | char  *outvals = "v";                   /* output specification */ | 
| 44 |  | int  hresolu = 0;                       /* horizontal (scan) size */ | 
| 45 |  | int  vresolu = 0;                       /* vertical resolution */ | 
| 46 |  |  | 
| 47 | + | extern int  castonly;                   /* only doing ray-casting? */ | 
| 48 | + |  | 
| 49 |  | int  imm_irrad = 0;                     /* compute immediate irradiance? */ | 
| 50 |  | int  lim_dist = 0;                      /* limit distance? */ | 
| 51 |  |  | 
| 59 |  | char  *tralist[MAXMODLIST];             /* list of modifers to trace (or no) */ | 
| 60 |  | int  traincl = -1;                      /* include == 1, exclude == 0 */ | 
| 61 |  |  | 
| 62 | + | double  (*sens_curve)(SCOLOR scol) = NULL;      /* spectral conversion for 1-channel */ | 
| 63 | + | double  out_scalefactor = 1;            /* output calibration scale factor */ | 
| 64 | + | RGBPRIMP  out_prims = stdprims;         /* output color primitives (NULL if spectral) */ | 
| 65 | + | static RGBPRIMS  our_prims;             /* private output color primitives */ | 
| 66 | + |  | 
| 67 |  | static int  loadflags = ~IO_FILES;      /* what to load from octree */ | 
| 68 |  |  | 
| 69 |  | static void onsig(int  signo); | 
| 70 |  | static void sigdie(int  signo, char  *msg); | 
| 71 |  | static void printdefaults(void); | 
| 72 |  |  | 
| 73 | + | #ifdef PERSIST | 
| 74 | + | #define RTRACE_FEATURES "Persist\nParallelPersist\nMultiprocessing\n" \ | 
| 75 | + | "IrradianceCalc\nImmediateIrradiance\nDistanceLimiting\n" \ | 
| 76 | + | "ParticipatingMedia=Mist\n" \ | 
| 77 | + | "HessianAmbientCache\nAmbientAveraging\n" \ | 
| 78 | + | "AmbientValueSharing\nAdaptiveShadowTesting\n" \ | 
| 79 | + | "InputFormats=a,f,d\nOutputFormats=a,f,d,c\n" \ | 
| 80 | + | "Outputs=o,d,v,V,w,W,l,L,c,p,n,N,s,m,M,r,x,R,X,~\n" | 
| 81 | + | #else | 
| 82 | + | #define RTRACE_FEATURES "IrradianceCalc\nIrradianceCalc\nDistanceLimiting\n" \ | 
| 83 | + | "ParticipatingMedia=Mist\n" \ | 
| 84 | + | "HessianAmbientCache\nAmbientAveraging\n" \ | 
| 85 | + | "AmbientValueSharing\nAdaptiveShadowTesting\n" \ | 
| 86 | + | "InputFormats=a,f,d\nOutputFormats=a,f,d,c\n" \ | 
| 87 | + | "Outputs=o,d,v,V,w,W,l,L,c,p,n,N,s,m,M,r,x,R,X,~\n" | 
| 88 | + | #endif | 
| 89 |  |  | 
| 90 | + |  | 
| 91 |  | int | 
| 92 |  | main(int  argc, char  *argv[]) | 
| 93 |  | { | 
| 94 |  | #define  check(ol,al)           if (argv[i][ol] || \ | 
| 95 |  | badarg(argc-i-1,argv+i+1,al)) \ | 
| 96 |  | goto badopt | 
| 97 | < | #define  bool(olen,var)         switch (argv[i][olen]) { \ | 
| 97 | > | #define  check_bool(olen,var)           switch (argv[i][olen]) { \ | 
| 98 |  | case '\0': var = !var; break; \ | 
| 99 |  | case 'y': case 'Y': case 't': case 'T': \ | 
| 100 |  | case '+': case '1': var = 1; break; \ | 
| 101 |  | case 'n': case 'N': case 'f': case 'F': \ | 
| 102 |  | case '-': case '0': var = 0; break; \ | 
| 103 |  | default: goto badopt; } | 
| 104 | + | extern char  *octname; | 
| 105 |  | int  persist = 0; | 
| 106 |  | char  *octnm = NULL; | 
| 107 |  | char  **tralp = NULL; | 
| 110 |  | int  i; | 
| 111 |  | /* global program name */ | 
| 112 |  | progname = argv[0] = fixargv0(argv[0]); | 
| 113 | + | /* feature check only? */ | 
| 114 | + | strcat(RFeatureList, RTRACE_FEATURES); | 
| 115 | + | if (argc > 1 && !strcmp(argv[1], "-features")) | 
| 116 | + | return feature_status(argc-2, argv+2); | 
| 117 |  | /* add trace notify function */ | 
| 118 |  | for (i = 0; addobjnotify[i] != NULL; i++) | 
| 119 |  | ; | 
| 120 |  | addobjnotify[i] = tranotify; | 
| 91 | – | /* set our defaults */ | 
| 92 | – | rand_samp = 1; | 
| 93 | – | maxdepth = -10; | 
| 94 | – | minweight = 2e-3; | 
| 121 |  | /* option city */ | 
| 122 |  | for (i = 1; i < argc; i++) { | 
| 123 |  | /* expand arguments */ | 
| 158 |  | check(2,"i"); | 
| 159 |  | vresolu = atoi(argv[++i]); | 
| 160 |  | break; | 
| 161 | < | case 'w':                               /* warnings */ | 
| 161 | > | case 'w':                               /* warnings & spectral */ | 
| 162 |  | rval = erract[WARNING].pf != NULL; | 
| 163 | < | bool(2,rval); | 
| 163 | > | check_bool(2,rval); | 
| 164 |  | if (rval) erract[WARNING].pf = wputs; | 
| 165 |  | else erract[WARNING].pf = NULL; | 
| 166 |  | break; | 
| 171 |  | case 'l':                               /* limit distance */ | 
| 172 |  | if (argv[i][2] != 'd') | 
| 173 |  | goto badopt; | 
| 174 | < | bool(3,lim_dist); | 
| 174 | > | check_bool(3,lim_dist); | 
| 175 |  | break; | 
| 176 |  | case 'I':                               /* immed. irradiance */ | 
| 177 | < | bool(2,imm_irrad); | 
| 177 | > | check_bool(2,imm_irrad); | 
| 178 |  | break; | 
| 179 |  | case 'f':                               /* format i/o */ | 
| 180 |  | switch (argv[i][2]) { | 
| 206 |  | break; | 
| 207 |  | case 'h':                               /* header output */ | 
| 208 |  | rval = loadflags & IO_INFO; | 
| 209 | < | bool(2,rval); | 
| 209 | > | check_bool(2,rval); | 
| 210 |  | loadflags = rval ? loadflags | IO_INFO : | 
| 211 |  | loadflags & ~IO_INFO; | 
| 212 |  | break; | 
| 220 |  | tralp = tralist; | 
| 221 |  | } | 
| 222 |  | if (argv[i][2] == 'I') {        /* file */ | 
| 223 | < | rval = wordfile(tralp, | 
| 223 | > | rval = wordfile(tralp, MAXMODLIST-(tralp-tralist), | 
| 224 |  | getpath(argv[++i],getrlibpath(),R_OK)); | 
| 225 |  | if (rval < 0) { | 
| 226 |  | sprintf(errmsg, | 
| 242 |  | tralp = tralist; | 
| 243 |  | } | 
| 244 |  | if (argv[i][2] == 'E') {        /* file */ | 
| 245 | < | rval = wordfile(tralp, | 
| 245 | > | rval = wordfile(tralp, MAXMODLIST-(tralp-tralist), | 
| 246 |  | getpath(argv[++i],getrlibpath(),R_OK)); | 
| 247 |  | if (rval < 0) { | 
| 248 |  | sprintf(errmsg, | 
| 260 |  | goto badopt; | 
| 261 |  | } | 
| 262 |  | break; | 
| 263 | + | case 'p':                               /* value output */ | 
| 264 | + | switch (argv[i][2]) { | 
| 265 | + | case 'R':                       /* standard RGB output */ | 
| 266 | + | if (strcmp(argv[i]+2, "RGB")) | 
| 267 | + | goto badopt; | 
| 268 | + | out_prims = stdprims; | 
| 269 | + | out_scalefactor = 1; | 
| 270 | + | sens_curve = NULL; | 
| 271 | + | break; | 
| 272 | + | case 'X':                       /* XYZ output */ | 
| 273 | + | if (strcmp(argv[i]+2, "XYZ")) | 
| 274 | + | goto badopt; | 
| 275 | + | out_prims = xyzprims; | 
| 276 | + | out_scalefactor = WHTEFFICACY; | 
| 277 | + | sens_curve = NULL; | 
| 278 | + | break; | 
| 279 | + | case 'c': { | 
| 280 | + | int     j; | 
| 281 | + | check(3,"ffffffff"); | 
| 282 | + | rval = 0; | 
| 283 | + | for (j = 0; j < 8; j++) { | 
| 284 | + | our_prims[0][j] = atof(argv[++i]); | 
| 285 | + | rval |= fabs(our_prims[0][j]-stdprims[0][j]) > .001; | 
| 286 | + | } | 
| 287 | + | if (rval) { | 
| 288 | + | if (!colorprimsOK(our_prims)) | 
| 289 | + | error(USER, "illegal primary chromaticities"); | 
| 290 | + | out_prims = our_prims; | 
| 291 | + | } else | 
| 292 | + | out_prims = stdprims; | 
| 293 | + | out_scalefactor = 1; | 
| 294 | + | sens_curve = NULL; | 
| 295 | + | } break; | 
| 296 | + | case 'Y':                       /* photopic response */ | 
| 297 | + | sens_curve = scolor_photopic; | 
| 298 | + | out_scalefactor = WHTEFFICACY; | 
| 299 | + | break; | 
| 300 | + | case 'S':                       /* scotopic response */ | 
| 301 | + | sens_curve = scolor_scotopic; | 
| 302 | + | out_scalefactor = WHTSCOTOPIC; | 
| 303 | + | break; | 
| 304 | + | case 'M':                       /* melanopic response */ | 
| 305 | + | sens_curve = scolor_melanopic; | 
| 306 | + | out_scalefactor = WHTMELANOPIC; | 
| 307 | + | break; | 
| 308 | + | default: | 
| 309 | + | goto badopt; | 
| 310 | + | } | 
| 311 | + | break; | 
| 312 | + | #if MAXCSAMP>3 | 
| 313 | + | case 'c':                               /* output spectral results */ | 
| 314 | + | if (argv[i][2] != 'o') | 
| 315 | + | goto badopt; | 
| 316 | + | rval = (out_prims == NULL); | 
| 317 | + | check_bool(3,rval); | 
| 318 | + | if (rval) out_prims = NULL; | 
| 319 | + | else if (out_prims == NULL) out_prims = stdprims; | 
| 320 | + | break; | 
| 321 | + | #endif | 
| 322 |  | #ifdef  PERSIST | 
| 323 |  | case 'P':                               /* persist file */ | 
| 324 |  | if (argv[i][2] == 'P') { | 
| 335 |  | goto badopt; | 
| 336 |  | } | 
| 337 |  | } | 
| 338 | < | if (nproc > 1) { | 
| 339 | < | if (persist) | 
| 340 | < | error(USER, "multiprocessing incompatible with persist file"); | 
| 341 | < | if (!vresolu && hresolu > 0 && hresolu < nproc) | 
| 342 | < | error(WARNING, "number of cores should not exceed horizontal resolution"); | 
| 343 | < | if (trace != NULL) | 
| 344 | < | error(WARNING, "multiprocessing does not work properly with trace mode"); | 
| 345 | < | } | 
| 338 | > | /* set/check spectral sampling */ | 
| 339 | > | rval = setspectrsamp(CNDX, WLPART); | 
| 340 | > | if (rval < 0) | 
| 341 | > | error(USER, "unsupported spectral sampling"); | 
| 342 | > | if (out_prims != NULL) { | 
| 343 | > | if (!rval) | 
| 344 | > | error(WARNING, "spectral range incompatible with color output"); | 
| 345 | > | } else if (NCSAMP == 3) | 
| 346 | > | out_prims = stdprims;   /* 3 samples do not a spectrum make */ | 
| 347 | > | if (nproc > 1 && persist) | 
| 348 | > | error(USER, "multiprocessing incompatible with persist file"); | 
| 349 |  | /* initialize object types */ | 
| 350 |  | initotypes(); | 
| 351 |  | /* initialize urand */ | 
| 403 |  | #endif | 
| 404 |  | if (outform != 'a') | 
| 405 |  | SET_FILE_BINARY(stdout); | 
| 406 | < | readoct(octname = octnm, loadflags, &thescene, NULL); | 
| 406 | > | rval = setrtoutput(); | 
| 407 | > | octname = savqstr(octnm); | 
| 408 | > | readoct(octname, loadflags, &thescene, NULL); | 
| 409 |  | nsceneobjs = nobjects; | 
| 410 |  |  | 
| 411 |  | if (loadflags & IO_INFO) {      /* print header */ | 
| 412 |  | printargs(i, argv, stdout); | 
| 413 |  | printf("SOFTWARE= %s\n", VersionID); | 
| 414 |  | fputnow(stdout); | 
| 415 | + | if (rval > 0)           /* saved from setrtoutput() call */ | 
| 416 | + | fputncomp(rval, stdout); | 
| 417 | + | if (NCSAMP > 3) | 
| 418 | + | fputwlsplit(WLPART, stdout); | 
| 419 | + | if ((out_prims != stdprims) & (out_prims != NULL)) | 
| 420 | + | fputprims(out_prims, stdout); | 
| 421 | + | if ((outform == 'f') | (outform == 'd')) | 
| 422 | + | fputendian(stdout); | 
| 423 |  | fputformat(formstr(outform), stdout); | 
| 424 | < | putchar('\n'); | 
| 424 | > | fputc('\n', stdout);    /* end of header */ | 
| 425 |  | } | 
| 328 | – |  | 
| 329 | – | ray_init_pmap();     /* PMAP: set up & load photon maps */ | 
| 330 | – |  | 
| 331 | – | marksources();                  /* find and mark sources */ | 
| 426 |  |  | 
| 427 | < | setambient();                   /* initialize ambient calculation */ | 
| 428 | < |  | 
| 427 | > | if (!castonly) {        /* any actual ray traversal to do? */ | 
| 428 | > |  | 
| 429 | > | ray_init_pmap();        /* PMAP: set up & load photon maps */ | 
| 430 | > |  | 
| 431 | > | marksources();          /* find and mark sources */ | 
| 432 | > |  | 
| 433 | > | setambient();           /* initialize ambient calculation */ | 
| 434 | > | } else | 
| 435 | > | distantsources();       /* else mark only distant sources */ | 
| 436 | > |  | 
| 437 | > | fflush(stdout);                 /* in case we're duplicating header */ | 
| 438 | > |  | 
| 439 |  | #ifdef  PERSIST | 
| 440 |  | if (persist) { | 
| 337 | – | fflush(stdout); | 
| 441 |  | /* reconnect stdout */ | 
| 442 |  | dup2(duped1, fileno(stdout)); | 
| 443 |  | close(duped1); | 
| 491 |  | return 1; /* pro forma return */ | 
| 492 |  |  | 
| 493 |  | #undef  check | 
| 494 | < | #undef  bool | 
| 494 | > | #undef  check_bool | 
| 495 |  | } | 
| 496 |  |  | 
| 497 |  |  | 
| 498 |  | void | 
| 499 |  | wputs(                          /* warning output function */ | 
| 500 | < | char    *s | 
| 500 | > | const char      *s | 
| 501 |  | ) | 
| 502 |  | { | 
| 503 |  | int  lasterrno = errno; | 
| 508 |  |  | 
| 509 |  | void | 
| 510 |  | eputs(                          /* put string to stderr */ | 
| 511 | < | register char  *s | 
| 511 | > | const char  *s | 
| 512 |  | ) | 
| 513 |  | { | 
| 514 |  | static int  midline = 0; | 
| 563 |  | static void | 
| 564 |  | printdefaults(void)                     /* print default values to stdout */ | 
| 565 |  | { | 
| 566 | < | register char  *cp; | 
| 566 | > | char  *cp; | 
| 567 |  |  | 
| 568 |  | if (imm_irrad) | 
| 569 |  | printf("-I+\t\t\t\t# immediate irradiance on\n"); | 
| 573 |  | printf("-y %-9d\t\t\t# y resolution\n", vresolu); | 
| 574 |  | printf(lim_dist ? "-ld+\t\t\t\t# limit distance on\n" : | 
| 575 |  | "-ld-\t\t\t\t# limit distance off\n"); | 
| 576 | < | printf("-h%c\t\t\t\t# %s header\n", loadflags & IO_INFO ? '+' : '-', | 
| 577 | < | loadflags & IO_INFO ? "output" : "no"); | 
| 576 | > | printf(loadflags & IO_INFO ? "-h+\t\t\t\t# output header\n" : | 
| 577 | > | "-h-\t\t\t\t# no header\n"); | 
| 578 |  | printf("-f%c%c\t\t\t\t# format input/output = %s/%s\n", | 
| 579 |  | inform, outform, formstr(inform), formstr(outform)); | 
| 580 |  | printf("-o%-9s\t\t\t# output", outvals); | 
| 583 |  | case 't': case 'T': printf(" trace"); break; | 
| 584 |  | case 'o': printf(" origin"); break; | 
| 585 |  | case 'd': printf(" direction"); break; | 
| 586 | + | case 'r': printf(" reflect_contrib"); break; | 
| 587 | + | case 'R': printf(" reflect_length"); break; | 
| 588 | + | case 'x': printf(" unreflect_contrib"); break; | 
| 589 | + | case 'X': printf(" unreflect_length"); break; | 
| 590 |  | case 'v': printf(" value"); break; | 
| 591 |  | case 'V': printf(" contribution"); break; | 
| 592 |  | case 'l': printf(" length"); break; | 
| 599 |  | case 'W': printf(" coefficient"); break; | 
| 600 |  | case 'm': printf(" modifier"); break; | 
| 601 |  | case 'M': printf(" material"); break; | 
| 602 | < | case '-': printf(" stroke"); break; | 
| 602 | > | case '~': printf(" tilde"); break; | 
| 603 |  | } | 
| 604 | < | putchar('\n'); | 
| 604 | > | fputc('\n', stdout); | 
| 605 | > | if (NCSAMP > 3) | 
| 606 | > | printf(out_prims != NULL ? "-co-\t\t\t\t# output tristimulus colors\n" : | 
| 607 | > | "-co+\t\t\t\t# output spectral values\n"); | 
| 608 | > | if (sens_curve == scolor_photopic) | 
| 609 | > | printf("-pY\t\t\t\t# photopic output\n"); | 
| 610 | > | else if (sens_curve == scolor_scotopic) | 
| 611 | > | printf("-pS\t\t\t\t# scotopic output\n"); | 
| 612 | > | else if (sens_curve == scolor_melanopic) | 
| 613 | > | printf("-pM\t\t\t\t# melanopic output\n"); | 
| 614 | > | else if (out_prims == stdprims) | 
| 615 | > | printf("-pRGB\t\t\t\t# standard RGB color output\n"); | 
| 616 | > | else if (out_prims == xyzprims) | 
| 617 | > | printf("-pXYZ\t\t\t\t# CIE XYZ color output\n"); | 
| 618 | > | else if (out_prims != NULL) | 
| 619 | > | printf("-pc %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\t# output color primaries and white point\n", | 
| 620 | > | out_prims[RED][0], out_prims[RED][1], | 
| 621 | > | out_prims[GRN][0], out_prims[GRN][1], | 
| 622 | > | out_prims[BLU][0], out_prims[BLU][1], | 
| 623 | > | out_prims[WHT][0], out_prims[WHT][1]); | 
| 624 |  | printf(erract[WARNING].pf != NULL ? | 
| 625 |  | "-w+\t\t\t\t# warning messages on\n" : | 
| 626 |  | "-w-\t\t\t\t# warning messages off\n"); |