--- ray/src/hd/rhcopy.c 1997/12/18 10:03:29 3.2 +++ ray/src/hd/rhcopy.c 2004/01/01 11:21:55 3.22 @@ -1,53 +1,92 @@ -/* Copyright (c) 1997 Silicon Graphics, Inc. */ - #ifndef lint -static char SCCSid[] = "$SunId$ SGI"; +static const char RCSid[] = "$Id: rhcopy.c,v 3.22 2004/01/01 11:21:55 schorsch Exp $"; #endif - /* * Copy data into a holodeck file */ +#include "platform.h" +#include "rterror.h" #include "holo.h" #include "view.h" -#include "resolu.h" +#ifndef BKBSIZE +#define BKBSIZE 256 /* beam clump size (kilobytes) */ +#endif + +int checkdepth = 1; /* check depth (!-d option)? */ +int checkrepeats = 0; /* check for repeats (-u option)? */ int frompicz; /* input from pictures & depth-buffers? */ int noutsects; /* number of output sections */ char obstr, unobstr; /* flag pointer values */ char *progname; /* global argv[0] */ +struct phead { + VIEW vw; + double expos; + short gotview; + short badfmt; + short altprims; +}; +static int openholo(char *fname, int append); +static void addray(FVECT ro, FVECT rd, double d, COLR cv); +static int holheadline(char *s, int *hf); +static int bpcmp(const void *b1p, const void *b2p); +static int addclump(HOLO *hp, int *bq, int nb); +static void addholo(char *hdf); +static int picheadline(char *s, struct phead *ph); +static void addpicz(char *pcf, char *zbf); -main(argc, argv) -int argc; -char *argv[]; + + +int +main( + int argc, + char *argv[] +) { int i; progname = argv[0]; - if (argc < 4) + frompicz = -1; + for (i = 2; i < argc && argv[i][0] == '-'; i++) + switch (argv[i][1]) { + case 'u': + checkrepeats = 1; + break; + case 'd': + checkdepth = 0; + break; + case 'h': + frompicz = 0; + break; + case 'p': + frompicz = 1; + break; + default: + goto userr; + } + if (i >= argc || frompicz < 0) goto userr; - if (!strcmp(argv[2], "-h")) - frompicz = 0; - else if (!strcmp(argv[2], "-pz")) - frompicz = 1; - else + if (frompicz && (argc-i)%2) goto userr; - if (frompicz && (argc-3)%2) - goto userr; noutsects = openholo(argv[1], 1); - if (frompicz) - for (i = 3; i < argc; i += 2) + if (frompicz) { + for ( ; i < argc; i += 2) addpicz(argv[i], argv[i+1]); - else - for (i = 3; i < argc; i++) + } else { + if (BKBSIZE*1024*1.5 > hdcachesize) + hdcachesize = BKBSIZE*1024*1.5; + for ( ; i < argc; i++) addholo(argv[i]); + } quit(0); userr: - fprintf(stderr, "Usage: %s output.hdk -h inp1.hdk ..\n", progname); - fprintf(stderr, " Or: %s output.hdk -pz inp1.pic inp1.zbf ..\n", + fprintf(stderr, "Usage: %s output.hdk [-u][-d] -h inp1.hdk ..\n", progname); + fprintf(stderr, " Or: %s output.hdk [-u][-d] -p inp1.pic inp1.zbf ..\n", + progname); exit(1); } @@ -56,9 +95,11 @@ userr: #define H_OBST 02 #define H_OBSF 04 -holheadline(s, hf) /* check holodeck header line */ -register char *s; -int *hf; +int +holheadline( /* check holodeck header line */ + register char *s, + int *hf +) { char fmt[32]; @@ -67,31 +108,32 @@ int *hf; *hf |= H_BADF; else *hf &= ~H_BADF; - return; + return(0); } if (!strncmp(s, "OBSTRUCTIONS=", 13)) { s += 13; while (*s == ' ') s++; - if (*s == 't' | *s == 'T') + if ((*s == 't') | (*s == 'T')) *hf |= H_OBST; - else if (*s == 'f' | *s == 'F') + else if ((*s == 'f') | (*s == 'F')) *hf |= H_OBSF; else error(WARNING, "bad OBSTRUCTIONS value in holodeck"); - return; + return(0); } + return(0); } int -openholo(fname, append) /* open existing holodeck file for i/o */ -char *fname; -int append; +openholo( /* open existing holodeck file for i/o */ + char *fname, + int append +) { - extern long ftell(); FILE *fp; int fd; int hflags = 0; - int4 nextloc; + long nextloc; int n; /* open holodeck file */ if ((fp = fopen(fname, append ? "r+" : "r")) == NULL) { @@ -100,7 +142,7 @@ int append; error(SYSTEM, errmsg); } /* check header and magic number */ - if (getheader(fp, holheadline, &hflags) < 0 || + if (getheader(fp, holheadline, (char *)&hflags) < 0 || hflags&H_BADF || getw(fp) != HOLOMAGIC) { sprintf(errmsg, "file \"%s\" not in holodeck format", fname); error(USER, errmsg); @@ -109,7 +151,7 @@ int append; nextloc = ftell(fp); /* get stdio position */ fclose(fp); /* done with stdio */ for (n = 0; nextloc > 0L; n++) { /* initialize each section */ - lseek(fd, (long)nextloc, 0); + lseek(fd, (off_t)nextloc, SEEK_SET); read(fd, (char *)&nextloc, sizeof(nextloc)); hdinit(fd, NULL)->priv = hflags&H_OBST ? &obstr : hflags&H_OBSF ? &unobstr : (char *)NULL; @@ -122,16 +164,21 @@ int append; #undef H_OBSF -addray(ro, rd, d, cv) /* add a ray to our output holodeck */ -FVECT ro, rd; -double d; -COLR cv; +void +addray( /* add a ray to our output holodeck */ + FVECT ro, + FVECT rd, + double d, + COLR cv +) { - int sn; + int sn, bi, n; register HOLO *hp; GCOORD gc[2]; BYTE rr[2][2]; + BEAM *bp; double d0, d1; + unsigned dc; register RAYVAL *rv; /* check each output section */ for (sn = noutsects; sn--; ) { @@ -139,92 +186,138 @@ COLR cv; d0 = hdinter(gc, rr, &d1, hp, ro, rd); if (d <= d0 || d1 < -0.001) continue; /* missed section */ - if (hp->priv == &obstr && d0 < -0.001) - continue; /* ray starts too late */ - if (hp->priv == &unobstr && d < 0.999*d1) - continue; /* ray ends too soon */ - /* should we check for duplicates? */ - rv = hdnewrays(hp, hdbindex(hp, gc), 1); + if (checkdepth) { /* check depth */ + if (hp->priv == &obstr && d0 < -0.001) + continue; /* ray starts too late */ + if (hp->priv == &unobstr && d < 0.999*d1) + continue; /* ray ends too soon */ + } + dc = hdcode(hp, d-d0); + bi = hdbindex(hp, gc); /* check for duplicates */ + if (checkrepeats && (bp = hdgetbeam(hp, bi)) != NULL) { + for (n = bp->nrm, rv = hdbray(bp); n--; rv++) + if ((hp->priv != NULL || rv->d == dc) && + rv->r[0][0] == rr[0][0] && + rv->r[0][1] == rr[0][1] && + rv->r[1][0] == rr[1][0] && + rv->r[1][1] == rr[1][1]) + break; + if (n >= 0) + continue; /* found a matching ray */ + } + rv = hdnewrays(hp, bi, 1); + rv->d = dc; rv->r[0][0] = rr[0][0]; rv->r[0][1] = rr[0][1]; rv->r[1][0] = rr[1][0]; rv->r[1][1] = rr[1][1]; copycolr(rv->v, cv); - rv->d = hdcode(hp, d-d0); } } -addholo(hdf) /* add a holodeck file */ -char *hdf; +static BEAMI *beamdir; + +static int +bpcmp( /* compare beam positions on disk */ + const void *b1p, + const void *b2p +) { - int fd; - register HOLO *hp; - register BEAM *bp; + register off_t pdif = beamdir[*(int*)b1p].fo - beamdir[*(int*)b2p].fo; + + if (pdif > 0L) return(1); + if (pdif < 0L) return(-1); + return(0); +} + +static int +addclump( /* transfer the given clump and free */ + HOLO *hp, + int *bq, + int nb +) +{ GCOORD gc[2]; FVECT ro, rd; double d; - int i, j; + int i; register int k; + register BEAM *bp; + /* sort based on file position */ + beamdir = hp->bi; + qsort((char *)bq, nb, sizeof(*bq), bpcmp); + /* transfer each beam */ + for (i = 0; i < nb; i++) { + bp = hdgetbeam(hp, bq[i]); + hdbcoord(gc, hp, bq[i]); + /* add each ray to output */ + for (k = bp->nrm; k--; ) { + d = hdray(ro, rd, hp, gc, hdbray(bp)[k].r); + if (hp->priv == &unobstr) + VSUM(ro, ro, rd, d); + else + d = 0.; + d = hddepth(hp, hdbray(bp)[k].d) - d; + addray(ro, rd, d, hdbray(bp)[k].v); + } + hdfreebeam(hp, bq[i]); /* free the beam */ + } + return(0); +} - openholo(hdf, 0); /* open the holodeck for reading */ + +void +addholo( /* add a holodeck file */ + char *hdf +) +{ + int fd; + /* open the holodeck for reading */ + openholo(hdf, 0); fd = hdlist[noutsects]->fd; /* remember the file handle */ - while ((hp = hdlist[noutsects]) != NULL) { /* load each section */ - for (j = nbeams(hp); j > 0; j--) /* load each beam */ - if ((bp = hdgetbeam(hp, j)) != NULL) { - hdbcoord(gc, hp, j); - for (k = bp->nrm; k--; ) { - d = hdray(ro, rd, - hp, gc, hdbray(bp)[k].r); - if (hp->priv == &unobstr) - VSUM(ro, ro, rd, d); - else - d = 0.; - d = hddepth(hp, hdbray(bp)[k].d) - d; - addray(ro, rd, d, hdbray(bp)[k].v); - } - hdfreebeam(hp, j); /* free the beam */ - } - hddone(hp); /* free the section */ + while (hdlist[noutsects] != NULL) { /* load each section */ + /* clump the beams */ + clumpbeams(hdlist[noutsects], 0, BKBSIZE*1024, addclump); + hddone(hdlist[noutsects]); /* free the section */ } - close(fd); /* close the file */ + close(fd); /* close input file */ + hdflush(NULL); /* flush output */ } -struct phead { - VIEW vw; - double expos; - short gotview; - short badfmt; - short altprims; -}; - -picheadline(s, ph) /* process picture header line */ -char *s; -struct phead *ph; +int +picheadline( /* process picture header line */ + char *s, + struct phead *ph +) { char fmt[32]; if (formatval(fmt, s)) { ph->badfmt = strcmp(fmt, COLRFMT); - return; + return(0); } if (isprims(s)) { ph->altprims++; /* don't want to deal with this */ - return; + return(0); } if (isexpos(s)) { ph->expos *= exposval(s); - return; + return(0); } if (isview(s)) { ph->gotview += sscanview(&ph->vw, s); - return; + return(0); } + return(0); } -addpicz(pcf, zbf) /* add a picture + depth-buffer */ -char *pcf, *zbf; +void +addpicz( /* add a picture + depth-buffer */ + char *pcf, + char *zbf +) { FILE *pfp; int zfd; @@ -234,7 +327,7 @@ char *pcf, *zbf; int eshft; double emult; RESOLU prs; - FLOAT vl[2]; + RREAL vl[2]; FVECT ro, rd; double aftd; COLOR ctmp; @@ -250,10 +343,10 @@ char *pcf, *zbf; error(SYSTEM, pcf); } /* load picture header */ - copystruct(&phd.vw, &stdview); + phd.vw = stdview; phd.expos = 1.0; phd.badfmt = phd.gotview = phd.altprims = 0; - if (getheader(pfp, picheadline, &phd) < 0 || + if (getheader(pfp, picheadline, (char *)&phd) < 0 || phd.badfmt || !fgetsresolu(&prs, pfp)) { sprintf(errmsg, "bad format for picture file \"%s\"", pcf); error(USER, errmsg); @@ -269,11 +362,11 @@ char *pcf, *zbf; error(WARNING, errmsg); } /* figure out what to do about exposure */ - if (phd.expos < 0.99 | phd.expos > 1.01) { + if ((phd.expos < 0.99) | (phd.expos > 1.01)) { emult = -log(phd.expos)/log(2.); eshft = emult >= 0. ? emult+.5 : emult-.5; emult -= (double)eshft; - if (emult <= 0.01 & emult >= -0.01) + if ((emult <= 0.01) & (emult >= -0.01)) emult = -1.; else { emult = 1./phd.expos; @@ -286,7 +379,7 @@ char *pcf, *zbf; /* allocate buffers */ cscn = (COLR *)malloc(scanlen(&prs)*sizeof(COLR)); zscn = (float *)malloc(scanlen(&prs)*sizeof(float)); - if (cscn == NULL | zscn == NULL) + if ((cscn == NULL) | (zscn == NULL)) error(SYSTEM, "out of memory in addpicz"); /* read and process each scanline */ for (j = 0; j < numscans(&prs); j++) { @@ -318,16 +411,20 @@ char *pcf, *zbf; addray(ro, rd, (double)zscn[i], cscn[i]); } } + /* write output and free beams */ + hdflush(NULL); /* clean up */ - free((char *)cscn); - free((char *)zscn); + free((void *)cscn); + free((void *)zscn); fclose(pfp); close(zfd); } -eputs(s) /* put error message to stderr */ -register char *s; +void +eputs( /* put error message to stderr */ + register char *s +) { static int midline = 0; @@ -345,8 +442,10 @@ register char *s; } -quit(code) /* exit the program gracefully */ -int code; +void +quit( /* exit the program gracefully */ + int code +) { hdsync(NULL, 1); /* write out any buffered data */ exit(code);