ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rtcontrib.c
(Generate patch)

Comparing ray/src/util/rtcontrib.c (file contents):
Revision 1.44 by greg, Thu Nov 15 18:32:34 2007 UTC vs.
Revision 1.45 by greg, Sat Nov 17 01:13:51 2007 UTC

# Line 27 | Line 27 | typedef double DCOLOR[3];              /* double-precision color *
27   /*
28   * The MODCONT structure is used to accumulate ray contributions
29   * for a particular modifier, which may be subdivided into bins
30 < * if binv is non-zero.  If outspec contains a %s in it, this will
30 > * if binv evaluates > 0.  If outspec contains a %s in it, this will
31   * be replaced with the modifier name.  If outspec contains a %d in it,
32   * this will be used to create one output file per bin, otherwise all bins
33   * will be written to the same file, in order.  If the global outfmt
# Line 46 | Line 46 | static void mcfree(void *p) { epfree((*(MODCONT *)p).b
46  
47   LUTAB   modconttab = LU_SINIT(NULL,mcfree);     /* modifier lookup table */
48  
49 #define CNT_UNKNOWN     0               /* unknown record length */
50 #define CNT_PIPE        (-1)            /* output to a pipe */
49   /*
50   * The STREAMOUT structure holds an open FILE pointer and a count of
51 < * the number of RGB triplets per record, or CNT_UNKNOWN (0) if
54 < * unknown or CNT_PIPE (-1) if writing to a command.
51 > * the number of RGB triplets per record, or 0 if unknown.
52   */
53   typedef struct {
54          FILE            *ofp;           /* output file pointer */
55 +        int             outpipe;        /* output is to a pipe */
56          int             reclen;         /* triplets/record */
57 +        int             xr, yr;         /* output resolution for picture */
58   } STREAMOUT;
59  
60   /* close output stream and free record */
# Line 64 | Line 63 | closestream(void *p)
63   {
64          STREAMOUT       *sop = (STREAMOUT *)p;
65          int             status;
66 <        if (sop->reclen == CNT_PIPE)
66 >        if (sop->outpipe)
67                  status = pclose(sop->ofp);
68          else
69                  status = fclose(sop->ofp);
# Line 81 | Line 80 | LUTAB  ofiletab = LU_SINIT(free,closestream);  /* output
80   STREAMOUT *getostream(const char *ospec, const char *mname, int bn, int noopen);
81   int ofname(char *oname, const char *ospec, const char *mname, int bn);
82   void printheader(FILE *fout, const char *info);
83 < void printresolu(FILE *fout);
83 > void printresolu(FILE *fout, int xr, int yr);
84  
85   /*
86   * The rcont structure is used to manage i/o with a particular
# Line 132 | Line 131 | int            inpfmt = 'a';           /* input format */
131   int             outfmt = 'a';           /* output format */
132  
133   int             header = 1;             /* output header? */
134 + int             accumulate = 0;         /* accumulate ray values? */
135   int             force_open = 0;         /* truncate existing output? */
136   int             xres = 0;               /* horiz. output resolution */
137   int             yres = 0;               /* vert. output resolution */
# Line 155 | Line 155 | void addmodfile(char *fname, char *outf, char *binv, i
155  
156   void init(int np);
157   int done_rprocs(struct rtproc *rtp);
158 + void reload_output(void);
159   void recover_output(FILE *fin);
160   void trace_contribs(FILE *fin);
161   struct rtproc *wait_rproc(void);
# Line 273 | Line 274 | main(int argc, char *argv[])
274                                          continue;
275                                  }
276                                  break;
277 +                        case 'c':               /* accumulate ray values */
278 +                                switch (argv[i][2]) {
279 +                                case '\0':
280 +                                        accumulate = !accumulate;
281 +                                        continue;
282 +                                case '+': case '1':
283 +                                case 'T': case 't':
284 +                                case 'Y': case 'y':
285 +                                        accumulate = 1;
286 +                                        continue;
287 +                                case '-': case '0':
288 +                                case 'F': case 'f':
289 +                                case 'N': case 'n':
290 +                                        accumulate = 0;
291 +                                        continue;
292 +                                }
293 +                                break;
294                          case 'r':               /* recover output */
295                                  if (argv[i][2]) break;
296                                  recover++;
# Line 362 | Line 380 | main(int argc, char *argv[])
380                          }
381                  rtargv[rtargc++] = argv[i];     /* assume rtrace option */
382          }
383 +        if (accumulate)         /* no output flushing for single record */
384 +                xres = yres = 0;
385                                  /* set global argument list */
386          gargc = argc; gargv = argv;
387                                  /* add "mandatory" rtrace settings */
# Line 375 | Line 395 | main(int argc, char *argv[])
395                  printf("-n  %-2d\t\t\t\t# number of processes\n", nprocs);
396                  printf("-V%c\t\t\t\t# output %s\n", contrib ? '+' : '-',
397                                  contrib ? "contributions" : "coefficients");
398 +                printf("-c%c\t\t\t\t# %s\n", accumulate ? '+' : '-',
399 +                                accumulate ? "accumulate ray values" :
400 +                                        "one output record per ray");
401                  fflush(stdout);                 /* report OUR options */
402                  rtargv[rtargc++] = header ? "-h+" : "-h-";
403                  sprintf(fmt, "-f%c%c", inpfmt, outfmt);
# Line 417 | Line 440 | main(int argc, char *argv[])
440                                  /* start rtrace */
441          init(nprocs);
442          if (recover)            /* perform recovery if requested */
443 <                recover_output(stdin);
443 >                if ((force_open = accumulate))
444 >                        reload_output();
445 >                else
446 >                        recover_output(stdin);
447          trace_contribs(stdin);  /* compute contributions */
448          quit(0);
449   }
# Line 464 | Line 490 | quit(int status)
490   {
491          int     rtstat;
492  
493 <        if (persist_state == PERSIST_OURS)  /* terminate persistent rtrace */
493 >        if (persist_state == PERSIST_OURS)  /* terminate waiting rtrace */
494                  killpersist();
495                                          /* clean up rtrace process(es) */
496          rtstat = done_rprocs(&rt0);
# Line 581 | Line 607 | addmodifier(char *modn, char *outf, char *binv, int bi
607                  mp = growmodifier(mp, bincnt);
608          lep->data = (char *)mp;
609                                          /* allocate output streams */
610 <        for (i = outf==NULL || outf[0]=='!' ? 0 : bincnt; i-- > 0; )
610 >        for (i = bincnt; i-- > 0; )
611                  getostream(mp->outspec, mp->modname, i, 1);
612          return mp;
613   }
# Line 702 | Line 728 | printheader(FILE *fout, const char *info)
728  
729   /* write resolution string to given output stream */
730   void
731 < printresolu(FILE *fout)
731 > printresolu(FILE *fout, int xr, int yr)
732   {
733 <        if (xres > 0) {
734 <                if (yres > 0)                   /* resolution string */
735 <                        fprtresolu(xres, yres, fout);
733 >        if ((xr > 0) & (yr > 0))        /* resolution string */
734 >                fprtresolu(xr, yr, fout);
735 >        if (xres > 0)                   /* global flush flag */
736                  fflush(fout);
711        }
737   }
738  
739   /* Get output stream pointer (open and write header if new and noopen==0) */
740   STREAMOUT *
741   getostream(const char *ospec, const char *mname, int bn, int noopen)
742   {
743 +        static const DCOLOR     nocontrib = BLKCOLOR;
744          static STREAMOUT        stdos;
745          int                     ofl;
746          char                    oname[1024];
# Line 723 | Line 749 | getostream(const char *ospec, const char *mname, int b
749          
750          if (ospec == NULL) {                    /* use stdout? */
751                  if (!noopen && !using_stdout) {
726                        stdos.reclen = 0;
752                          if (outfmt != 'a')
753                                  SET_FILE_BINARY(stdout);
754                          if (header)
755                                  printheader(stdout, NULL);
756 <                        printresolu(stdout);
756 >                        printresolu(stdout, xres, yres);
757 >                        stdos.xr = xres; stdos.yr = yres;
758                          using_stdout = 1;
759                  }
760                  stdos.ofp = stdout;
# Line 748 | Line 774 | getostream(const char *ospec, const char *mname, int b
774                  sop = (STREAMOUT *)malloc(sizeof(STREAMOUT));
775                  if (sop == NULL)
776                          error(SYSTEM, "out of memory in getostream");
777 <                sop->reclen = oname[0] == '!' ? CNT_PIPE : CNT_UNKNOWN;
777 >                sop->outpipe = oname[0] == '!';
778 >                sop->reclen = 0;
779                  sop->ofp = NULL;                /* open iff noopen==0 */
780 +                sop->xr = xres; sop->yr = yres;
781                  lep->data = (char *)sop;
782 +                if (!force_open && access(oname, F_OK) == 0) {
783 +                        errno = EEXIST;         /* file exists */
784 +                        goto openerr;
785 +                }
786          }
787          if (!noopen && sop->ofp == NULL) {      /* open output stream */
788                  long            i;
789                  if (oname[0] == '!')            /* output to command */
790                          sop->ofp = popen(oname+1, "w");
791 <                else if (!force_open && access(oname, F_OK) == 0)
760 <                        errno = EEXIST;         /* file exists */
761 <                else                            /* else open it */
791 >                else                            /* else open file */
792                          sop->ofp = fopen(oname, "w");
793 <                if (sop->ofp == NULL) {
794 <                        sprintf(errmsg, "cannot open '%s' for writing", oname);
765 <                        error(SYSTEM, errmsg);
766 <                }
793 >                if (sop->ofp == NULL)
794 >                        goto openerr;
795                  if (outfmt != 'a')
796                          SET_FILE_BINARY(sop->ofp);
797                  if (header) {
# Line 780 | Line 808 | getostream(const char *ospec, const char *mname, int b
808                          *cp = '\0';
809                          printheader(sop->ofp, info);
810                  }
811 <                printresolu(sop->ofp);
811 >                printresolu(sop->ofp, sop->xr, sop->yr);
812                                                  /* play catch-up */
813 <                for (i = sop->reclen > 1 ? sop->reclen*lastdone : lastdone;
814 <                                                                i--; ) {
815 <                        static const DCOLOR     nocontrib = BLKCOLOR;
816 <                        put_contrib(nocontrib, sop->ofp);
813 >                for (i = accumulate ? 0 : lastdone; i--; ) {
814 >                        int     j = sop->reclen;
815 >                        if (j <= 0) j = 1;
816 >                        while (j--)
817 >                                put_contrib(nocontrib, sop->ofp);
818                          if (outfmt == 'a')
819                                  putc('\n', sop->ofp);
820                  }
821                  if (xres > 0)
822                          fflush(sop->ofp);
823          }
824 <        if (sop->reclen != CNT_PIPE)            /* add to length if noopen */
825 <                sop->reclen += noopen;
826 <        return sop;                             /* return open stream */
824 >        sop->reclen += noopen;                  /* add to length if noopen */
825 >        return sop;                             /* return output stream */
826 > openerr:
827 >        sprintf(errmsg, "cannot open '%s' for writing", oname);
828 >        error(SYSTEM, errmsg);
829 >        return NULL;    /* pro forma return */
830   }
831  
832   /* read input ray into buffer */
833   int
834   getinp(char *buf, FILE *fp)
835   {
836 <        double  dv[3];
837 <        float   fv[3];
836 >        double  dv[3], *dvp;
837 >        float   *fvp;
838          char    *cp;
839          int     i;
840  
# Line 826 | Line 858 | getinp(char *buf, FILE *fp)
858          case 'f':
859                  if (fread(buf, sizeof(float), 6, fp) < 6)
860                          return -1;
861 <                memcpy(fv, buf+3*sizeof(float), 3*sizeof(float));
862 <                if (DOT(fv,fv) <= FTINY*FTINY)
861 >                fvp = (float *)buf + 3;
862 >                if (DOT(fvp,fvp) <= FTINY*FTINY)
863                          return 0;       /* dummy ray */
864                  return sizeof(float)*6;
865          case 'd':
866                  if (fread(buf, sizeof(double), 6, fp) < 6)
867                          return -1;
868 <                memcpy(dv, buf+3*sizeof(double), 3*sizeof(double));
869 <                if (DOT(dv,dv) <= FTINY*FTINY)
868 >                dvp = (double *)buf + 3;
869 >                if (DOT(dvp,dvp) <= FTINY*FTINY)
870                          return 0;       /* dummy ray */
871                  return sizeof(double)*6;
872          }
# Line 920 | Line 952 | put_contrib(const DCOLOR cnt, FILE *fout)
952          }
953   }
954  
955 < /* output ray tallies and clear for next primary */
955 > /* output ray tallies and clear for next accumulation */
956   void
957   done_contrib(void)
958   {
# Line 940 | Line 972 | done_contrib(void)
972                          for (j = 1; j < mp->nbins; j++)
973                                  put_contrib(mp->cbin[j],
974                                      getostream(mp->outspec,mp->modname,j,0)->ofp);
975 <                                                /* clear for next ray tree */
975 >                                                /* clear for next time */
976                  memset(mp->cbin, 0, sizeof(DCOLOR)*mp->nbins);
977          }
978          --waitflush;                            /* terminate records */
# Line 1013 | Line 1045 | process_queue(void)
1045                          cp += sizeof(float)*9; n -= sizeof(float)*9;
1046                          add_contrib(modname);
1047                  }
1048 <                done_contrib();         /* sum up contributions & output */
1048 >                if (!accumulate)
1049 >                        done_contrib(); /* sum up contributions & output */
1050                  lastdone = rtp->raynum;
1051                  if (rtp->buf != NULL)   /* free up buffer space */
1052                          free(rtp->buf);
# Line 1128 | Line 1161 | trace_contribs(FILE *fin)
1161          }
1162          while (wait_rproc() != NULL)            /* process outstanding rays */
1163                  process_queue();
1164 +        if (accumulate)
1165 +                done_contrib();                 /* output tallies */
1166          if (raysleft)
1167                  error(USER, "unexpected EOF on input");
1168          lu_done(&ofiletab);                     /* close output files */
# Line 1149 | Line 1184 | myseeko(const LUENT *e, void *p)
1184          return 0;
1185   }
1186  
1187 + /* load previously accumulated values */
1188 + void
1189 + reload_output(void)
1190 + {
1191 +        int             i, j;
1192 +        MODCONT         *mp;
1193 +        int             ofl;
1194 +        char            oname[1024];
1195 +        char            *fmode = "rb";
1196 +        char            *outvfmt;
1197 +        LUENT           *ment, *oent;
1198 +        STREAMOUT       sout;
1199 +
1200 +        error(INTERNAL, "-r option not yet implemented with -c");
1201 +
1202 +        switch (outfmt) {
1203 +        case 'a':
1204 +                outvfmt = "ascii";
1205 +                fmode = "r";
1206 +                break;
1207 +        case 'f':
1208 +                outvfmt = "float";
1209 +                break;
1210 +        case 'd':
1211 +                outvfmt = "double";
1212 +                break;
1213 +        case 'c':
1214 +                outvfmt = COLRFMT;
1215 +                break;
1216 +        default:
1217 +                error(INTERNAL, "botched output format");
1218 +                return;
1219 +        }
1220 +                                                /* check modifier outputs */
1221 +        for (i = 0; i < nmods; i++) {
1222 +                ment = lu_find(&modconttab,modname[i]);
1223 +                mp = (MODCONT *)ment->data;
1224 +                if (mp->outspec == NULL)
1225 +                        error(USER, "cannot reload from stdout");
1226 +                if (mp->outspec[0] == '!')
1227 +                        error(USER, "cannot reload from command");
1228 +                for (j = 0; ; j++) {            /* check each bin's file */
1229 +                        ofl = ofname(oname, mp->outspec, mp->modname, j);
1230 +                        if (ofl < 0)
1231 +                                error(USER, "bad output file specification");
1232 +                        oent = lu_find(&ofiletab, oname);
1233 +                        if (oent->data != NULL) {
1234 +                                sout = *(STREAMOUT *)oent->data;
1235 +                        } else {
1236 +                                sout.reclen = 0;
1237 +                                sout.ofp = NULL;
1238 +                        }
1239 +                        if (sout.ofp != NULL) { /* already open? */
1240 +                                if (ofl & OF_BIN)
1241 +                                        continue;
1242 +                                break;
1243 +                        }
1244 +                                                /* open output */
1245 +                        sout.ofp = fopen(oname, fmode);
1246 +                        if (sout.ofp == NULL) {
1247 +                                if (j)
1248 +                                        break;  /* assume end of modifier */
1249 +                                sprintf(errmsg, "missing reload file '%s'",
1250 +                                                oname);
1251 +                                error(WARNING, errmsg);
1252 +                                break;
1253 +                        }
1254 +                        if (oent->key == NULL)  /* new entry */
1255 +                                oent->key = strcpy((char *)
1256 +                                                malloc(strlen(oname)+1), oname);
1257 +                        if (oent->data == NULL)
1258 +                                oent->data = (char *)malloc(sizeof(STREAMOUT));
1259 +                        *(STREAMOUT *)oent->data = sout;
1260 +                        if (!(ofl & OF_BIN))
1261 +                                break;          /* no bin separation */
1262 +                }
1263 +                if (j > mp->nbins)              /* reallocate modifier bins */
1264 +                        ment->data = (char *)(mp = growmodifier(mp, j));
1265 +        }
1266 +        lu_done(&ofiletab);                     /* close all files */
1267 + }
1268 +
1269   /* recover output if possible */
1270   void
1271   recover_output(FILE *fin)
# Line 1201 | Line 1318 | recover_output(FILE *fin)
1318                          if (oent->data != NULL) {
1319                                  sout = *(STREAMOUT *)oent->data;
1320                          } else {
1321 <                                sout.reclen = CNT_UNKNOWN;
1321 >                                sout.reclen = 0;
1322                                  sout.ofp = NULL;
1323                          }
1324                          if (sout.ofp != NULL) { /* already open? */
# Line 1216 | Line 1333 | recover_output(FILE *fin)
1333                                          break;  /* assume end of modifier */
1334                                  sprintf(errmsg, "missing recover file '%s'",
1335                                                  oname);
1336 <                                error(USER, errmsg);
1336 >                                error(WARNING, errmsg);
1337 >                                break;
1338                          }
1339                          nvals = lseek(fileno(sout.ofp), 0, SEEK_END);
1340                          if (nvals <= 0) {
# Line 1224 | Line 1342 | recover_output(FILE *fin)
1342                                  fclose(sout.ofp);
1343                                  break;
1344                          }
1345 <                        if (sout.reclen == CNT_UNKNOWN) {
1345 >                        if (!sout.reclen) {
1346                                  if (!(ofl & OF_BIN)) {
1347                                          sprintf(errmsg,
1348                                                  "need -bn to recover file '%s'",

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines