--- ray/src/rt/rtrace.c 2020/07/20 15:54:29 2.99 +++ ray/src/rt/rtrace.c 2023/12/11 18:33:53 2.110 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rtrace.c,v 2.99 2020/07/20 15:54:29 greg Exp $"; +static const char RCSid[] = "$Id: rtrace.c,v 2.110 2023/12/11 18:33:53 greg Exp $"; #endif /* * rtrace.c - program and variables for individual ray tracing. @@ -45,13 +45,19 @@ extern int traincl; /* include == 1, exclude == 0 * extern int hresolu; /* horizontal resolution */ extern int vresolu; /* vertical resolution */ -int castonly = 0; /* only doing ray-casting? */ +extern int castonly; /* only doing ray-casting? */ +extern double (*sens_curve)(SCOLOR scol); /* spectral conversion for 1-channel */ +extern double out_scalefactor; /* output calibration scale factor */ +extern RGBPRIMP out_prims; /* output color primitives (NULL if spectral) */ + #ifndef MAXTSET #define MAXTSET 8191 /* maximum number in trace set */ #endif OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */ +static int Tflag = 0; /* source tracing enabled? */ + static RAY thisray; /* for our convenience */ static FILE *inpfp = NULL; /* input stream pointer */ @@ -61,7 +67,7 @@ static int inp_qpos = 0; /* next ray to return */ static int inp_qend = 0; /* number of rays in this work group */ typedef void putf_t(RREAL *v, int n); -static putf_t puta, putd, putf, putrgbe; +static putf_t puta, putd, putf; typedef void oputf_t(RAY *r); static oputf_t oputo, oputd, oputv, oputV, oputl, oputL, oputc, oputp, @@ -81,6 +87,8 @@ static double nextray(FVECT org, FVECT dir); static void tabin(RAY *r); static void ourtrace(RAY *r); +static void putscolor(COLORV *scol); + static oputf_t *ray_out[32], *every_out[32]; static putf_t *putreal; @@ -104,7 +112,7 @@ quit( /* quit program */ } -char * +const char * formstr( /* return format identifier */ int f ) @@ -113,12 +121,27 @@ formstr( /* return format identifier */ case 'a': return("ascii"); case 'f': return("float"); case 'd': return("double"); - case 'c': return(COLRFMT); + case 'c': + if (out_prims == NULL) + return(SPECFMT); + if (out_prims == xyzprims) + return(CIEFMT); + return(COLRFMT); } return("unknown"); } +static void +trace_sources(void) /* trace rays to light sources, also */ +{ + int sn; + + for (sn = 0; sn < nsources; sn++) + source[sn].sflags |= SFOLLOW; +} + + void rtrace( /* trace rays from file */ char *fname, @@ -148,21 +171,15 @@ rtrace( /* trace rays from file */ /* set up output */ if (castonly || every_out[0] != NULL) nproc = 1; /* don't bother multiprocessing */ + if (every_out[0] != NULL) { + trace = ourtrace; /* enable full tree tracing */ + if (Tflag) /* light sources, too? */ + trace_sources(); + } if ((nextflush > 0) & (nproc > nextflush)) { error(WARNING, "reducing number of processes to match flush interval"); nproc = nextflush; } - switch (outform) { - case 'a': putreal = puta; break; - case 'f': putreal = putf; break; - case 'd': putreal = putd; break; - case 'c': - if (outvals[1] || !strchr("vrx", outvals[0])) - error(USER, "color format only with -ov, -or, -ox"); - putreal = putrgbe; break; - default: - error(CONSISTENCY, "botched output format"); - } if (nproc > 1) { /* start multiprocessing */ ray_popen(nproc); ray_fifo_out = printvals; @@ -217,38 +234,41 @@ rtrace( /* trace rays from file */ } -static void -trace_sources(void) /* trace rays to light sources, also */ -{ - int sn; - - for (sn = 0; sn < nsources; sn++) - source[sn].sflags |= SFOLLOW; -} - - int setrtoutput(void) /* set up output tables, return #comp */ { char *vs = outvals; oputf_t **table = ray_out; + const int nco = (sens_curve != NULL) ? 1 : + (out_prims != NULL) ? 3 : NCSAMP; int ncomp = 0; if (!*vs) error(USER, "empty output specification"); + switch (outform) { /* make sure (*putreal)() calls someone! */ + case 'a': putreal = puta; break; + case 'f': putreal = putf; break; + case 'd': putreal = putd; break; + case 'c': + if (outvals[1] || !strchr("vrx", outvals[0])) + error(USER, "color format only with -ov, -or, -ox"); + if (nco < 3) + error(USER, "color format incompatible with -pY, -pS, -pM"); + break; + default: + error(CONSISTENCY, "botched output format"); + } castonly = 1; /* sets castonly as side-effect */ do switch (*vs) { case 'T': /* trace sources */ - if (!vs[1]) break; - trace_sources(); + Tflag++; /* fall through */ case 't': /* trace */ if (!vs[1]) break; *table = NULL; table = every_out; - trace = ourtrace; castonly = 0; break; case 'o': /* origin */ @@ -261,7 +281,7 @@ setrtoutput(void) /* set up output tables, return #c break; case 'r': /* reflected contrib. */ *table++ = oputr; - ncomp += 3; + ncomp += nco; castonly = 0; break; case 'R': /* reflected distance */ @@ -271,7 +291,7 @@ setrtoutput(void) /* set up output tables, return #c break; case 'x': /* xmit contrib. */ *table++ = oputx; - ncomp += 3; + ncomp += nco; castonly = 0; break; case 'X': /* xmit distance */ @@ -281,12 +301,12 @@ setrtoutput(void) /* set up output tables, return #c break; case 'v': /* value */ *table++ = oputv; - ncomp += 3; + ncomp += nco; castonly = 0; break; case 'V': /* contribution */ *table++ = oputV; - ncomp += 3; + ncomp += nco; castonly = 0; if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0)) error(WARNING, @@ -328,7 +348,7 @@ setrtoutput(void) /* set up output tables, return #c break; case 'W': /* coefficient */ *table++ = oputW; - ncomp += 3; + ncomp += nco; castonly = 0; if (ambounce > 0 && (ambacc > FTINY) | (ambssamp > 0)) error(WARNING, @@ -420,21 +440,22 @@ rtcompute( /* compute and print ray value(s) */ ) { /* set up ray */ - rayorigin(&thisray, PRIMARY, NULL, NULL); if (imm_irrad) { VSUM(thisray.rorg, org, dir, 1.1e-4); thisray.rdir[0] = -dir[0]; thisray.rdir[1] = -dir[1]; thisray.rdir[2] = -dir[2]; thisray.rmax = 0.0; - thisray.revf = rayirrad; } else { VCOPY(thisray.rorg, org); VCOPY(thisray.rdir, dir); thisray.rmax = dmax; - if (castonly) - thisray.revf = raycast; } + rayorigin(&thisray, PRIMARY, NULL, NULL); + if (imm_irrad) + thisray.revf = rayirrad; + else if (castonly) + thisray.revf = raycast; if (ray_pnprocs > 1) { /* multiprocessing FIFO? */ if (ray_fifo_in(&thisray) < 0) error(USER, "lost children"); @@ -687,12 +708,12 @@ oputx( /* print unmirrored contribution */ RAY *r ) { - RREAL cval[3]; + SCOLOR cdiff; - cval[0] = colval(r->rcol,RED) - colval(r->mcol,RED); - cval[1] = colval(r->rcol,GRN) - colval(r->mcol,GRN); - cval[2] = colval(r->rcol,BLU) - colval(r->mcol,BLU); - (*putreal)(cval, 3); + copyscolor(cdiff, r->rcol); + sopscolor(cdiff, -=, r->mcol); + + putscolor(cdiff); } @@ -710,12 +731,7 @@ oputv( /* print value */ RAY *r ) { - RREAL cval[3]; - - cval[0] = colval(r->rcol,RED); - cval[1] = colval(r->rcol,GRN); - cval[2] = colval(r->rcol,BLU); - (*putreal)(cval, 3); + putscolor(r->rcol); } @@ -724,11 +740,11 @@ oputV( /* print value contribution */ RAY *r ) { - RREAL contr[3]; + SCOLOR contr; raycontrib(contr, r, PRIMARY); - multcolor(contr, r->rcol); - (*putreal)(contr, 3); + smultscolor(contr, r->rcol); + putscolor(contr); } @@ -765,14 +781,11 @@ static RREAL vdummy[3] = {0.0, 0.0, 0.0}; static void -oputp( /* print point */ +oputp( /* print intersection point */ RAY *r ) { - if (r->rot < FHUGE*.99) - (*putreal)(r->rop, 3); - else - (*putreal)(vdummy, 3); + (*putreal)(r->rop, 3); /* set to ray origin if distant or no hit */ } @@ -781,17 +794,18 @@ oputN( /* print unperturbed normal */ RAY *r ) { - if (r->rot < FHUGE*.99) { - if (r->rflips & 1) { /* undo any flippin' flips */ - FVECT unrm; - unrm[0] = -r->ron[0]; - unrm[1] = -r->ron[1]; - unrm[2] = -r->ron[2]; - (*putreal)(unrm, 3); - } else - (*putreal)(r->ron, 3); - } else + if (r->ro == NULL) { /* zero vector if clipped or no hit */ (*putreal)(vdummy, 3); + return; + } + if (r->rflips & 1) { /* undo any flippin' flips */ + FVECT unrm; + unrm[0] = -r->ron[0]; + unrm[1] = -r->ron[1]; + unrm[2] = -r->ron[2]; + (*putreal)(unrm, 3); + } else + (*putreal)(r->ron, 3); } @@ -802,7 +816,7 @@ oputn( /* print perturbed normal */ { FVECT pnorm; - if (r->rot >= FHUGE*.99) { + if (r->ro == NULL) { /* clipped or no hit */ (*putreal)(vdummy, 3); return; } @@ -840,14 +854,14 @@ oputW( /* print coefficient */ RAY *r ) { - RREAL contr[3]; + SCOLOR contr; /* shadow ray not on source? */ if (r->rsrc >= 0 && source[r->rsrc].so != r->ro) - setcolor(contr, 0.0, 0.0, 0.0); + scolorblack(contr); else raycontrib(contr, r, PRIMARY); - (*putreal)(contr, 3); + putscolor(contr); } @@ -912,10 +926,10 @@ static void putd(RREAL *v, int n) /* output binary double(s) */ { #ifdef SMLFLT - double da[3]; + double da[MAXCSAMP]; int i; - if (n > 3) + if (n > MAXCSAMP) error(INTERNAL, "code error in putd()"); for (i = n; i--; ) da[i] = v[i]; @@ -930,10 +944,10 @@ static void putf(RREAL *v, int n) /* output binary float(s) */ { #ifndef SMLFLT - float fa[3]; + float fa[MAXCSAMP]; int i; - if (n > 3) + if (n > MAXCSAMP) error(INTERNAL, "code error in putf()"); for (i = n; i--; ) fa[i] = v[i]; @@ -945,12 +959,56 @@ putf(RREAL *v, int n) /* output binary float(s) */ static void -putrgbe(RREAL *v, int n) /* output RGBE color */ +putscolor(COLORV *scol) /* output (spectral) color */ { - COLR cout; - - if (n != 3) - error(INTERNAL, "putrgbe() not called with 3 components"); - setcolr(cout, v[0], v[1], v[2]); - putbinary(cout, sizeof(cout), 1, stdout); + static COLORMAT xyz2myrgbmat; + SCOLOR my_scol; + COLOR col; + /* apply scalefactor if any */ + if (out_scalefactor != 1.) { + copyscolor(my_scol, scol); + scalescolor(my_scol, out_scalefactor); + scol = my_scol; + } + if (sens_curve != NULL) { /* single channel output */ + RREAL v = (*sens_curve)(scol); + (*putreal)(&v, 1); + return; + } + if (out_prims == NULL) { /* full spectral reporting */ + if (outform == 'c') { + SCOLR sclr; + scolor_scolr(sclr, scol); + putbinary(sclr, LSCOLR, 1, stdout); + } else if (sizeof(RREAL) != sizeof(COLORV)) { + RREAL sreal[MAXCSAMP]; + int i = NCSAMP; + while (i--) sreal[i] = scol[i]; + (*putreal)(sreal, NCSAMP); + } else + (*putreal)((RREAL *)scol, NCSAMP); + return; + } + if (out_prims == xyzprims) { + scolor_cie(col, scol); + } else if (out_prims == stdprims) { + scolor_rgb(col, scol); + } else { + COLOR xyz; + if (xyz2myrgbmat[0][0] == 0) + compxyz2rgbWBmat(xyz2myrgbmat, out_prims); + scolor_cie(xyz, scol); + colortrans(col, xyz2myrgbmat, xyz); + clipgamut(col, xyz[CIEY], CGAMUT_LOWER, cblack, cwhite); + } + if (outform == 'c') { + COLR clr; + setcolr(clr, colval(col,RED), colval(col,GRN), colval(col,BLU)); + putbinary(clr, sizeof(COLR), 1, stdout); + } else if (sizeof(RREAL) != sizeof(COLORV)) { + RREAL creal[3]; + copycolor(creal, col); + (*putreal)(creal, 3); + } else + (*putreal)((RREAL *)col, 3); }