Back to index

radiance  4R0+20100331
rhcopy.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rhcopy.c,v 3.24 2008/11/10 19:08:19 greg Exp $";
00003 #endif
00004 /*
00005  * Copy data into a holodeck file
00006  */
00007 
00008 #include "platform.h"
00009 #include "rterror.h"
00010 #include "holo.h"
00011 #include "view.h"
00012 
00013 #ifndef BKBSIZE
00014 #define BKBSIZE             256           /* beam clump size (kilobytes) */
00015 #endif
00016 
00017 int    checkdepth = 1;             /* check depth (!-d option)? */
00018 int    checkrepeats = 0;    /* check for repeats (-u option)? */
00019 int    frompicz;            /* input from pictures & depth-buffers? */
00020 int    noutsects;           /* number of output sections */
00021 char   obstr, unobstr;             /* flag pointer values */
00022 
00023 char   *progname;           /* global argv[0] */
00024 
00025 struct phead {
00026        VIEW   vw;
00027        double expos;
00028        short  gotview;
00029        short  badfmt;
00030        short  altprims;
00031 };
00032 static int openholo(char *fname, int append);
00033 static void addray(FVECT ro, FVECT rd, double d, COLR cv);
00034 static gethfunc holheadline;
00035 static int bpcmp(const void *b1p, const void *b2p);
00036 static int addclump(HOLO *hp, int *bq, int nb);
00037 static void addholo(char *hdf);
00038 static gethfunc picheadline;
00039 static void addpicz(char *pcf, char *zbf);
00040 
00041 
00042 
00043 int
00044 main(
00045        int    argc,
00046        char   *argv[]
00047 )
00048 {
00049        int    i;
00050 
00051        progname = argv[0];
00052        frompicz = -1;
00053        for (i = 2; i < argc && argv[i][0] == '-'; i++)
00054               switch (argv[i][1]) {
00055               case 'u':
00056                      checkrepeats = 1;
00057                      break;
00058               case 'd':
00059                      checkdepth = 0;
00060                      break;
00061               case 'h':
00062                      frompicz = 0;
00063                      break;
00064               case 'p':
00065                      frompicz = 1;
00066                      break;
00067               default:
00068                      goto userr;
00069               }
00070        if (i >= argc || frompicz < 0)
00071               goto userr;
00072        if (frompicz && (argc-i)%2)
00073               goto userr;
00074        noutsects = openholo(argv[1], 1);
00075        if (frompicz) {
00076               for ( ; i < argc; i += 2)
00077                      addpicz(argv[i], argv[i+1]);
00078        } else {
00079               if (BKBSIZE*1024*1.5 > hdcachesize)
00080                      hdcachesize = BKBSIZE*1024*1.5;
00081               for ( ; i < argc; i++)
00082                      addholo(argv[i]);
00083        }
00084        quit(0);
00085 userr:
00086        fprintf(stderr, "Usage: %s output.hdk [-u][-d] -h inp1.hdk ..\n",
00087                      progname);
00088        fprintf(stderr, "   Or: %s output.hdk [-u][-d] -p inp1.hdr inp1.zbf ..\n",
00089                      progname);
00090        exit(1);
00091 }
00092 
00093 
00094 #define H_BADF       01
00095 #define H_OBST       02
00096 #define H_OBSF       04
00097 
00098 static int
00099 holheadline(         /* check holodeck header line */
00100        register char *s,
00101        void   *vhf
00102 )
00103 {
00104        char   fmt[32];
00105        int    *hf = vhf;
00106 
00107        if (formatval(fmt, s)) {
00108               if (strcmp(fmt, HOLOFMT))
00109                      *hf |= H_BADF;
00110               else
00111                      *hf &= ~H_BADF;
00112               return(0);
00113        }
00114        if (!strncmp(s, "OBSTRUCTIONS=", 13)) {
00115               s += 13;
00116               while (*s == ' ') s++;
00117               if ((*s == 't') | (*s == 'T'))
00118                      *hf |= H_OBST;
00119               else if ((*s == 'f') | (*s == 'F'))
00120                      *hf |= H_OBSF;
00121               else
00122                      error(WARNING, "bad OBSTRUCTIONS value in holodeck");
00123               return(0);
00124        }
00125        return(0);
00126 }
00127 
00128 int
00129 openholo(            /* open existing holodeck file for i/o */
00130        char   *fname,
00131        int    append
00132 )
00133 {
00134        FILE   *fp;
00135        int    fd;
00136        int    hflags = 0;
00137        long   nextloc;
00138        int    n;
00139                                    /* open holodeck file */
00140        if ((fp = fopen(fname, append ? "r+" : "r")) == NULL) {
00141               sprintf(errmsg, "cannot open \"%s\" for %s", fname,
00142                             append ? "appending" : "reading");
00143               error(SYSTEM, errmsg);
00144        }
00145                                    /* check header and magic number */
00146        if (getheader(fp, holheadline, &hflags) < 0 ||
00147                      hflags&H_BADF || getw(fp) != HOLOMAGIC) {
00148               sprintf(errmsg, "file \"%s\" not in holodeck format", fname);
00149               error(USER, errmsg);
00150        }
00151        fd = dup(fileno(fp));                     /* dup file handle */
00152        nextloc = ftell(fp);               /* get stdio position */
00153        fclose(fp);                        /* done with stdio */
00154        for (n = 0; nextloc > 0L; n++) {   /* initialize each section */
00155               lseek(fd, (off_t)nextloc, SEEK_SET);
00156               read(fd, (char *)&nextloc, sizeof(nextloc));
00157               hdinit(fd, NULL)->priv = hflags&H_OBST ? &obstr :
00158                             hflags&H_OBSF ? &unobstr : (char *)NULL;
00159        }
00160        return(n);
00161 }
00162 
00163 #undef H_BADF
00164 #undef H_OBST
00165 #undef H_OBSF
00166 
00167 
00168 void
00169 addray(              /* add a ray to our output holodeck */
00170        FVECT  ro,
00171        FVECT  rd,
00172        double d,
00173        COLR   cv
00174 )
00175 {
00176        int    sn, bi, n;
00177        register HOLO *hp;
00178        GCOORD gc[2];
00179        BYTE   rr[2][2];
00180        BEAM   *bp;
00181        double d0, d1;
00182        unsigned      dc;
00183        register RAYVAL      *rv;
00184                             /* check each output section */
00185        for (sn = noutsects; sn--; ) {
00186               hp = hdlist[sn];
00187               d0 = hdinter(gc, rr, &d1, hp, ro, rd);
00188               if (d <= d0 || d1 < -0.001)
00189                      continue;     /* missed section */
00190               if (checkdepth) {           /* check depth */
00191                      if (hp->priv == &obstr && d0 < -0.001)
00192                             continue;     /* ray starts too late */
00193                      if (hp->priv == &unobstr && d < 0.999*d1)
00194                             continue;     /* ray ends too soon */
00195               }
00196               dc = hdcode(hp, d-d0);
00197               bi = hdbindex(hp, gc);             /* check for duplicates */
00198               if (checkrepeats && (bp = hdgetbeam(hp, bi)) != NULL) {
00199                      for (n = bp->nrm, rv = hdbray(bp); n--; rv++)
00200                             if ((hp->priv != NULL || rv->d == dc) &&
00201                                           rv->r[0][0] == rr[0][0] &&
00202                                           rv->r[0][1] == rr[0][1] &&
00203                                           rv->r[1][0] == rr[1][0] &&
00204                                           rv->r[1][1] == rr[1][1])
00205                                    break;
00206                      if (n >= 0)
00207                             continue;     /* found a matching ray */
00208               }
00209               rv = hdnewrays(hp, bi, 1);
00210               rv->d = dc;
00211               rv->r[0][0] = rr[0][0]; rv->r[0][1] = rr[0][1];
00212               rv->r[1][0] = rr[1][0]; rv->r[1][1] = rr[1][1];
00213               copycolr(rv->v, cv);
00214        }
00215 }
00216 
00217 
00218 static BEAMI  *beamdir;
00219 
00220 static int
00221 bpcmp(               /* compare beam positions on disk */
00222        const void    *b1p,
00223        const void    *b2p
00224 )
00225 {
00226        register off_t       pdif = beamdir[*(int*)b1p].fo - beamdir[*(int*)b2p].fo;
00227 
00228        if (pdif > 0L) return(1);
00229        if (pdif < 0L) return(-1);
00230        return(0);
00231 }
00232 
00233 static int
00234 addclump(            /* transfer the given clump and free */
00235        HOLO   *hp,
00236        int    *bq,
00237        int    nb
00238 )
00239 {
00240        GCOORD gc[2];
00241        FVECT  ro, rd;
00242        double d;
00243        int    i;
00244        register int  k;
00245        register BEAM *bp;
00246                                    /* sort based on file position */
00247        beamdir = hp->bi;
00248        qsort((char *)bq, nb, sizeof(*bq), bpcmp);
00249                                    /* transfer each beam */
00250        for (i = 0; i < nb; i++) {
00251               bp = hdgetbeam(hp, bq[i]);
00252               hdbcoord(gc, hp, bq[i]);
00253                                           /* add each ray to output */
00254               for (k = bp->nrm; k--; ) {
00255                      d = hdray(ro, rd, hp, gc, hdbray(bp)[k].r);
00256                      if (hp->priv == &unobstr)
00257                             VSUM(ro, ro, rd, d);
00258                      else
00259                             d = 0.;
00260                      d = hddepth(hp, hdbray(bp)[k].d) - d;
00261                      addray(ro, rd, d, hdbray(bp)[k].v);
00262               }
00263               hdfreebeam(hp, bq[i]);             /* free the beam */
00264        }
00265        return(0);
00266 }
00267 
00268 
00269 void
00270 addholo(                    /* add a holodeck file */
00271        char   *hdf
00272 )
00273 {
00274        int    fd;
00275                                    /* open the holodeck for reading */
00276        openholo(hdf, 0);
00277        fd = hdlist[noutsects]->fd; /* remember the file handle */
00278        while (hdlist[noutsects] != NULL) {       /* load each section */
00279                                                  /* clump the beams */
00280               clumpbeams(hdlist[noutsects], 0, BKBSIZE*1024, addclump);
00281               hddone(hdlist[noutsects]);         /* free the section */
00282        }
00283        close(fd);                  /* close input file */
00284        hdflush(NULL);                     /* flush output */
00285 }
00286 
00287 
00288 
00289 static int
00290 picheadline(         /* process picture header line */
00291        char   *s,
00292        void   *vph
00293 )
00294 {
00295        char   fmt[32];
00296        struct phead *ph = vph;
00297 
00298        if (formatval(fmt, s)) {
00299               ph->badfmt = strcmp(fmt, COLRFMT);
00300               return(0);
00301        }
00302        if (isprims(s)) {
00303               ph->altprims++;             /* don't want to deal with this */
00304               return(0);
00305        }
00306        if (isexpos(s)) {
00307               ph->expos *= exposval(s);
00308               return(0);
00309        }
00310        if (isview(s)) {
00311               ph->gotview += sscanview(&ph->vw, s);
00312               return(0);
00313        }
00314        return(0);
00315 }
00316 
00317 
00318 void
00319 addpicz(             /* add a picture + depth-buffer */
00320        char   *pcf,
00321        char   *zbf
00322 )
00323 {
00324        FILE   *pfp;
00325        int    zfd;
00326        COLR   *cscn;
00327        float  *zscn;
00328        struct phead  phd;
00329        int    eshft;
00330        double emult;
00331        RESOLU prs;
00332        RREAL  vl[2];
00333        FVECT  ro, rd;
00334        double aftd;
00335        COLOR  ctmp;
00336        int    j;
00337        register int  i;
00338                             /* open files */
00339        if ((pfp = fopen(pcf, "r")) == NULL) {
00340               sprintf(errmsg, "cannot open picture file \"%s\"", pcf);
00341               error(SYSTEM, pcf);
00342        }
00343        if ((zfd = open(zbf, O_RDONLY)) < 0) {
00344               sprintf(errmsg, "cannot open depth file \"%s\"", zbf);
00345               error(SYSTEM, pcf);
00346        }
00347                             /* load picture header */
00348        phd.vw = stdview;
00349        phd.expos = 1.0;
00350        phd.badfmt = phd.gotview = phd.altprims = 0;
00351        if (getheader(pfp, picheadline, &phd) < 0 ||
00352                      phd.badfmt || !fgetsresolu(&prs, pfp)) {
00353               sprintf(errmsg, "bad format for picture file \"%s\"", pcf);
00354               error(USER, errmsg);
00355        }
00356        if (!phd.gotview || setview(&phd.vw) != NULL) {
00357               sprintf(errmsg, "missing/illegal view in picture \"%s\"",
00358                             pcf);
00359               error(USER, errmsg);
00360        }
00361        if (phd.altprims) {
00362               sprintf(errmsg, "ignoring primary values in picture \"%s\"",
00363                             pcf);
00364               error(WARNING, errmsg);
00365        }
00366                             /* figure out what to do about exposure */
00367        if ((phd.expos < 0.99) | (phd.expos > 1.01)) {
00368               emult = -log(phd.expos)/log(2.);
00369               eshft = emult >= 0. ? emult+.5 : emult-.5;
00370               emult -= (double)eshft;
00371               if ((emult <= 0.01) & (emult >= -0.01))
00372                      emult = -1.;
00373               else {
00374                      emult = 1./phd.expos;
00375                      eshft = 0;
00376               }
00377        } else {
00378               emult = -1.;
00379               eshft = 0;
00380        }
00381                             /* allocate buffers */
00382        cscn = (COLR *)malloc(scanlen(&prs)*sizeof(COLR));
00383        zscn = (float *)malloc(scanlen(&prs)*sizeof(float));
00384        if ((cscn == NULL) | (zscn == NULL))
00385               error(SYSTEM, "out of memory in addpicz");
00386                             /* read and process each scanline */
00387        for (j = 0; j < numscans(&prs); j++) {
00388               i = scanlen(&prs);                 /* read colrs */
00389               if (freadcolrs(cscn, i, pfp) < 0) {
00390                      sprintf(errmsg, "error reading picture \"%s\"", pcf);
00391                      error(USER, errmsg);
00392               }
00393               if (eshft)                         /* shift exposure */
00394                      shiftcolrs(cscn, i, eshft);
00395               i *= sizeof(float);                /* read depth */
00396               if (read(zfd, (char *)zscn, i) != i) {
00397                      sprintf(errmsg, "error reading depth file \"%s\"", zbf);
00398                      error(USER, errmsg);
00399               }
00400               for (i = scanlen(&prs); i--; ) {   /* do each pixel */
00401                      pix2loc(vl, &prs, i, j);
00402                      aftd = viewray(ro, rd, &phd.vw, vl[0], vl[1]);
00403                      if (aftd < -FTINY)
00404                             continue;            /* off view */
00405                      if (aftd > FTINY && zscn[i] > aftd)
00406                             continue;            /* aft clipped */
00407                      if (emult > 0.) {           /* whatta pain */
00408                             colr_color(ctmp, cscn[i]);
00409                             scalecolor(ctmp, emult);
00410                             setcolr(cscn[i], colval(ctmp,RED),
00411                                    colval(ctmp,GRN), colval(ctmp,BLU));
00412                      }
00413                      addray(ro, rd, (double)zscn[i], cscn[i]);
00414               }
00415        }
00416                             /* write output and free beams */
00417        hdflush(NULL);
00418                             /* clean up */
00419        free((void *)cscn);
00420        free((void *)zscn);
00421        fclose(pfp);
00422        close(zfd);
00423 }
00424 
00425 
00426 void
00427 eputs(               /* put error message to stderr */
00428        register char  *s
00429 )
00430 {
00431        static int  midline = 0;
00432 
00433        if (!*s)
00434               return;
00435        if (!midline++) {    /* prepend line with program name */
00436               fputs(progname, stderr);
00437               fputs(": ", stderr);
00438        }
00439        fputs(s, stderr);
00440        if (s[strlen(s)-1] == '\n') {
00441               fflush(stderr);
00442               midline = 0;
00443        }
00444 }
00445 
00446 
00447 void
00448 quit(                /* exit the program gracefully */
00449        int    code
00450 )
00451 {
00452        hdsync(NULL, 1);     /* write out any buffered data */
00453        exit(code);
00454 }