Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F85012342
rc2.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Sep 26, 04:24
Size
15 KB
Mime Type
text/x-c
Expires
Sat, Sep 28, 04:24 (2 d)
Engine
blob
Format
Raw Data
Handle
21117348
Attached To
R10977 RADIANCE Photon Map
rc2.c
View Options
#ifndef lint
static const char RCSid[] = "$Id: rc2.c,v 2.24 2019/09/04 20:19:51 greg Exp $";
#endif
/*
* Accumulate ray contributions for a set of materials
* File i/o and recovery
*/
#include <ctype.h>
#include "platform.h"
#include "rcontrib.h"
#include "resolu.h"
/* Close output stream and free record */
static void
closestream(void *p)
{
STREAMOUT *sop = (STREAMOUT *)p;
if (sop->ofp != NULL) {
int status = 0;
if (sop->outpipe)
status = pclose(sop->ofp);
else if (sop->ofp != stdout)
status = fclose(sop->ofp);
if (status)
error(SYSTEM, "error closing output stream");
}
free(p);
}
LUTAB ofiletab = LU_SINIT(free,closestream); /* output file table */
#define OF_MODIFIER 01
#define OF_BIN 02
/************************** STREAM & FILE I/O ***************************/
/* Construct output file name and return flags whether modifier/bin present */
static int
ofname(char *oname, const char *ospec, const char *mname, int bn)
{
const char *mnp = NULL;
const char *bnp = NULL;
const char *cp;
if (ospec == NULL)
return(-1);
for (cp = ospec; *cp; cp++) /* check format position(s) */
if (*cp == '%') {
do
++cp;
while (isdigit(*cp));
switch (*cp) {
case '%':
break;
case 's':
if (mnp != NULL)
return(-1);
mnp = cp;
break;
case 'd':
case 'i':
case 'o':
case 'x':
case 'X':
if (bnp != NULL)
return(-1);
bnp = cp;
break;
default:
return(-1);
}
}
if (mnp != NULL) { /* create file name */
if (bnp != NULL) {
if (bnp > mnp)
sprintf(oname, ospec, mname, bn);
else
sprintf(oname, ospec, bn, mname);
return(OF_MODIFIER|OF_BIN);
}
sprintf(oname, ospec, mname);
return(OF_MODIFIER);
}
if (bnp != NULL) {
sprintf(oname, ospec, bn);
return(OF_BIN);
}
strcpy(oname, ospec);
return(0);
}
/* Write header to the given output stream */
static void
printheader(FILE *fout, const char *info)
{
extern char VersionID[];
/* copy octree header */
if (octname[0] == '!') {
newheader("RADIANCE", fout);
fputs(octname+1, fout);
if (octname[strlen(octname)-1] != '\n')
fputc('\n', fout);
} else {
FILE *fin = fopen(octname, (outfmt=='a') ? "r" : "rb");
if (fin == NULL)
quit(1);
checkheader(fin, OCTFMT, fout);
fclose(fin);
}
printargs(gargc-1, gargv, fout); /* add our command */
fprintf(fout, "SOFTWARE= %s\n", VersionID);
fputnow(fout);
fputs("NCOMP=3\n", fout); /* always RGB */
if (info != NULL) /* add extra info if given */
fputs(info, fout);
if ((outfmt == 'f') | (outfmt == 'd'))
fputendian(fout);
fputformat(formstr(outfmt), fout);
fputc('\n', fout); /* empty line ends header */
}
/* Write resolution string to given output stream */
static void
printresolu(FILE *fout, int xr, int yr)
{
if ((xr > 0) & (yr > 0)) /* resolution string */
fprtresolu(xr, yr, fout);
}
/* Get output stream pointer (open and write header if new and noopen==0) */
STREAMOUT *
getostream(const char *ospec, const char *mname, int bn, int noopen)
{
static STREAMOUT stdos;
char info[1024];
int ofl;
char oname[1024];
LUENT *lep;
STREAMOUT *sop;
char *cp;
if (ospec == NULL) { /* use stdout? */
if (!noopen & !using_stdout) {
if (outfmt != 'a')
SET_FILE_BINARY(stdout);
#ifdef getc_unlocked
flockfile(stdout); /* avoid lock/unlock overhead */
#endif
if (header) {
cp = info;
if (yres > 0) {
sprintf(cp, "NROWS=%d\n", yres *
(xres + !xres) );
while (*cp) ++cp;
}
if ((xres <= 0) | (stdos.reclen > 1))
sprintf(cp, "NCOLS=%d\n", stdos.reclen);
printheader(stdout, info);
}
if (stdos.reclen == 1)
printresolu(stdout, xres, yres);
if (waitflush > 0)
fflush(stdout);
stdos.xr = xres; stdos.yr = yres;
using_stdout = 1;
}
stdos.ofp = stdout;
stdos.reclen += noopen;
return(&stdos);
}
ofl = ofname(oname, ospec, mname, bn); /* get output name */
if (ofl < 0) {
sprintf(errmsg, "bad output format '%s'", ospec);
error(USER, errmsg);
}
lep = lu_find(&ofiletab, oname); /* look it up */
if (lep->key == NULL) /* new entry */
lep->key = strcpy((char *)malloc(strlen(oname)+1), oname);
sop = (STREAMOUT *)lep->data;
if (sop == NULL) { /* allocate stream */
sop = (STREAMOUT *)malloc(sizeof(STREAMOUT));
if (sop == NULL)
error(SYSTEM, "out of memory in getostream");
sop->outpipe = (oname[0] == '!');
sop->reclen = 0;
sop->ofp = NULL; /* open iff noopen==0 */
sop->xr = xres; sop->yr = yres;
lep->data = (char *)sop;
if (!sop->outpipe & !force_open & !recover &&
access(oname, F_OK) == 0) {
errno = EEXIST; /* file exists */
goto openerr;
}
} else if (noopen && outfmt == 'c' && /* stream exists to picture? */
(sop->xr > 0) & (sop->yr > 0)) {
if (ofl & OF_BIN)
return(NULL); /* let caller offset bins */
sprintf(errmsg, "output '%s' not a valid picture", oname);
error(WARNING, errmsg);
}
if (!noopen && sop->ofp == NULL) { /* open output stream */
if (oname[0] == '!') /* output to command */
sop->ofp = popen(oname+1, "w");
else /* else open file */
sop->ofp = fopen(oname, "w");
if (sop->ofp == NULL)
goto openerr;
if (outfmt != 'a')
SET_FILE_BINARY(sop->ofp);
#ifdef getc_unlocked
flockfile(sop->ofp); /* avoid lock/unlock overhead */
#endif
if (accumulate > 0) { /* global resolution */
sop->xr = xres; sop->yr = yres;
}
if (header) {
cp = info;
if (ofl & OF_MODIFIER || sop->reclen == 1) {
sprintf(cp, "MODIFIER=%s\n", mname);
while (*cp) ++cp;
}
if (ofl & OF_BIN) {
sprintf(cp, "BIN=%d\n", bn);
while (*cp) ++cp;
}
if (sop->yr > 0) {
sprintf(cp, "NROWS=%d\n", sop->yr *
(sop->xr + !sop->xr) );
while (*cp) ++cp;
}
if ((sop->xr <= 0) | (sop->reclen > 1))
sprintf(cp, "NCOLS=%d\n", sop->reclen);
printheader(sop->ofp, info);
}
if (sop->reclen == 1)
printresolu(sop->ofp, sop->xr, sop->yr);
if (waitflush > 0)
fflush(sop->ofp);
}
sop->reclen += noopen; /* add to length if noopen */
return(sop); /* return output stream */
openerr:
sprintf(errmsg, "cannot open '%s' for writing", oname);
error(SYSTEM, errmsg);
return(NULL); /* pro forma return */
}
/* Get a vector from stdin */
int
getvec(FVECT vec)
{
float vf[3];
double vd[3];
char buf[32];
int i;
switch (inpfmt) {
case 'a': /* ascii */
for (i = 0; i < 3; i++) {
if (fgetword(buf, sizeof(buf), stdin) == NULL ||
!isflt(buf))
return(-1);
vec[i] = atof(buf);
}
break;
case 'f': /* binary float */
if (getbinary((char *)vf, sizeof(float), 3, stdin) != 3)
return(-1);
VCOPY(vec, vf);
break;
case 'd': /* binary double */
if (getbinary((char *)vd, sizeof(double), 3, stdin) != 3)
return(-1);
VCOPY(vec, vd);
break;
default:
error(CONSISTENCY, "botched input format");
}
return(0);
}
/* Put out ray contribution to file */
static void
put_contrib(const DCOLOR cnt, FILE *fout)
{
double sf = 1;
COLOR fv;
COLR cv;
if (accumulate > 1)
sf = 1./(double)accumulate;
switch (outfmt) {
case 'a':
if (accumulate > 1)
fprintf(fout, "%.6e\t%.6e\t%.6e\t",
sf*cnt[0], sf*cnt[1], sf*cnt[2]);
else
fprintf(fout, "%.6e\t%.6e\t%.6e\t",
cnt[0], cnt[1], cnt[2]);
break;
case 'f':
if (accumulate > 1) {
copycolor(fv, cnt);
scalecolor(fv, sf);
} else
copycolor(fv, cnt);
putbinary(fv, sizeof(float), 3, fout);
break;
case 'd':
if (accumulate > 1) {
DCOLOR dv;
copycolor(dv, cnt);
scalecolor(dv, sf);
putbinary(dv, sizeof(double), 3, fout);
} else
putbinary(cnt, sizeof(double), 3, fout);
break;
case 'c':
if (accumulate > 1)
setcolr(cv, sf*cnt[0], sf*cnt[1], sf*cnt[2]);
else
setcolr(cv, cnt[0], cnt[1], cnt[2]);
putbinary(cv, sizeof(cv), 1, fout);
break;
default:
error(INTERNAL, "botched output format");
}
}
/* Output modifier values to appropriate stream(s) */
void
mod_output(MODCONT *mp)
{
STREAMOUT *sop = getostream(mp->outspec, mp->modname, mp->bin0, 0);
int j;
put_contrib(mp->cbin[0], sop->ofp);
if (mp->nbins > 3 && /* minor optimization */
sop == getostream(mp->outspec, mp->modname, mp->bin0+1, 0)) {
for (j = 1; j < mp->nbins; j++)
put_contrib(mp->cbin[j], sop->ofp);
} else {
for (j = 1; j < mp->nbins; j++) {
sop = getostream(mp->outspec, mp->modname, mp->bin0+j, 0);
put_contrib(mp->cbin[j], sop->ofp);
}
}
}
/* callback to output newline to ASCII file and/or flush as requested */
static int
puteol(const LUENT *e, void *p)
{
STREAMOUT *sop = (STREAMOUT *)e->data;
if (outfmt == 'a')
putc('\n', sop->ofp);
if (!waitflush)
fflush(sop->ofp);
if (ferror(sop->ofp)) {
sprintf(errmsg, "write error on file '%s'", e->key);
error(SYSTEM, errmsg);
}
return(0);
}
/* Terminate record output and flush if time */
void
end_record()
{
--waitflush;
lu_doall(&ofiletab, &puteol, NULL);
if (using_stdout & (outfmt == 'a'))
putc('\n', stdout);
if (!waitflush) {
waitflush = (yres > 0) & (xres > 1) ? 0 : xres;
if (using_stdout)
fflush(stdout);
}
}
/************************** PARTIAL RESULTS RECOVERY ***********************/
/* Get ray contribution from previous file */
static int
get_contrib(DCOLOR cnt, FILE *finp)
{
COLOR fv;
COLR cv;
switch (outfmt) {
case 'a':
return(fscanf(finp,"%lf %lf %lf",&cnt[0],&cnt[1],&cnt[2]) == 3);
case 'f':
if (getbinary(fv, sizeof(fv[0]), 3, finp) != 3)
return(0);
copycolor(cnt, fv);
return(1);
case 'd':
return(getbinary(cnt, sizeof(cnt[0]), 3, finp) == 3);
case 'c':
if (getbinary(cv, sizeof(cv), 1, finp) != 1)
return(0);
colr_color(fv, cv);
copycolor(cnt, fv);
return(1);
default:
error(INTERNAL, "botched output format");
}
return(0); /* pro forma return */
}
/* Close output file opened for input */
static int
myclose(const LUENT *e, void *p)
{
STREAMOUT *sop = (STREAMOUT *)e->data;
if (sop->ofp == NULL)
return(0);
fclose(sop->ofp);
sop->ofp = NULL;
return(0);
}
/* Load previously accumulated values */
void
reload_output()
{
int i, j;
MODCONT *mp;
int ofl;
char oname[1024];
char *fmode = "rb";
char *outvfmt;
LUENT *oent;
int xr, yr;
STREAMOUT *sop;
DCOLOR rgbv;
if (outfmt == 'a')
fmode = "r";
outvfmt = formstr(outfmt);
/* reload modifier values */
for (i = 0; i < nmods; i++) {
mp = (MODCONT *)lu_find(&modconttab,modname[i])->data;
if (mp->outspec == NULL)
error(USER, "cannot reload from stdout");
if (mp->outspec[0] == '!')
error(USER, "cannot reload from command");
for (j = 0; j < mp->nbins; j++) { /* load each modifier bin */
ofl = ofname(oname, mp->outspec, mp->modname, mp->bin0+j);
if (ofl < 0)
error(USER, "bad output file specification");
oent = lu_find(&ofiletab, oname);
if (oent->data == NULL)
error(INTERNAL, "unallocated stream in reload_output()");
sop = (STREAMOUT *)oent->data;
if (sop->ofp == NULL) { /* open output as input */
sop->ofp = fopen(oname, fmode);
if (sop->ofp == NULL) {
sprintf(errmsg, "missing reload file '%s'",
oname);
error(WARNING, errmsg);
break;
}
#ifdef getc_unlocked
flockfile(sop->ofp);
#endif
if (header && checkheader(sop->ofp, outvfmt, NULL) != 1) {
sprintf(errmsg, "format mismatch for '%s'",
oname);
error(USER, errmsg);
}
if ((sop->reclen == 1) & (sop->xr > 0) & (sop->yr > 0) &&
(!fscnresolu(&xr, &yr, sop->ofp) ||
(xr != sop->xr) |
(yr != sop->yr))) {
sprintf(errmsg, "resolution mismatch for '%s'",
oname);
error(USER, errmsg);
}
}
/* read in RGB value */
if (!get_contrib(rgbv, sop->ofp)) {
if (!j) {
fclose(sop->ofp);
break; /* ignore empty file */
}
if (j < mp->nbins) {
sprintf(errmsg, "missing data in '%s'",
oname);
error(USER, errmsg);
}
break;
}
copycolor(mp->cbin[j], rgbv);
}
}
lu_doall(&ofiletab, &myclose, NULL); /* close all files */
}
/* Seek on the given output file */
static int
myseeko(const LUENT *e, void *p)
{
STREAMOUT *sop = (STREAMOUT *)e->data;
off_t nbytes = *(off_t *)p;
if (sop->reclen > 1)
nbytes *= (off_t)sop->reclen;
if (fseeko(sop->ofp, nbytes, SEEK_CUR) < 0) {
sprintf(errmsg, "seek error on file '%s'", e->key);
error(SYSTEM, errmsg);
}
return(0);
}
/* Recover output if possible */
void
recover_output()
{
off_t lastout = -1;
int outvsiz, recsiz;
char *outvfmt;
int i, j;
MODCONT *mp;
int ofl;
char oname[1024];
LUENT *oent;
STREAMOUT *sop;
off_t nvals;
int xr, yr;
switch (outfmt) {
case 'a':
error(USER, "cannot recover ASCII output");
return;
case 'f':
outvsiz = sizeof(float)*3;
break;
case 'd':
outvsiz = sizeof(double)*3;
break;
case 'c':
outvsiz = sizeof(COLR);
break;
default:
error(INTERNAL, "botched output format");
return;
}
outvfmt = formstr(outfmt);
/* check modifier outputs */
for (i = 0; i < nmods; i++) {
mp = (MODCONT *)lu_find(&modconttab,modname[i])->data;
if (mp->outspec == NULL)
error(USER, "cannot recover from stdout");
if (mp->outspec[0] == '!')
error(USER, "cannot recover from command");
for (j = 0; j < mp->nbins; j++) { /* check each bin's file */
ofl = ofname(oname, mp->outspec, mp->modname, mp->bin0+j);
if (ofl < 0)
error(USER, "bad output file specification");
oent = lu_find(&ofiletab, oname);
if (oent->data == NULL)
error(INTERNAL, "unallocated stream in recover_output()");
sop = (STREAMOUT *)oent->data;
if (sop->ofp != NULL) { /* already open? */
if (ofl & OF_BIN)
continue;
break;
}
/* open output */
sop->ofp = fopen(oname, "rb+");
if (sop->ofp == NULL) {
sprintf(errmsg, "missing recover file '%s'",
oname);
error(WARNING, errmsg);
lastout = 0;
break;
}
nvals = lseek(fileno(sop->ofp), 0, SEEK_END);
if (nvals <= 0) {
lastout = 0; /* empty output, quit here */
fclose(sop->ofp);
break;
}
recsiz = outvsiz * sop->reclen;
lseek(fileno(sop->ofp), 0, SEEK_SET);
if (header && checkheader(sop->ofp, outvfmt, NULL) != 1) {
sprintf(errmsg, "format mismatch for '%s'",
oname);
error(USER, errmsg);
}
if ((sop->reclen == 1) & (sop->xr > 0) & (sop->yr > 0) &&
(!fscnresolu(&xr, &yr, sop->ofp) ||
(xr != sop->xr) |
(yr != sop->yr))) {
sprintf(errmsg, "resolution mismatch for '%s'",
oname);
error(USER, errmsg);
}
nvals = (nvals - (off_t)ftell(sop->ofp)) / recsiz;
if ((lastout < 0) | (nvals < lastout))
lastout = nvals;
if (!(ofl & OF_BIN))
break; /* no bin separation */
}
if (!lastout) { /* empty output */
error(WARNING, "no previous data to recover");
/* reclose all outputs */
lu_doall(&ofiletab, &myclose, NULL);
return;
}
}
if (lastout < 0) {
error(WARNING, "no output files to recover");
return;
}
if (raysleft && lastout >= raysleft/accumulate) {
error(WARNING, "output appears to be complete");
/* XXX should read & discard input? */
quit(0);
}
/* seek on all files */
nvals = lastout * outvsiz;
lu_doall(&ofiletab, &myseeko, &nvals);
/* skip repeated input */
lastout *= accumulate;
for (nvals = 0; nvals < lastout; nvals++) {
FVECT vdummy;
if (getvec(vdummy) < 0 || getvec(vdummy) < 0)
error(USER, "unexpected EOF on input");
}
lastray = lastdone = (RNUMBER)lastout;
if (raysleft)
raysleft -= lastray;
}
Event Timeline
Log In to Comment