void getpictcolrs( /* get scanline from picture */ int yoff, COLR *scan, PNODE *p, int xsiz, int ysiz ) { int mx; int my; if (p->kid == NULL) { /* do this node */ setcolr(scan[0], colval(p->v,RED), colval(p->v,GRN), colval(p->v,BLU)); for (mx = 1; mx < xsiz; mx++) copycolr(scan[mx], scan[0]); return; } /* do kids */ mx = xsiz >> 1; my = ysiz >> 1; if (yoff < my) { getpictcolrs(yoff, scan, p->kid+DL, mx, my); getpictcolrs(yoff, scan+mx, p->kid+DR, xsiz-mx, my); } else { getpictcolrs(yoff-my, scan, p->kid+UL, mx, ysiz-my); getpictcolrs(yoff-my, scan+mx, p->kid+UR, xsiz-mx, ysiz-my); } }
static void initambfile( /* initialize ambient file */ int cre8 ) { extern char *progname, *octname; static char *mybuf = NULL; #ifdef F_SETLKW aflock(cre8 ? F_WRLCK : F_RDLCK); #endif SET_FILE_BINARY(ambfp); if (mybuf == NULL) mybuf = (char *)bmalloc(BUFSIZ+8); setbuf(ambfp, mybuf); if (cre8) { /* new file */ newheader("RADIANCE", ambfp); fprintf(ambfp, "%s -av %g %g %g -aw %d -ab %d -aa %g ", progname, colval(ambval,RED), colval(ambval,GRN), colval(ambval,BLU), ambvwt, ambounce, ambacc); fprintf(ambfp, "-ad %d -as %d -ar %d ", ambdiv, ambssamp, ambres); if (octname != NULL) fputs(octname, ambfp); fputc('\n', ambfp); fprintf(ambfp, "SOFTWARE= %s\n", VersionID); fputnow(ambfp); fputformat(AMBFMT, ambfp); fputc('\n', ambfp); putambmagic(ambfp); } else if (checkheader(ambfp, AMBFMT, NULL) < 0 || !hasambmagic(ambfp)) error(USER, "bad ambient file"); }
static void combine(void) /* combine pictures */ { EPNODE *coldef[3], *brtdef; COLOR *scanout; double d; register int i, j; /* check defined variables */ for (j = 0; j < 3; j++) { if (vardefined(vcolout[j])) coldef[j] = eparse(vcolout[j]); else coldef[j] = NULL; } if (vardefined(vbrtout)) brtdef = eparse(vbrtout); else brtdef = NULL; /* allocate scanline */ scanout = (COLOR *)emalloc(xres*sizeof(COLOR)); /* set input position */ yscan = ymax+MIDSCN; /* combine files */ for (ypos = yres-1; ypos >= 0; ypos--) { advance(); varset(vypos, '=', (double)ypos); for (xpos = 0; xpos < xres; xpos++) { xscan = (xpos+.5)*xmax/xres; varset(vxpos, '=', (double)xpos); eclock++; if (brtdef != NULL) { d = evalue(brtdef); if (d < 0.0) d = 0.0; setcolor(scanout[xpos], d, d, d); } else { for (j = 0; j < 3; j++) { if (coldef[j] != NULL) { d = evalue(coldef[j]); } else { d = 0.0; for (i = 0; i < nfiles; i++) d += colval(input[i].scan[MIDSCN][xscan],j); } if (d < 0.0) d = 0.0; colval(scanout[xpos],j) = d; } } } if (fwritescan(scanout, xres, stdout) < 0) { perror("write error"); quit(1); } } efree((char *)scanout); }
/* Return brightness of farthest ambient sample */ static double back_ambval(AMBHEMI *hp, const int n1, const int n2, const int n3) { if (hp->sa[n1].d <= hp->sa[n2].d) { if (hp->sa[n1].d <= hp->sa[n3].d) return(colval(hp->sa[n1].v,CIEY)); return(colval(hp->sa[n3].v,CIEY)); } if (hp->sa[n2].d <= hp->sa[n3].d) return(colval(hp->sa[n2].v,CIEY)); return(colval(hp->sa[n3].v,CIEY)); }
extern double cielum( /* compute (scotopic) luminance of CIE color */ COLOR xyz, int scotopic ) { if (scotopic) /* approximate */ return(colval(xyz,CIEY) * (1.33*(1. + (colval(xyz,CIEY)+colval(xyz,CIEZ))/ colval(xyz,CIEX)) - 1.68)); return(colval(xyz,CIEY)); }
static int aclrscan2( /* get an ASCII color scanline */ register COLOR *scan, register int len, FILE *fp ) { while (len-- > 0) { colval(scan[0],RED) = fltv(scanint(fp)); colval(scan[0],GRN) = fltv(scanint(fp)); colval(scan[0],BLU) = fltv(scanint(fp)); scan++; } return(0); }
static double l_expos( /* return picture exposure */ char *nam ) { int fn, n; double d; d = argument(1); if (d <= -0.5 || d >= nfiles+0.5) { errno = EDOM; return(0.0); } if (d < 0.5) return((double)nfiles); fn = d - 0.5; if (nam == vbrtexp) return((*ourbright)(input[fn].expos)); n = 3; while (n--) if (nam == vcolexp[n]) return(colval(input[fn].expos,n)); eputs("Bad call to l_expos()!\n"); quit(1); return 1; /* pro forma return */ }
static void putmapping(void) /* put out color mapping */ { static char cchar[3] = {'r', 'g', 'b'}; register int i, j; /* print brightness mapping */ for (j = 0; j < 3; j++) { printf("%cxa(i) : select(i", cchar[j]); for (i = 0; i < NMBNEU; i++) printf(",%g", colval(bramp[i][0],j)); printf(");\n"); printf("%cya(i) : select(i", cchar[j]); for (i = 0; i < NMBNEU; i++) printf(",%g", colval(bramp[i][1],j)); printf(");\n"); printf("%cfi(n) = if(n-%g, %d, if(%cxa(n+1)-%c, n, %cfi(n+1)));\n", cchar[j], NMBNEU-1.5, NMBNEU-1, cchar[j], cchar[j], cchar[j]); printf("%cndx = %cfi(1);\n", cchar[j], cchar[j]); printf("%c%c = ((%cxa(%cndx+1)-%c)*%cya(%cndx) + ", cchar[j], scanning?'n':'o', cchar[j], cchar[j], cchar[j], cchar[j], cchar[j]); printf("(%c-%cxa(%cndx))*%cya(%cndx+1)) /\n", cchar[j], cchar[j], cchar[j], cchar[j], cchar[j]); printf("\t\t(%cxa(%cndx+1) - %cxa(%cndx)) ;\n", cchar[j], cchar[j], cchar[j], cchar[j]); } /* print color mapping */ if (scanning) { printf("r = ri(1); g = gi(1); b = bi(1);\n"); printf("ro = %g*rn + %g*gn + %g*bn ;\n", solmat[0][0], solmat[0][1], solmat[0][2]); printf("go = %g*rn + %g*gn + %g*bn ;\n", solmat[1][0], solmat[1][1], solmat[1][2]); printf("bo = %g*rn + %g*gn + %g*bn ;\n", solmat[2][0], solmat[2][1], solmat[2][2]); } else { printf("r1 = ri(1); g1 = gi(1); b1 = bi(1);\n"); printf("r = %g*r1 + %g*g1 + %g*b1 ;\n", solmat[0][0], solmat[0][1], solmat[0][2]); printf("g = %g*r1 + %g*g1 + %g*b1 ;\n", solmat[1][0], solmat[1][1], solmat[1][2]); printf("b = %g*r1 + %g*g1 + %g*b1 ;\n", solmat[2][0], solmat[2][1], solmat[2][2]); } }
static double l_colin( /* return color value for picture */ register char *nam ) { int fn; register int n, xoff, yoff; double d; d = argument(1); if (d <= -0.5 || d >= nfiles+0.5) { errno = EDOM; return(0.0); } if (d < 0.5) return((double)nfiles); fn = d - 0.5; xoff = yoff = 0; n = nargum(); if (n >= 2) { d = argument(2); if (d < 0.0) { xoff = d-.5; if (xscan+xoff < 0) xoff = -xscan; } else { xoff = d+.5; if (xscan+xoff >= xmax) xoff = xmax-1-xscan; } } if (n >= 3) { d = argument(3); if (d < 0.0) { yoff = d-.5; if (yoff+MIDSCN < 0) yoff = -MIDSCN; if (yscan+yoff < 0) yoff = -yscan; } else { yoff = d+.5; if (yoff+MIDSCN >= WINSIZ) yoff = WINSIZ-1-MIDSCN; if (yscan+yoff >= ymax) yoff = ymax-1-yscan; } } if (nam == vbrtin) return((*ourbright)(input[fn].scan[MIDSCN+yoff][xscan+xoff])); n = 3; while (n--) if (nam == vcolin[n]) return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n)); eputs("Bad call to l_colin()!\n"); quit(1); return 1; /* pro forma return */ }
static void valtopix(void) /* convert values to a pixel file */ { int dogamma; register COLOR *scanln; int y; register int x; scanln = (COLOR *)malloc(scanlen(&picres)*sizeof(COLOR)); if (scanln == NULL) { fprintf(stderr, "%s: out of memory\n", progname); quit(1); } dogamma = gamcor < .95 || gamcor > 1.05; set_io(); for (y = 0; y < numscans(&picres); y++) { for (x = 0; x < scanlen(&picres); x++) { if (!dataonly) { fscanf(fin, "%*d %*d"); if (fin2 != NULL) { fscanf(fin2, "%*d %*d"); fscanf(fin3, "%*d %*d"); } } if ((*getval)(scanln[x]) < 0) { fprintf(stderr, "%s: read error\n", progname); quit(1); } if (dogamma) setcolor(scanln[x], pow(colval(scanln[x],RED), gamcor), pow(colval(scanln[x],GRN), gamcor), pow(colval(scanln[x],BLU), gamcor)); if (doexposure) multcolor(scanln[x], exposure); } if (fwritescan(scanln, scanlen(&picres), stdout) < 0) { fprintf(stderr, "%s: write error\n", progname); quit(1); } } free((void *)scanln); }
void lightinit() /* initialize lighting */ { GLfloat ambv[4]; if (!dolights) return; glPushAttrib(GL_LIGHTING_BIT); if (expval <= FTINY && bright(ambval) > FTINY) expval = 0.2/bright(ambval); ambv[0] = expval*colval(ambval,RED); ambv[1] = expval*colval(ambval,GRN); ambv[2] = expval*colval(ambval,BLU); ambv[3] = 1.; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambv); glCallList(lightlist = newglist()); rgl_checkerr("in lightinit"); nlights = 0; }
static int bgryscan2( /* get a binary greyscale scanline */ register COLOR *scan, int len, register FILE *fp ) { register int c; while (len-- > 0) { if ((c = getby2(fp)) == EOF) return(-1); colval(scan[0],RED) = colval(scan[0],GRN) = colval(scan[0],BLU) = fltv(c); scan++; } return(0); }
static int setbrdfunc( /* set up brdf function and variables */ BRDFDAT *np ) { FVECT vec; if (setfunc(np->mp, np->pr) == 0) return(0); /* it's OK, setfunc says we're done */ /* else (re)assign special variables */ multv3(vec, np->pnorm, funcxf.xfm); varset("NxP", '=', vec[0]/funcxf.sca); varset("NyP", '=', vec[1]/funcxf.sca); varset("NzP", '=', vec[2]/funcxf.sca); varset("RdotP", '=', np->pdot <= -1.0 ? -1.0 : np->pdot >= 1.0 ? 1.0 : np->pdot); varset("CrP", '=', colval(np->mcolor,RED)); varset("CgP", '=', colval(np->mcolor,GRN)); varset("CbP", '=', colval(np->mcolor,BLU)); return(1); }
static int checkhead( /* deal with line from header */ char *line, void *p ) { char fmt[32]; double d; COLOR ctmp; if (formatval(fmt, line)) { if (!strcmp(fmt, CIEFMT)) mybright = &xyz_bright; else if (!strcmp(fmt, COLRFMT)) mybright = &rgb_bright; else wrongformat++; } else if (original && isexpos(line)) { d = 1.0/exposval(line); scalecolor(exposure, d); doexposure++; } else if (original && iscolcor(line)) { colcorval(ctmp, line); setcolor(exposure, colval(exposure,RED)/colval(ctmp,RED), colval(exposure,GRN)/colval(ctmp,GRN), colval(exposure,BLU)/colval(ctmp,BLU)); doexposure++; } else if (header) fputs(line, stdout); return(0); }
static void ppm2ra2( /* convert 2-byte Pixmap to Radiance picture */ colorscanf_t *getscan ) { COLOR *scanout; double mult; int y; register int x; /* allocate scanline */ scanout = (COLOR *)malloc(xmax*sizeof(COLOR)); if (scanout == NULL) quiterr("out of memory in ppm2ra2"); if (bradj) mult = pow(2., (double)bradj); /* convert image */ for (y = ymax-1; y >= 0; y--) { if ((*getscan)(scanout, xmax, stdin) < 0) quiterr("error reading Pixmap"); for (x = (gamcor>1.01)|(gamcor<0.99)?xmax:0; x--; ) { colval(scanout[x],RED) = pow(colval(scanout[x],RED), gamcor); colval(scanout[x],GRN) = pow(colval(scanout[x],GRN), gamcor); colval(scanout[x],BLU) = pow(colval(scanout[x],BLU), gamcor); } for (x = bradj?xmax:0; x--; ) scalecolor(scanout[x], mult); if (fwritescan(scanout, xmax, stdout) < 0) quiterr("error writing Radiance picture"); } /* free scanline */ free((void *)scanout); }
void printdefaults() /* print default values to stdout */ { #ifdef EVALDRC_HACK /* EvalDRC support */ puts("-A\t\t\t\t# angular source file"); #endif puts("-ae mod\t\t\t\t# exclude modifier"); puts("-aE file\t\t\t\t# exclude modifiers from file"); puts("-ai mod\t\t\t\t# include modifier"); puts("-aI file\t\t\t\t# include modifiers from file"); #ifdef PMAP_EKSPERTZ puts("-api xmin ymin zmin xmax ymax zmax\t# region of interest"); #endif puts("-apg file nPhotons\t\t\t# global photon map"); puts("-apc file nPhotons\t\t\t# caustic photon map"); puts("-apd file nPhotons\t\t\t# direct photon map"); puts("-app file nPhotons bwidth\t\t# precomputed global photon map"); puts("-apv file nPhotons\t\t\t# volume photon map"); puts("-apC file nPhotons\t\t\t# contribution photon map"); printf("-apD %f\t\t\t\t# predistribution factor\n", preDistrib); printf("-apM %d\t\t\t\t\t# max predistrib passes\n", maxPreDistrib); #if 1 /* Kept for backwards compat, will be gradually phased out by -lD, -lr */ printf("-apm %ld\t\t\t\t# limit photon bounces\n", photonMaxBounce); #endif puts("-apo mod\t\t\t\t# photon port modifier"); puts("-apO file\t\t\t\t# photon ports from file"); printf("-apP %f\t\t\t\t# precomputation factor\n", finalGather); printf("-apr %d\t\t\t\t\t# random seed\n", randSeed); puts("-aps mod\t\t\t\t# antimatter sensor modifier"); puts("-apS file\t\t\t\t# antimatter sensors from file"); printf(backvis ? "-bv+\t\t\t\t\t# back face visibility on\n" : "-bv-\t\t\t\t\t# back face visibility off\n"); printf("-dp %.1f\t\t\t\t# PDF samples / sr\n", pdfSamples); printf("-ds %f\t\t\t\t# source partition size ratio\n", srcsizerat); printf("-e %s\t\t\t\t# diagnostics output file\n", diagFile); printf(clobber ? "-fo+\t\t\t\t\t# force overwrite\n" : "-fo-\t\t\t\t\t# do not overwrite\n"); #ifdef PMAP_EKSPERTZ /* NU STUFF for Ze Exspertz! */ printf("-ld %.1f\t\t\t\t\t# limit photon distance\n", photonMaxDist); printf("-lr %ld\t\t\t\t# limit photon bounces\n", photonMaxBounce); #endif printf("-ma %.2f %.2f %.2f\t\t\t# scattering albedo\n", colval(salbedo,RED), colval(salbedo,GRN), colval(salbedo,BLU)); printf("-me %.2e %.2e %.2e\t\t# extinction coefficient\n", colval(cextinction,RED), colval(cextinction,GRN), colval(cextinction,BLU)); printf("-mg %.2f\t\t\t\t# scattering eccentricity\n", seccg); #if NIX /* Multiprocessing on NIX only */ printf("-n %d\t\t\t\t\t# number of parallel processes\n", nproc); #endif printf("-t %-9d\t\t\t\t# time between reports\n", photonRepTime); printf(verbose ? "-v+\t\t\t\t\t# verbose console output\n" : "-v-\t\t\t\t\t# terse console output\n"); }
static int rmx_load_rgbe(RMATRIX *rm, FILE *fp) { COLOR *scan = (COLOR *)malloc(sizeof(COLOR)*rm->ncols); int i, j; if (scan == NULL) return(0); for (i = 0; i < rm->nrows; i++) { if (freadscan(scan, rm->ncols, fp) < 0) { free(scan); return(0); } for (j = rm->ncols; j--; ) { rmx_lval(rm,i,j,0) = colval(scan[j],RED); rmx_lval(rm,i,j,1) = colval(scan[j],GRN); rmx_lval(rm,i,j,2) = colval(scan[j],BLU); } } free(scan); return(1); }
extern void raycontrib( /* compute (cumulative) ray contribution */ RREAL rc[3], const RAY *r, int flags ) { double eext[3]; int i; eext[0] = eext[1] = eext[2] = 0.; rc[0] = rc[1] = rc[2] = 1.; while (r != NULL && r->crtype&flags) { for (i = 3; i--; ) { rc[i] *= colval(r->rcoef,i); eext[i] += r->rot * colval(r->cext,i); } r = r->parent; } for (i = 3; i--; ) rc[i] *= (eext[i] <= FTINY) ? 1. : (eext[i] > 92.) ? 0. : exp(-eext[i]); }
static void mbscan( /* apply macbethcal adj. to scaline */ COLOR *sl, int len, register struct mbc *mb ) { double d; register int i, j; while (len--) { colortrans(sl[0], mb->cmat, sl[0]); clipgamut(sl[0], greypoint(sl[0]), CGAMUT, mb->cmin, mb->cmax); for (i = 0; i < 3; i++) { d = colval(sl[0],i); for (j = 0; j < 4 && mb->xa[i][j+1] <= d; j++) ; colval(sl[0],i) = ( (mb->xa[i][j+1] - d)*mb->ya[i][j] + (d - mb->xa[i][j])*mb->ya[i][j+1] ) / (mb->xa[i][j+1] - mb->xa[i][j]); } sl++; } }
int bigdiff(COLOR c1, COLOR c2, double md) { /* c1 delta c2 > md? */ int i; for (i = 0; i < 3; i++) if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) || colval(c2,i)-colval(c1,i) > md*colval(c1,i)) { return(1); } return(0); }
extern double rgblum( /* compute (scotopic) luminance of RGB color */ COLOR clr, int scotopic ) { if (scotopic) /* approximate */ return( WHTSEFFICACY * (colval(clr,RED)*.062 + colval(clr,GRN)*.608 + colval(clr,BLU)*.330) ); return( WHTEFFICACY * (colval(clr,RED)*inrgb2xyz[1][0] + colval(clr,GRN)*inrgb2xyz[1][1] + colval(clr,BLU)*inrgb2xyz[1][2]) ); }
/* Compute direction gradient from a hemispherical sampling */ static void ambdirgrad(AMBHEMI *hp, FVECT uv[2], float dg[2]) { AMBSAMP *ap; double dgsum[2]; int n; FVECT vd; double gfact; dgsum[0] = dgsum[1] = 0.0; /* sum values times -tan(theta) */ for (ap = hp->sa, n = hp->ns*hp->ns; n--; ap++) { /* use vector for azimuth + 90deg */ VSUB(vd, ap->p, hp->rp->rop); /* brightness over cosine factor */ gfact = colval(ap->v,CIEY) / DOT(hp->rp->ron, vd); /* sine = proj_radius/vd_length */ dgsum[0] -= DOT(uv[1], vd) * gfact; dgsum[1] += DOT(uv[0], vd) * gfact; } dg[0] = dgsum[0] / (hp->ns*hp->ns); dg[1] = dgsum[1] / (hp->ns*hp->ns); }
void traceray( /* trace a single ray */ char *s ) { RAY thisray; char buf[512]; thisray.rmax = 0.0; if (!sscanvec(s, thisray.rorg) || !sscanvec(sskip2(s,3), thisray.rdir)) { int x, y; if (dev->getcur == NULL) return; (*dev->comout)("Pick ray\n"); if ((*dev->getcur)(&x, &y) == ABORT) return; if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir, &ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) { error(COMMAND, "not on image"); return; } } else if (normalize(thisray.rdir) == 0.0) { error(COMMAND, "zero ray direction"); return; } ray_trace(&thisray); if (thisray.ro == NULL) (*dev->comout)("ray hit nothing"); else { OBJREC *mat = NULL; OBJREC *mod = NULL; char matspec[256]; OBJREC *ino; matspec[0] = '\0'; if (thisray.ro->omod != OVOID) { mod = objptr(thisray.ro->omod); mat = findmaterial(mod); } if (thisray.rod < 0.0) strcpy(matspec, "back of "); if (mod != NULL) { strcat(matspec, mod->oname); if (mat != mod && mat != NULL) sprintf(matspec+strlen(matspec), " (%s)", mat->oname); } else strcat(matspec, VOIDID); sprintf(buf, "ray hit %s %s \"%s\"", matspec, ofun[thisray.ro->otype].funame, thisray.ro->oname); if ((ino = objptr(thisray.robj)) != thisray.ro) sprintf(buf+strlen(buf), " in %s \"%s\"", ofun[ino->otype].funame, ino->oname); (*dev->comout)(buf); (*dev->comin)(buf, NULL); if (thisray.rot >= FHUGE) (*dev->comout)("at infinity"); else { sprintf(buf, "at (%.6g %.6g %.6g) (%.6g)", thisray.rop[0], thisray.rop[1], thisray.rop[2], raydistance(&thisray)); (*dev->comout)(buf); } (*dev->comin)(buf, NULL); sprintf(buf, "value (%.5g %.5g %.5g) (%.3gL)", colval(thisray.rcol,RED), colval(thisray.rcol,GRN), colval(thisray.rcol,BLU), luminance(thisray.rcol)); (*dev->comout)(buf); } (*dev->comin)(buf, NULL); }
static void getmbcalfile( /* load macbethcal file */ char *fn, register struct mbc *mb ) { char buf[128]; FILE *fp; int inpflags = 0; register int i; if ((fp = fopen(fn, "r")) == NULL) syserror(fn); while (fgets(buf, sizeof(buf), fp) != NULL) { if (!(inpflags & 01) && sscanf(buf, "rxa(i) : select(i,%f,%f,%f,%f,%f,%f)", &mb->xa[0][0], &mb->xa[0][1], &mb->xa[0][2], &mb->xa[0][3], &mb->xa[0][4], &mb->xa[0][5] ) == 6) inpflags |= 01; else if (!(inpflags & 02) && sscanf(buf, "rya(i) : select(i,%f,%f,%f,%f,%f,%f)", &mb->ya[0][0], &mb->ya[0][1], &mb->ya[0][2], &mb->ya[0][3], &mb->ya[0][4], &mb->ya[0][5] ) == 6) inpflags |= 02; else if (!(inpflags & 04) && sscanf(buf, "gxa(i) : select(i,%f,%f,%f,%f,%f,%f)", &mb->xa[1][0], &mb->xa[1][1], &mb->xa[1][2], &mb->xa[1][3], &mb->xa[1][4], &mb->xa[1][5] ) == 6) inpflags |= 04; else if (!(inpflags & 010) && sscanf(buf, "gya(i) : select(i,%f,%f,%f,%f,%f,%f)", &mb->ya[1][0], &mb->ya[1][1], &mb->ya[1][2], &mb->ya[1][3], &mb->ya[1][4], &mb->ya[1][5] ) == 6) inpflags |= 010; else if (!(inpflags & 020) && sscanf(buf, "bxa(i) : select(i,%f,%f,%f,%f,%f,%f)", &mb->xa[2][0], &mb->xa[2][1], &mb->xa[2][2], &mb->xa[2][3], &mb->xa[2][4], &mb->xa[2][5] ) == 6) inpflags |= 020; else if (!(inpflags & 040) && sscanf(buf, "bya(i) : select(i,%f,%f,%f,%f,%f,%f)", &mb->ya[2][0], &mb->ya[2][1], &mb->ya[2][2], &mb->ya[2][3], &mb->ya[2][4], &mb->ya[2][5] ) == 6) inpflags |= 040; else if (!(inpflags & 0100) && sscanf(buf, "ro = %f*rn + %f*gn + %f*bn", &mb->cmat[0][0], &mb->cmat[0][1], &mb->cmat[0][2]) == 3) inpflags |= 0100; else if (!(inpflags & 0200) && sscanf(buf, "go = %f*rn + %f*gn + %f*bn", &mb->cmat[1][0], &mb->cmat[1][1], &mb->cmat[1][2]) == 3) inpflags |= 0200; else if (!(inpflags & 0400) && sscanf(buf, "bo = %f*rn + %f*gn + %f*bn", &mb->cmat[2][0], &mb->cmat[2][1], &mb->cmat[2][2]) == 3) inpflags |= 0400; } if (inpflags != 0777) { fprintf(stderr, "%s: cannot grok macbethcal file \"%s\" (inpflags==0%o)\n", progname, fn, inpflags); exit(1); } fclose(fp); /* compute gamut */ for (i = 0; i < 3; i++) { colval(mb->cmin,i) = mb->xa[i][0] - mb->ya[i][0] * (mb->xa[i][1]-mb->xa[i][0]) / (mb->ya[i][1]-mb->ya[i][0]); colval(mb->cmax,i) = mb->xa[i][4] + (1.-mb->ya[i][4]) * (mb->xa[i][5] - mb->xa[i][4]) / (mb->ya[i][5] - mb->ya[i][4]); } }
static int ambsample( /* initial ambient division sample */ AMBHEMI *hp, int i, int j, int n ) { AMBSAMP *ap = &ambsam(hp,i,j); RAY ar; int hlist[3], ii; double spt[2], zd; /* generate hemispherical sample */ /* ambient coefficient for weight */ if (ambacc > FTINY) setcolor(ar.rcoef, AVGREFL, AVGREFL, AVGREFL); else copycolor(ar.rcoef, hp->acoef); if (rayorigin(&ar, AMBIENT, hp->rp, ar.rcoef) < 0) return(0); if (ambacc > FTINY) { multcolor(ar.rcoef, hp->acoef); scalecolor(ar.rcoef, 1./AVGREFL); } hlist[0] = hp->rp->rno; hlist[1] = j; hlist[2] = i; multisamp(spt, 2, urand(ilhash(hlist,3)+n)); resample: SDsquare2disk(spt, (j+spt[1])/hp->ns, (i+spt[0])/hp->ns); zd = sqrt(1. - spt[0]*spt[0] - spt[1]*spt[1]); for (ii = 3; ii--; ) ar.rdir[ii] = spt[0]*hp->ux[ii] + spt[1]*hp->uy[ii] + zd*hp->rp->ron[ii]; checknorm(ar.rdir); /* avoid coincident samples */ if (!n && ambcollision(hp, i, j, ar.rdir)) { spt[0] = frandom(); spt[1] = frandom(); goto resample; /* reject this sample */ } dimlist[ndims++] = AI(hp,i,j) + 90171; rayvalue(&ar); /* evaluate ray */ ndims--; zd = raydistance(&ar); if (zd <= FTINY) return(0); /* should never happen */ multcolor(ar.rcol, ar.rcoef); /* apply coefficient */ if (zd*ap->d < 1.0) /* new/closer distance? */ ap->d = 1.0/zd; if (!n) { /* record first vertex & value */ if (zd > 10.0*thescene.cusize + 1000.) zd = 10.0*thescene.cusize + 1000.; VSUM(ap->p, ar.rorg, ar.rdir, zd); copycolor(ap->v, ar.rcol); } else { /* else update recorded value */ hp->acol[RED] -= colval(ap->v,RED); hp->acol[GRN] -= colval(ap->v,GRN); hp->acol[BLU] -= colval(ap->v,BLU); zd = 1.0/(double)(n+1); scalecolor(ar.rcol, zd); zd *= (double)n; scalecolor(ap->v, zd); addcolor(ap->v, ar.rcol); } addcolor(hp->acol, ap->v); /* add to our sum */ return(1); }
char * material(void) /* get (and print) current material */ { char *mname = "mat"; COLOR radrgb, c2; double d; if (c_cmname != NULL) mname = c_cmname; if (!c_cmaterial->clock) return(mname); /* already current */ /* else update output */ c_cmaterial->clock = 0; if (c_cmaterial->ed > .1) { /* emitter */ cvtcolor(radrgb, &c_cmaterial->ed_c, emult*c_cmaterial->ed/(PI*WHTEFFICACY)); if (glowdist < FHUGE) { /* do a glow */ fprintf(matfp, "\nvoid glow %s\n0\n0\n", mname); fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU), glowdist); } else { fprintf(matfp, "\nvoid light %s\n0\n0\n", mname); fprintf(matfp, "3 %f %f %f\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU)); } return(mname); } d = c_cmaterial->rd + c_cmaterial->td + c_cmaterial->rs + c_cmaterial->ts; if ((d < 0.) | (d > 1.)) return(NULL); /* check for glass/dielectric */ if (c_cmaterial->nr > 1.1 && c_cmaterial->ts > .25 && c_cmaterial->rs <= .125 && c_cmaterial->td <= .01 && c_cmaterial->rd <= .01 && c_cmaterial->rs_a <= .01 && c_cmaterial->ts_a <= .01) { cvtcolor(radrgb, &c_cmaterial->ts_c, c_cmaterial->ts + c_cmaterial->rs); if (c_cmaterial->sided) { /* dielectric */ colval(radrgb,RED) = pow(colval(radrgb,RED), 1./C_1SIDEDTHICK); colval(radrgb,GRN) = pow(colval(radrgb,GRN), 1./C_1SIDEDTHICK); colval(radrgb,BLU) = pow(colval(radrgb,BLU), 1./C_1SIDEDTHICK); fprintf(matfp, "\nvoid dielectric %s\n0\n0\n", mname); fprintf(matfp, "5 %g %g %g %f 0\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU), c_cmaterial->nr); return(mname); } /* glass */ fprintf(matfp, "\nvoid glass %s\n0\n0\n", mname); fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU), c_cmaterial->nr); return(mname); } /* check for trans */ if (c_cmaterial->td > .01 || c_cmaterial->ts > .01) { double ts, a5, a6; if (c_cmaterial->sided) { ts = sqrt(c_cmaterial->ts); /* approximate */ a5 = .5; } else { ts = c_cmaterial->ts; a5 = 1.; } /* average colors */ d = c_cmaterial->rd + c_cmaterial->td + ts; cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd/d); cvtcolor(c2, &c_cmaterial->td_c, c_cmaterial->td/d); addcolor(radrgb, c2); cvtcolor(c2, &c_cmaterial->ts_c, ts/d); addcolor(radrgb, c2); if (c_cmaterial->rs + ts > .0001) a5 = (c_cmaterial->rs*c_cmaterial->rs_a + ts*a5*c_cmaterial->ts_a) / (c_cmaterial->rs + ts); a6 = (c_cmaterial->td + ts) / (c_cmaterial->rd + c_cmaterial->td + ts); if (a6 < .999) d = c_cmaterial->rd/(1. - c_cmaterial->rs)/(1. - a6); else d = c_cmaterial->td + ts; scalecolor(radrgb, d); fprintf(matfp, "\nvoid trans %s\n0\n0\n", mname); fprintf(matfp, "7 %f %f %f\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU)); fprintf(matfp, "\t%f %f %f %f\n", c_cmaterial->rs, a5, a6, ts/(ts + c_cmaterial->td)); return(mname); } /* check for plastic */ if (c_cmaterial->rs < .1) { cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd/(1.-c_cmaterial->rs)); fprintf(matfp, "\nvoid plastic %s\n0\n0\n", mname); fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU), c_cmaterial->rs, c_cmaterial->rs_a); return(mname); } /* else it's metal */ /* average colors */ cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd); cvtcolor(c2, &c_cmaterial->rs_c, c_cmaterial->rs); addcolor(radrgb, c2); fprintf(matfp, "\nvoid metal %s\n0\n0\n", mname); fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED), colval(radrgb,GRN), colval(radrgb,BLU), c_cmaterial->rs/(c_cmaterial->rd + c_cmaterial->rs), c_cmaterial->rs_a); return(mname); }
int m_dielectric( /* color a ray which hit a dielectric interface */ OBJREC *m, RAY *r ) { double cos1, cos2, nratio; COLOR ctrans; COLOR talb; int hastexture; int flatsurface; double refl, trans; FVECT dnorm; double d1, d2; RAY p; int i; /* PMAP: skip refracted shadow or ambient ray if accounted for in photon map */ if (shadowRayInPmap(r) || ambRayInPmap(r)) return(1); if (m->oargs.nfargs != (m->otype==MAT_DIELECTRIC ? 5 : 8)) objerror(m, USER, "bad arguments"); raytexture(r, m->omod); /* get modifiers */ if ( (hastexture = DOT(r->pert,r->pert) > FTINY*FTINY) ) cos1 = raynormal(dnorm, r); /* perturb normal */ else { VCOPY(dnorm, r->ron); cos1 = r->rod; } flatsurface = r->ro != NULL && isflat(r->ro->otype) && !hastexture | (r->crtype & AMBIENT); /* index of refraction */ if (m->otype == MAT_DIELECTRIC) nratio = m->oargs.farg[3] + m->oargs.farg[4]/MLAMBDA; else nratio = m->oargs.farg[3] / m->oargs.farg[7]; if (cos1 < 0.0) { /* inside */ hastexture = -hastexture; cos1 = -cos1; dnorm[0] = -dnorm[0]; dnorm[1] = -dnorm[1]; dnorm[2] = -dnorm[2]; setcolor(r->cext, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)), -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[2]*colval(r->pcol,BLU))); setcolor(r->albedo, 0., 0., 0.); r->gecc = 0.; if (m->otype == MAT_INTERFACE) { setcolor(ctrans, -mylog(m->oargs.farg[4]*colval(r->pcol,RED)), -mylog(m->oargs.farg[5]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[6]*colval(r->pcol,BLU))); setcolor(talb, 0., 0., 0.); } else { copycolor(ctrans, cextinction); copycolor(talb, salbedo); } } else { /* outside */ nratio = 1.0 / nratio; setcolor(ctrans, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)), -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[2]*colval(r->pcol,BLU))); setcolor(talb, 0., 0., 0.); if (m->otype == MAT_INTERFACE) { setcolor(r->cext, -mylog(m->oargs.farg[4]*colval(r->pcol,RED)), -mylog(m->oargs.farg[5]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[6]*colval(r->pcol,BLU))); setcolor(r->albedo, 0., 0., 0.); r->gecc = 0.; } } d2 = 1.0 - nratio*nratio*(1.0 - cos1*cos1); /* compute cos theta2 */ if (d2 < FTINY) /* total reflection */ refl = 1.0; else { /* refraction occurs */ /* compute Fresnel's equations */ cos2 = sqrt(d2); d1 = cos1; d2 = nratio*cos2; d1 = (d1 - d2) / (d1 + d2); refl = d1 * d1; d1 = 1.0 / cos1; d2 = nratio / cos2; d1 = (d1 - d2) / (d1 + d2); refl += d1 * d1; refl *= 0.5; trans = 1.0 - refl; trans *= nratio*nratio; /* solid angle ratio */ setcolor(p.rcoef, trans, trans, trans); if (rayorigin(&p, REFRACTED, r, p.rcoef) == 0) { /* compute refracted ray */ d1 = nratio*cos1 - cos2; for (i = 0; i < 3; i++) p.rdir[i] = nratio*r->rdir[i] + d1*dnorm[i]; /* accidental reflection? */ if (hastexture && DOT(p.rdir,r->ron)*hastexture >= -FTINY) { d1 *= (double)hastexture; for (i = 0; i < 3; i++) /* ignore texture */ p.rdir[i] = nratio*r->rdir[i] + d1*r->ron[i]; normalize(p.rdir); /* not exact */ } else checknorm(p.rdir); #ifdef DISPERSE if (m->otype != MAT_DIELECTRIC || r->rod > 0.0 || r->crtype & SHADOW || !directvis || m->oargs.farg[4] == 0.0 || !disperse(m, r, p.rdir, trans, ctrans, talb)) #endif { copycolor(p.cext, ctrans); copycolor(p.albedo, talb); rayvalue(&p); multcolor(p.rcol, p.rcoef); addcolor(r->rcol, p.rcol); /* virtual distance */ if (flatsurface || (1.-FTINY <= nratio) & (nratio <= 1.+FTINY)) r->rxt = r->rot + raydistance(&p); } } } setcolor(p.rcoef, refl, refl, refl); if (!(r->crtype & SHADOW) && rayorigin(&p, REFLECTED, r, p.rcoef) == 0) { /* compute reflected ray */ VSUM(p.rdir, r->rdir, dnorm, 2.*cos1); /* accidental penetration? */ if (hastexture && DOT(p.rdir,r->ron)*hastexture <= FTINY) VSUM(p.rdir, r->rdir, r->ron, 2.*r->rod); checknorm(p.rdir); rayvalue(&p); /* reflected ray value */ multcolor(p.rcol, p.rcoef); /* color contribution */ copycolor(r->mcol, p.rcol); addcolor(r->rcol, p.rcol); /* virtual distance */ r->rmt = r->rot; if (flatsurface) r->rmt += raydistance(&p); } /* rayvalue() computes absorption */ return(1); }
static void dirbrdf( /* compute source contribution */ COLOR cval, /* returned coefficient */ void *nnp, /* material data */ FVECT ldir, /* light source direction */ double omega /* light source size */ ) { BRDFDAT *np = nnp; double ldot; double dtmp; COLOR ctmp; FVECT ldx; static double vldx[5], pt[MAXDIM]; char **sa; int i; #define lddx (vldx+1) setcolor(cval, 0.0, 0.0, 0.0); ldot = DOT(np->pnorm, ldir); if (ldot <= FTINY && ldot >= -FTINY) return; /* too close to grazing */ if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY) return; /* wrong side */ if (ldot > 0.0) { /* * Compute and add diffuse reflected component to returned * color. The diffuse reflected component will always be * modified by the color of the material. */ copycolor(ctmp, np->rdiff); dtmp = ldot * omega / PI; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } else { /* * Diffuse transmitted component. */ copycolor(ctmp, np->tdiff); dtmp = -ldot * omega / PI; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY) return; /* diffuse only */ /* set up function */ setbrdfunc(np); sa = np->mp->oargs.sarg; errno = 0; /* transform light vector */ multv3(ldx, ldir, funcxf.xfm); for (i = 0; i < 3; i++) lddx[i] = ldx[i]/funcxf.sca; lddx[3] = omega; /* compute BRTDF */ if (np->mp->otype == MAT_BRTDF) { if (sa[6][0] == '0') /* special case */ colval(ctmp,RED) = 0.0; else colval(ctmp,RED) = funvalue(sa[6], 4, lddx); if (sa[7][0] == '0') colval(ctmp,GRN) = 0.0; else if (!strcmp(sa[7],sa[6])) colval(ctmp,GRN) = colval(ctmp,RED); else colval(ctmp,GRN) = funvalue(sa[7], 4, lddx); if (!strcmp(sa[8],sa[6])) colval(ctmp,BLU) = colval(ctmp,RED); else if (!strcmp(sa[8],sa[7])) colval(ctmp,BLU) = colval(ctmp,GRN); else colval(ctmp,BLU) = funvalue(sa[8], 4, lddx); dtmp = bright(ctmp); } else if (np->dp == NULL) { dtmp = funvalue(sa[0], 4, lddx); setcolor(ctmp, dtmp, dtmp, dtmp); } else { for (i = 0; i < np->dp->nd; i++) pt[i] = funvalue(sa[3+i], 4, lddx); vldx[0] = datavalue(np->dp, pt); dtmp = funvalue(sa[0], 5, vldx); setcolor(ctmp, dtmp, dtmp, dtmp); } if ((errno == EDOM) | (errno == ERANGE)) { objerror(np->mp, WARNING, "compute error"); return; } if (dtmp <= FTINY) return; if (ldot > 0.0) { /* * Compute reflected non-diffuse component. */ if ((np->mp->otype == MAT_MFUNC) | (np->mp->otype == MAT_MDATA)) multcolor(ctmp, np->mcolor); dtmp = ldot * omega * np->rspec; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } else { /* * Compute transmitted non-diffuse component. */ if ((np->mp->otype == MAT_TFUNC) | (np->mp->otype == MAT_TDATA)) multcolor(ctmp, np->mcolor); dtmp = -ldot * omega * np->tspec; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } #undef lddx }
static void pixtoval(void) /* convert picture to values */ { register COLOR *scanln; int dogamma; COLOR lastc; RREAL hv[2]; int startprim, endprim; long startpos; int y; register int x; scanln = (COLOR *)malloc(scanlen(&picres)*sizeof(COLOR)); if (scanln == NULL) { fprintf(stderr, "%s: out of memory\n", progname); quit(1); } dogamma = gamcor < .95 || gamcor > 1.05; if (putprim == ALL && !interleave) { startprim = RED; endprim = BLU; startpos = ftell(fin); } else { startprim = putprim; endprim = putprim; } for (putprim = startprim; putprim <= endprim; putprim++) { if (putprim != startprim && fseek(fin, startpos, 0)) { fprintf(stderr, "%s: seek error on input file\n", progname); quit(1); } set_io(); setcolor(lastc, 0.0, 0.0, 0.0); for (y = 0; y < numscans(&picres); y++) { if (freadscan(scanln, scanlen(&picres), fin) < 0) { fprintf(stderr, "%s: read error\n", progname); quit(1); } for (x = 0; x < scanlen(&picres); x++) { if (uniq) { if ( colval(scanln[x],RED) == colval(lastc,RED) && colval(scanln[x],GRN) == colval(lastc,GRN) && colval(scanln[x],BLU) == colval(lastc,BLU) ) continue; else copycolor(lastc, scanln[x]); } if (doexposure) multcolor(scanln[x], exposure); if (dogamma) setcolor(scanln[x], pow(colval(scanln[x],RED), 1.0/gamcor), pow(colval(scanln[x],GRN), 1.0/gamcor), pow(colval(scanln[x],BLU), 1.0/gamcor)); if (!dataonly) { pix2loc(hv, &picres, x, y); printf("%7d %7d ", (int)(hv[0]*picres.xr), (int)(hv[1]*picres.yr)); } if ((*putval)(scanln[x]) < 0) { fprintf(stderr, "%s: write error\n", progname); quit(1); } } } } free((void *)scanln); }
int getparam( /* get variable from user */ char *str, char *dsc, int typ, void *p ) { MyUptr ptr = (MyUptr)p; int i0; double d0, d1, d2; char buf[48]; switch (typ) { case 'i': /* integer */ if (sscanf(str, "%d", &i0) != 1) { (*dev->comout)(dsc); sprintf(buf, " (%d): ", ptr->i); (*dev->comout)(buf); (*dev->comin)(buf, NULL); if (sscanf(buf, "%d", &i0) != 1) return(0); } if (ptr->i == i0) return(0); ptr->i = i0; break; case 'r': /* real */ if (sscanf(str, "%lf", &d0) != 1) { (*dev->comout)(dsc); sprintf(buf, " (%.6g): ", ptr->d); (*dev->comout)(buf); (*dev->comin)(buf, NULL); if (sscanf(buf, "%lf", &d0) != 1) return(0); } if (FEQ(ptr->d, d0)) return(0); ptr->d = d0; break; case 'b': /* boolean */ if (sscanf(str, "%1s", buf) != 1) { (*dev->comout)(dsc); sprintf(buf, "? (%c): ", ptr->i ? 'y' : 'n'); (*dev->comout)(buf); (*dev->comin)(buf, NULL); if (buf[0] == '\0') return(0); } if (strchr("yY+1tTnN-0fF", buf[0]) == NULL) return(0); i0 = strchr("yY+1tT", buf[0]) != NULL; if (ptr->i == i0) return(0); ptr->i = i0; break; case 'C': /* color */ if (sscanf(str, "%lf %lf %lf", &d0, &d1, &d2) != 3) { (*dev->comout)(dsc); sprintf(buf, " (%.6g %.6g %.6g): ", colval(ptr->C,RED), colval(ptr->C,GRN), colval(ptr->C,BLU)); (*dev->comout)(buf); (*dev->comin)(buf, NULL); if (sscanf(buf, "%lf %lf %lf", &d0, &d1, &d2) != 3) return(0); } if (FEQ(colval(ptr->C,RED), d0) && FEQ(colval(ptr->C,GRN), d1) && FEQ(colval(ptr->C,BLU), d2)) return(0); setcolor(ptr->C, d0, d1, d2); break; default: return(0); /* shouldn't happen */ } newparam++; return(1); }