--- ray/src/util/rtcontrib.c 2007/11/17 06:21:28 1.46 +++ ray/src/util/rtcontrib.c 2011/04/09 18:05:18 1.63 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rtcontrib.c,v 1.46 2007/11/17 06:21:28 greg Exp $"; +static const char RCSid[] = "$Id: rtcontrib.c,v 1.63 2011/04/09 18:05:18 greg Exp $"; #endif /* * Gather rtrace output to compute contributions from particular sources @@ -20,7 +20,7 @@ static const char RCSid[] = "$Id: rtcontrib.c,v 1.46 2 #define MAXMODLIST 1024 /* maximum modifiers we'll track */ #endif -int treebufsiz = BUFSIZ; /* current tree buffer size */ +size_t treebufsiz = BUFSIZ; /* current tree buffer size */ typedef double DCOLOR[3]; /* double-precision color */ @@ -92,14 +92,14 @@ struct rtproc { struct rtproc *next; /* next in list of processes */ SUBPROC pd; /* rtrace pipe descriptors */ unsigned long raynum; /* ray number for this tree */ - int bsiz; /* ray tree buffer length */ + size_t bsiz; /* ray tree buffer length */ char *buf; /* ray tree buffer */ - int nbr; /* number of bytes from rtrace */ + size_t nbr; /* number of bytes from rtrace */ }; /* rtrace process buffer */ /* rtrace command and defaults */ char *rtargv[256+2*MAXMODLIST] = { "rtrace", - "-dj", ".5", "-dr", "3", + "-dj", ".9", "-dr", "3", "-ab", "1", "-ad", "350", }; int rtargc = 9; @@ -107,8 +107,8 @@ int rtargc = 9; char *myrtopts[] = { "-h-", "-x", "1", "-y", "0", "-dt", "0", "-as", "0", "-aa", "0", NULL }; -#define RTCOEFF "-o~~TmWdp" /* compute coefficients only */ -#define RTCONTRIB "-o~~TmVdp" /* compute ray contributions */ +#define RTCOEFF "-o~~~TmWdp" /* compute coefficients only */ +#define RTCONTRIB "-o~~~TmVdp" /* compute ray contributions */ struct rtproc rt0; /* head of rtrace process list */ @@ -131,12 +131,13 @@ int inpfmt = 'a'; /* input format */ int outfmt = 'a'; /* output format */ int header = 1; /* output header? */ -int accumulate = 0; /* accumulate ray values? */ int force_open = 0; /* truncate existing output? */ int recover = 0; /* recover previous output? */ +int accumulate = 1; /* input rays per output record */ int xres = 0; /* horiz. output resolution */ int yres = 0; /* vert. output resolution */ +int account; /* current accumulation count */ unsigned long raysleft; /* number of rays left to trace */ long waitflush; /* how long until next flush */ @@ -166,7 +167,7 @@ void process_queue(void); void put_contrib(const DCOLOR cnt, FILE *fout); void add_contrib(const char *modn); -void done_contrib(void); +void done_contrib(int navg); /* return number of open rtrace processes */ static int @@ -245,7 +246,7 @@ main(int argc, char *argv[]) while ((j = expandarg(&argc, &argv, i)) > 0) ; if (j < 0) { - fprintf(stderr, "%s: cannot expand '%s'", + fprintf(stderr, "%s: cannot expand '%s'\n", argv[0], argv[i]); exit(1); } @@ -274,23 +275,10 @@ main(int argc, char *argv[]) continue; } break; - case 'c': /* accumulate ray values */ - switch (argv[i][2]) { - case '\0': - accumulate = !accumulate; - continue; - case '+': case '1': - case 'T': case 't': - case 'Y': case 'y': - accumulate = 1; - continue; - case '-': case '0': - case 'F': case 'f': - case 'N': case 'n': - accumulate = 0; - continue; - } - break; + case 'c': /* input rays per output */ + if (argv[i][2] || i >= argc-2) break; + accumulate = atoi(argv[++i]); + continue; case 'r': /* recover output */ if (argv[i][2]) break; recover = 1; @@ -352,7 +340,7 @@ main(int argc, char *argv[]) case 'b': /* bin expression/count */ if (i >= argc-2) break; if (argv[i][2] == 'n') { - bincnt = atoi(argv[++i]); + bincnt = (int)(eval(argv[++i]) + .5); continue; } if (argv[i][2]) break; @@ -380,7 +368,7 @@ main(int argc, char *argv[]) } rtargv[rtargc++] = argv[i]; /* assume rtrace option */ } - if (accumulate) /* no output flushing for single record */ + if (accumulate <= 0) /* no output flushing for single record */ xres = yres = 0; /* set global argument list */ gargc = argc; gargv = argv; @@ -390,15 +378,16 @@ main(int argc, char *argv[]) rtargv[rtargc++] = contrib ? RTCONTRIB : RTCOEFF; /* just asking for defaults? */ if (!strcmp(argv[i], "-defaults")) { - char sxres[16], syres[16]; + char nps[8], sxres[16], syres[16]; char *rtpath; - printf("-n %-2d\t\t\t\t# number of processes\n", nprocs); + printf("-c %-5d\t\t\t# accumulated rays per record\n", + accumulate); printf("-V%c\t\t\t\t# output %s\n", contrib ? '+' : '-', contrib ? "contributions" : "coefficients"); - printf("-c%c\t\t\t\t# %s\n", accumulate ? '+' : '-', - accumulate ? "accumulate ray values" : - "one output record per ray"); fflush(stdout); /* report OUR options */ + rtargv[rtargc++] = "-n"; + sprintf(nps, "%d", nprocs); + rtargv[rtargc++] = nps; rtargv[rtargc++] = header ? "-h+" : "-h-"; sprintf(fmt, "-f%c%c", inpfmt, outfmt); rtargv[rtargc++] = fmt; @@ -554,11 +543,13 @@ init(int np) raysleft = yres; } else raysleft = 0; - waitflush = xres; + if ((account = accumulate) > 0) + raysleft *= accumulate; + waitflush = (yres > 0) & (xres > 1) ? 0 : xres; if (!recover) return; /* recover previous values */ - if (accumulate) + if (accumulate <= 0) reload_output(); else recover_output(stdin); @@ -591,7 +582,7 @@ addmodifier(char *modn, char *outf, char *binv, int bi error(USER, errmsg); } if (nmods >= MAXMODLIST) - error(USER, "too many modifiers"); + error(INTERNAL, "too many modifiers"); modname[nmods++] = modn; /* XXX assumes static string */ lep->key = modn; /* XXX assumes static string */ mp = (MODCONT *)malloc(sizeof(MODCONT)); @@ -599,15 +590,20 @@ addmodifier(char *modn, char *outf, char *binv, int bi error(SYSTEM, "out of memory in addmodifier"); mp->outspec = outf; /* XXX assumes static string */ mp->modname = modn; /* XXX assumes static string */ - if (binv != NULL) - mp->binv = eparse(binv); - else - mp->binv = eparse("0"); - mp->nbins = 1; + if (binv == NULL) + binv = "0"; /* use single bin if unspecified */ + mp->binv = eparse(binv); + if (mp->binv->type == NUM) { /* check value if constant */ + bincnt = (int)(evalue(mp->binv) + 1.5); + if (bincnt != 1) { + sprintf(errmsg, "illegal non-zero constant for bin (%s)", + binv); + error(USER, errmsg); + } + } + mp->nbins = 1; /* initialize results holder */ setcolor(mp->cbin[0], 0., 0., 0.); - if (mp->binv->type == NUM) /* assume one bin if constant */ - bincnt = 1; - else if (bincnt > 1) + if (bincnt > 1) mp = growmodifier(mp, bincnt); lep->data = (char *)mp; /* allocate output streams */ @@ -670,6 +666,10 @@ ofname(char *oname, const char *ospec, const char *mna mnp = cp; break; case 'd': + case 'i': + case 'o': + case 'x': + case 'X': if (bnp != NULL) return -1; bnp = cp; @@ -702,12 +702,19 @@ void printheader(FILE *fout, const char *info) { extern char VersionID[]; - FILE *fin = fopen(octree, "r"); - - if (fin == NULL) - quit(1); - checkheader(fin, "ignore", fout); /* copy octree header */ - fclose(fin); + /* copy octree header */ + if (octree[0] == '!') { + newheader("RADIANCE", fout); + fputs(octree+1, fout); + if (octree[strlen(octree)-1] != '\n') + fputc('\n', fout); + } else { + FILE *fin = fopen(octree, "r"); + if (fin == NULL) + quit(1); + checkheader(fin, "ignore", fout); + fclose(fin); + } printargs(gargc-1, gargv, fout); /* add our command */ fprintf(fout, "SOFTWARE= %s\n", VersionID); fputnow(fout); @@ -736,8 +743,6 @@ printresolu(FILE *fout, int xr, int yr) { if ((xr > 0) & (yr > 0)) /* resolution string */ fprtresolu(xr, yr, fout); - if (xres > 0) /* global flush flag */ - fflush(fout); } /* Get output stream pointer (open and write header if new and noopen==0) */ @@ -758,6 +763,8 @@ getostream(const char *ospec, const char *mname, int b if (header) printheader(stdout, NULL); printresolu(stdout, xres, yres); + if (waitflush > 0) + fflush(stdout); stdos.xr = xres; stdos.yr = yres; using_stdout = 1; } @@ -813,9 +820,12 @@ getostream(const char *ospec, const char *mname, int b *cp = '\0'; printheader(sop->ofp, info); } + if (accumulate > 0) { /* global resolution */ + sop->xr = xres; sop->yr = yres; + } printresolu(sop->ofp, sop->xr, sop->yr); /* play catch-up */ - for (i = accumulate ? 0 : lastdone; i--; ) { + for (i = accumulate > 0 ? lastdone/accumulate : 0; i--; ) { int j = sop->reclen; if (j <= 0) j = 1; while (j--) @@ -823,7 +833,7 @@ getostream(const char *ospec, const char *mname, int b if (outfmt == 'a') putc('\n', sop->ofp); } - if (xres > 0) + if (waitflush > 0) fflush(sop->ofp); } sop->reclen += noopen; /* add to length if noopen */ @@ -957,14 +967,21 @@ put_contrib(const DCOLOR cnt, FILE *fout) /* output ray tallies and clear for next accumulation */ void -done_contrib(void) +done_contrib(int navg) { + double sf = 1.; int i, j; MODCONT *mp; STREAMOUT *sop; + /* set average scaling */ + if (navg > 1) + sf = 1. / (double)navg; /* output modifiers in order */ for (i = 0; i < nmods; i++) { mp = (MODCONT *)lu_find(&modconttab,modname[i])->data; + if (navg > 1) /* average scaling */ + for (j = mp->nbins; j--; ) + scalecolor(mp->cbin[j], sf); sop = getostream(mp->outspec, mp->modname, 0,0); put_contrib(mp->cbin[0], sop->ofp); if (mp->nbins > 3 && /* minor optimization */ @@ -983,7 +1000,7 @@ done_contrib(void) if (using_stdout & (outfmt == 'a')) putc('\n', stdout); if (!waitflush) { - waitflush = xres; + waitflush = (yres > 0) & (xres > 1) ? 0 : xres; if (using_stdout) fflush(stdout); } @@ -1048,8 +1065,9 @@ process_queue(void) cp += sizeof(float)*9; n -= sizeof(float)*9; add_contrib(modname); } - if (!accumulate) - done_contrib(); /* sum up contributions & output */ + /* time to produce record? */ + if (account > 0 && !--account) + done_contrib(account = accumulate); lastdone = rtp->raynum; if (rtp->buf != NULL) /* free up buffer space */ free(rtp->buf); @@ -1064,7 +1082,7 @@ wait_rproc(void) { struct rtproc *rtfree = NULL; fd_set readset, errset; - int nr; + ssize_t nr; struct rtproc *rt; int n; @@ -1095,7 +1113,7 @@ wait_rproc(void) continue; if (rt->buf == NULL) { rt->bsiz = treebufsiz; - rt->buf = (char *)malloc(treebufsiz); + rt->buf = (char *)malloc(rt->bsiz); } else if (rt->nbr + BUFSIZ > rt->bsiz) { if (rt->bsiz + BUFSIZ <= treebufsiz) rt->bsiz = treebufsiz; @@ -1109,9 +1127,9 @@ wait_rproc(void) if (nr <= 0) error(USER, "rtrace process died"); rt->nbr += nr; /* advance & check */ - if (rt->nbr >= 4 && !memcmp(rt->buf+rt->nbr-4, - "~\t~\t", 4)) { - rt->nbr -= 4; /* elide terminator */ + if (rt->nbr >= 6 && !memcmp(rt->buf+rt->nbr-6, + "~\t~\t~\t", 6)) { + rt->nbr -= 6; /* elide terminator */ queue_raytree(rt); rtfree = rt; /* ready for next ray */ } @@ -1136,27 +1154,33 @@ get_rproc(void) void trace_contribs(FILE *fin) { + static int ignore_warning_given = 0; char inpbuf[128]; int iblen; struct rtproc *rtp; /* loop over input */ while ((iblen = getinp(inpbuf, fin)) >= 0) { - if (!iblen || /* need reset? */ + if (!iblen && accumulate != 1) { + if (!ignore_warning_given++) + error(WARNING, + "dummy ray(s) ignored during accumulation\n"); + continue; + } + if (!iblen || /* need flush/reset? */ queue_length() > 10*nrtprocs() || lastray+1 < lastray) { while (wait_rproc() != NULL) process_queue(); - if (lastray+1 < lastray) - lastdone = lastray = 0; + lastdone = lastray = 0; } rtp = get_rproc(); /* get avail. rtrace process */ rtp->raynum = ++lastray; /* assign ray */ if (iblen) { /* trace ray if valid */ writebuf(rtp->pd.w, inpbuf, iblen); } else { /* else bypass dummy ray */ - queue_raytree(rtp); /* empty tree */ - if ((yres <= 0) | (waitflush > 1)) - waitflush = 1; /* flush after this */ + queue_raytree(rtp); /* queue empty ray/record */ + if ((yres <= 0) | (xres <= 0)) + waitflush = 1; /* flush right after */ } process_queue(); /* catch up with results */ if (raysleft && !--raysleft) @@ -1164,8 +1188,12 @@ trace_contribs(FILE *fin) } while (wait_rproc() != NULL) /* process outstanding rays */ process_queue(); - if (accumulate) - done_contrib(); /* output tallies */ + if (accumulate <= 0) + done_contrib(0); /* output tallies */ + else if (account < accumulate) { + error(WARNING, "partial accumulation in final record"); + done_contrib(accumulate - account); + } if (raysleft) error(USER, "unexpected EOF on input"); lu_done(&ofiletab); /* close output files */ @@ -1207,9 +1235,10 @@ myclose(const LUENT *e, void *p) STREAMOUT *sop = (STREAMOUT *)e->data; if (sop->ofp == NULL) - return; + return(0); fclose(sop->ofp); sop->ofp = NULL; + return(0); } /* load previously accumulated values */ @@ -1283,24 +1312,20 @@ reload_output(void) } if ((sout.xr > 0) & (sout.yr > 0) && (!fscnresolu(&xr, &yr, sout.ofp) || - xr != sout.xr || - yr != sout.yr)) { + (xr != sout.xr) | + (yr != sout.yr))) { sprintf(errmsg, "resolution mismatch for '%s'", oname); error(USER, errmsg); } } - if (oent->key == NULL) /* new file entry */ - oent->key = strcpy((char *) - malloc(strlen(oname)+1), oname); - if (oent->data == NULL) - oent->data = (char *)malloc(sizeof(STREAMOUT)); - *(STREAMOUT *)oent->data = sout; /* read in RGB value */ if (!get_contrib(rgbv, sout.ofp)) { - if (!j) + if (!j) { + fclose(sout.ofp); break; /* ignore empty file */ - if (j && j < mp->nbins) { + } + if (j < mp->nbins) { sprintf(errmsg, "missing data in '%s'", oname); error(USER, errmsg); @@ -1310,6 +1335,12 @@ reload_output(void) if (j >= mp->nbins) /* grow modifier size */ ment->data = (char *)(mp = growmodifier(mp, j+1)); copycolor(mp->cbin[j], rgbv); + if (oent->key == NULL) /* new file entry */ + oent->key = strcpy((char *) + malloc(strlen(oname)+1), oname); + if (oent->data == NULL) + oent->data = (char *)malloc(sizeof(STREAMOUT)); + *(STREAMOUT *)oent->data = sout; } } lu_doall(&ofiletab, myclose, NULL); /* close all files */ @@ -1385,7 +1416,6 @@ recover_output(FILE *fin) } else { sout.reclen = 0; sout.outpipe = 0; - sout.xr = xres; sout.yr = yres; sout.ofp = NULL; } if (sout.ofp != NULL) { /* already open? */ @@ -1426,10 +1456,11 @@ recover_output(FILE *fin) oname); error(USER, errmsg); } - if ((xres > 0) & (yres > 0) && + sout.xr = xres; sout.yr = yres; + if ((sout.xr > 0) & (sout.yr > 0) && (!fscnresolu(&xr, &yr, sout.ofp) || - xr != xres || - yr != yres)) { + (xr != sout.xr) | + (yr != sout.yr))) { sprintf(errmsg, "resolution mismatch for '%s'", oname); error(USER, errmsg); @@ -1458,7 +1489,7 @@ recover_output(FILE *fin) error(WARNING, "no output files to recover"); return; } - if (raysleft && lastout >= raysleft) { + if (raysleft && lastout >= raysleft/accumulate) { error(WARNING, "output appears to be complete"); /* XXX should read & discard input? */ quit(0); @@ -1470,7 +1501,7 @@ recover_output(FILE *fin) for (nvals = 0; nvals < lastout; nvals++) if (getinp(oname, fin) < 0) error(USER, "unexpected EOF on input"); - lastray = lastdone = (unsigned long)lastout; + lastray = lastdone = (unsigned long)lastout * accumulate; if (raysleft) raysleft -= lastray; }