--- ray/src/rt/rtrace.c 2020/04/03 17:06:16 2.89 +++ ray/src/rt/rtrace.c 2022/04/30 15:13:42 2.104 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rtrace.c,v 2.89 2020/04/03 17:06:16 greg Exp $"; +static const char RCSid[] = "$Id: rtrace.c,v 2.104 2022/04/30 15:13:42 greg Exp $"; #endif /* * rtrace.c - program and variables for individual ray tracing. @@ -45,13 +45,15 @@ extern int traincl; /* include == 1, exclude == 0 * extern int hresolu; /* horizontal resolution */ extern int vresolu; /* vertical resolution */ -static int castonly = 0; +int castonly = 0; /* only doing ray-casting? */ #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 */ @@ -68,8 +70,8 @@ static oputf_t oputo, oputd, oputv, oputV, oputl, opu oputr, oputR, oputx, oputX, oputn, oputN, oputs, oputw, oputW, oputm, oputM, oputtilde; -static void setoutput(char *vs); extern void tranotify(OBJECT obj); +static int is_fifo(FILE *fp); static void bogusray(void); static void raycast(RAY *r); static void rayirrad(RAY *r); @@ -92,8 +94,10 @@ quit( /* quit program */ { if (ray_pnprocs > 0) /* close children if any */ ray_pclose(0); + else if (ray_pnprocs < 0) + _exit(code); /* avoid flush() in child */ #ifndef NON_POSIX - else if (!ray_pnprocs) { + else { headclean(); /* delete header file */ pfclean(); /* clean up persist files */ } @@ -117,7 +121,17 @@ formstr( /* return format identifier */ } -extern void +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, int nproc @@ -144,26 +158,17 @@ rtrace( /* trace rays from file */ if (inform != 'a') SET_FILE_BINARY(inpfp); /* set up output */ - setoutput(outvals); - if (imm_irrad) - castonly = 0; - else if (castonly) + 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[0] && (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; @@ -218,97 +223,117 @@ rtrace( /* trace rays from file */ } -static void -trace_sources(void) /* trace rays to light sources, also */ +int +setrtoutput(void) /* set up output tables, return #comp */ { - int sn; - - for (sn = 0; sn < nsources; sn++) - source[sn].sflags |= SFOLLOW; -} - - -static void -setoutput( /* set up output tables */ - char *vs -) -{ + char *vs = outvals; oputf_t **table = ray_out; + int ncomp = 0; - castonly = 1; - while (*vs) - switch (*vs++) { + 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"); + putreal = putrgbe; break; + default: + error(CONSISTENCY, "botched output format"); + } + castonly = 1; /* sets castonly as side-effect */ + do + switch (*vs) { case 'T': /* trace sources */ - if (!*vs) break; - trace_sources(); + Tflag++; /* fall through */ case 't': /* trace */ - if (!*vs) break; + if (!vs[1]) break; *table = NULL; table = every_out; - trace = ourtrace; castonly = 0; break; case 'o': /* origin */ *table++ = oputo; + ncomp += 3; break; case 'd': /* direction */ *table++ = oputd; + ncomp += 3; break; case 'r': /* reflected contrib. */ *table++ = oputr; + ncomp += 3; castonly = 0; break; case 'R': /* reflected distance */ *table++ = oputR; + ncomp++; castonly = 0; break; case 'x': /* xmit contrib. */ *table++ = oputx; + ncomp += 3; castonly = 0; break; case 'X': /* xmit distance */ *table++ = oputX; + ncomp++; castonly = 0; break; case 'v': /* value */ *table++ = oputv; + ncomp += 3; castonly = 0; break; case 'V': /* contribution */ *table++ = oputV; + ncomp += 3; + castonly = 0; if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0)) error(WARNING, "-otV accuracy depends on -aa 0 -as 0"); break; case 'l': /* effective distance */ *table++ = oputl; + ncomp++; castonly = 0; break; case 'c': /* local coordinates */ *table++ = oputc; + ncomp += 2; break; case 'L': /* single ray length */ *table++ = oputL; + ncomp++; break; case 'p': /* point */ *table++ = oputp; + ncomp += 3; break; case 'n': /* perturbed normal */ *table++ = oputn; + ncomp += 3; castonly = 0; break; case 'N': /* unperturbed normal */ *table++ = oputN; + ncomp += 3; break; case 's': /* surface */ *table++ = oputs; + ncomp++; break; case 'w': /* weight */ *table++ = oputw; + ncomp++; break; case 'W': /* coefficient */ *table++ = oputW; + ncomp += 3; castonly = 0; if (ambounce > 0 && (ambacc > FTINY) | (ambssamp > 0)) error(WARNING, @@ -316,16 +341,27 @@ setoutput( /* set up output tables */ break; case 'm': /* modifier */ *table++ = oputm; + ncomp++; break; case 'M': /* material */ *table++ = oputM; + ncomp++; break; case '~': /* tilde */ *table++ = oputtilde; break; + default: + sprintf(errmsg, "unrecognized output option '%c'", *vs); + error(USER, errmsg); } + while (*++vs); + *table = NULL; + if (*every_out != NULL) + ncomp = 0; /* compatibility */ + if ((do_irrad | imm_irrad) && castonly) + error(USER, "-I+ and -i+ options require some value output"); for (table = ray_out; *table != NULL; table++) { if ((*table == oputV) | (*table == oputW)) error(WARNING, "-oVW options require trace mode"); @@ -334,6 +370,7 @@ setoutput( /* set up output tables */ (*table == oputx) | (*table == oputX)) error(WARNING, "-orRxX options incompatible with -I+ and -i+"); } + return(ncomp); } @@ -388,21 +425,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"); @@ -432,6 +470,23 @@ printvals( /* print requested ray values */ static int +is_fifo( /* check if file pointer connected to pipe */ + FILE *fp +) +{ +#ifdef S_ISFIFO + struct stat sbuf; + + if (fstat(fileno(fp), &sbuf) < 0) + error(SYSTEM, "fstat() failed on input stream"); + return(S_ISFIFO(sbuf.st_mode)); +#else + return (fp == stdin); /* just a guess, really */ +#endif +} + + +static int getvec( /* get a vector from fp */ FVECT vec, int fmt, @@ -495,7 +550,8 @@ nextray( /* return next ray in work group (-1.0 if EO int rsiz = 6*20; /* conservative ascii ray size */ if (inform == 'f') rsiz = 6*sizeof(float); else if (inform == 'd') rsiz = 6*sizeof(double); - if ((inpfp == stdin) & (qlength*rsiz > 512)) /* pipe limit */ + /* check against pipe limit */ + if (qlength*rsiz > 512 && is_fifo(inpfp)) inp_queue = (FVECT *)malloc(sizeof(FVECT)*2*qlength); inp_qend = -(inp_queue == NULL); /* flag for no queue */ } @@ -715,14 +771,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 */ } @@ -731,17 +784,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); } @@ -752,7 +806,7 @@ oputn( /* print perturbed normal */ { FVECT pnorm; - if (r->rot >= FHUGE*.99) { + if (r->ro == NULL) { /* clipped or no hit */ (*putreal)(vdummy, 3); return; }