--- ray/src/rt/ambient.c 2023/01/27 19:57:08 2.116 +++ ray/src/rt/ambient.c 2024/04/05 01:10:26 2.123 @@ -1,4 +1,4 @@ -static const char RCSid[] = "$Id: ambient.c,v 2.116 2023/01/27 19:57:08 greg Exp $"; +static const char RCSid[] = "$Id: ambient.c,v 2.123 2024/04/05 01:10:26 greg Exp $"; /* * ambient.c - routines dealing with ambient (inter-reflected) component. * @@ -44,11 +44,12 @@ static long lastpos = -1; /* last flush position */ #define AMBFLUSH (BUFSIZ/AMBVALSIZ) -#define newambval() (AMBVAL *)malloc(sizeof(AMBVAL)) +#define AVSIZE (sizeof(AMBVAL)-sizeof(SCOLOR)+sizeof(COLORV)*NCSAMP) +#define newambval() (AMBVAL *)malloc(AVSIZE) -#define tfunc(lwr, x, upr) (((x)-(lwr))/((upr)-(lwr))) +#define tfunc(x0, x, x1) (((x)-(x0))/((x1)-(x0))) -static void initambfile(int creat); +static void initambfile(int cre8); static void avsave(AMBVAL *av); static AMBVAL *avstore(AMBVAL *aval); static AMBTREE *newambtree(void); @@ -62,10 +63,10 @@ static void unloadatree(AMBTREE *at, unloadtf_t *f); static void sortambvals(void); static int plugaleak(RAY *r, AMBVAL *ap, FVECT anorm, double ang); -static double sumambient(COLOR acol, RAY *r, FVECT rn, int al, +static double sumambient(SCOLOR acol, RAY *r, FVECT rn, int al, AMBTREE *at, FVECT c0, double s); -static int makeambient(COLOR acol, RAY *r, FVECT rn, int al); -static int extambient(COLOR cr, AMBVAL *ap, FVECT pv, FVECT nv, +static int makeambient(SCOLOR acol, RAY *r, FVECT rn, int al); +static int extambient(SCOLOR cr, AMBVAL *ap, FVECT pv, FVECT nv, FVECT uvw[3]); #ifdef F_SETLKW @@ -229,14 +230,14 @@ ambnotify( /* record new modifier */ void multambient( /* compute ambient component & multiply by coef. */ - COLOR aval, + SCOLOR aval, RAY *r, FVECT nrm ) { static double logAvgAbsorp = 1; static int rdepth = 0; /* ambient recursion */ - COLOR acol, caustic; + SCOLOR acol, caustic; int i, ok; double d, l; @@ -252,9 +253,12 @@ multambient( /* compute ambient component & multiply /* PMAP: Factor in specular-diffuse ambient (caustics) from photon * map, if enabled and ray is primary, else caustic is zero. Continue * with RADIANCE ambient calculation */ - copycolor(caustic, aval); - ambPmapCaustic(caustic, r, rdepth); - +{/* XXX TEMPORARY */ + COLOR pmc; + scolor_color(pmc, aval); + ambPmapCaustic(pmc, r, rdepth); + setscolor(caustic, colval(pmc,RED), colval(pmc,GRN), colval(pmc,BLU)); +} if (ambdiv <= 0) /* no ambient calculation */ goto dumbamb; /* check number of bounces */ @@ -265,15 +269,17 @@ multambient( /* compute ambient component & multiply ambincl != inset(ambset, r->ro->omod)) goto dumbamb; - if (ambacc <= FTINY) { /* no ambient storage */ - FVECT uvd[2]; + if (ambacc <= FTINY) { /* no ambient storage? */ + double rdot = DOT(nrm,r->ron); + int sgn = 1 - 2*(rdot < 0); float dgrad[2], *dgp = NULL; + FVECT uvd[2]; - if (nrm != r->ron && DOT(nrm,r->ron) < 0.9999) + if (sgn*rdot < 0.9999) dgp = dgrad; /* compute rotational grad. */ - copycolor(acol, aval); + copyscolor(acol, aval); rdepth++; - ok = doambient(acol, r, r->rweight, + ok = doambient(acol, r, r->rweight*sgn, uvd, NULL, NULL, dgp, NULL); rdepth--; if (!ok) @@ -283,28 +289,27 @@ multambient( /* compute ambient component & multiply VCROSS(v1, r->ron, nrm); d = 1.0; for (i = 3; i--; ) - d += v1[i] * (dgp[0]*uvd[0][i] + dgp[1]*uvd[1][i]); + d += sgn*v1[i] * (dgp[0]*uvd[0][i] + dgp[1]*uvd[1][i]); if (d >= 0.05) - scalecolor(acol, d); + scalescolor(acol, d); } - copycolor(aval, acol); + copyscolor(aval, acol); /* PMAP: add in caustic */ - addcolor(aval, caustic); + saddscolor(aval, caustic); return; } /* interpolate ambient value */ - setcolor(acol, 0.0, 0.0, 0.0); + scolorblack(acol); d = sumambient(acol, r, nrm, rdepth, &atrunk, thescene.cuorg, thescene.cusize); if (d > FTINY) { - d = 1.0/d; - scalecolor(acol, d); - multcolor(aval, acol); + scalescolor(acol, 1.0/d); + smultscolor(aval, acol); /* PMAP: add in caustic */ - addcolor(aval, caustic); + saddscolor(aval, caustic); return; } @@ -313,19 +318,19 @@ multambient( /* compute ambient component & multiply rdepth--; if (ok) { - multcolor(aval, acol); /* computed new value */ + smultscolor(aval, acol); /* computed new value */ /* PMAP: add in caustic */ - addcolor(aval, caustic); + saddscolor(aval, caustic); return; } dumbamb: /* return global value */ if ((ambvwt <= 0) | (navsum == 0)) { - multcolor(aval, ambval); + smultcolor(aval, ambval); /* PMAP: add in caustic */ - addcolor(aval, caustic); + saddscolor(aval, caustic); return; } @@ -334,11 +339,11 @@ dumbamb: /* return global value */ d = (log(l)*(double)ambvwt + avsum + logAvgAbsorp*navsum) / (double)(ambvwt + navsum); d = exp(d) / l; - scalecolor(aval, d); - multcolor(aval, ambval); /* apply color of ambval */ + scalescolor(aval, d); + smultcolor(aval, ambval); /* apply color of ambval */ } else { d = exp( avsum/(double)navsum + logAvgAbsorp ); - scalecolor(aval, d); /* neutral color */ + scalescolor(aval, d); /* neutral color */ } } @@ -391,7 +396,7 @@ plugaleak(RAY *r, AMBVAL *ap, FVECT anorm, double ang) static double sumambient( /* get interpolated ambient value */ - COLOR acol, + SCOLOR acol, RAY *r, FVECT rn, int al, @@ -401,6 +406,7 @@ sumambient( /* get interpolated ambient value */ ) { /* initial limit is 10 degrees plus ambacc radians */ const double minangle = 10.0 * PI/180.; + const int sgn = 1 - 2*(DOT(r->ron,rn) < 0); double maxangle = minangle + ambacc; double wsum = 0.0; FVECT ck0; @@ -424,7 +430,7 @@ sumambient( /* get interpolated ambient value */ at->kid+i, ck0, s); } /* good enough? */ - if (wsum >= 0.05 && s > minarad*10.0) + if ((wsum >= 0.05) & (s*ambacc > minarad)) return(wsum); } /* adjust maximum angle */ @@ -433,7 +439,7 @@ sumambient( /* get interpolated ambient value */ /* sum this node */ for (av = at->alist; av != NULL; av = av->next) { double u, v, d, delta_r2, delta_t2; - COLOR ct; + SCOLOR sct; FVECT uvw[3]; /* * Ambient level test @@ -445,7 +451,7 @@ sumambient( /* get interpolated ambient value */ * Direction test using unperturbed normal */ decodedir(uvw[2], av->ndir); - d = DOT(uvw[2], r->ron); + d = sgn * DOT(uvw[2], r->ron); if (d <= 0.0) /* >= 90 degrees */ continue; delta_r2 = 2.0 - 2.0*d; /* approx. radians^2 */ @@ -481,12 +487,12 @@ sumambient( /* get interpolated ambient value */ /* * Extrapolate value and compute final weight (hat function) */ - if (!extambient(ct, av, r->rop, rn, uvw)) + if (!extambient(sct, av, r->rop, rn, uvw)) continue; d = tfunc(maxangle, sqrt(delta_r2), 0.0) * tfunc(ambacc, sqrt(delta_t2), 0.0); - scalecolor(ct, d); - addcolor(acol, ct); + scalescolor(sct, d); + saddscolor(acol, sct); wsum += d; } return(wsum); @@ -495,12 +501,13 @@ sumambient( /* get interpolated ambient value */ static int makeambient( /* make a new ambient value for storage */ - COLOR acol, + SCOLOR acol, RAY *r, FVECT rn, int al ) { + int sgn = 1 - 2*(DOT(r->ron,rn) < 0); AMBVAL amb; FVECT uvw[3]; int i; @@ -510,32 +517,32 @@ makeambient( /* make a new ambient value for storage amb.weight *= AVGREFL; if (r->rweight < 0.1*amb.weight) /* heuristic override */ amb.weight = 1.25*r->rweight; - setcolor(acol, AVGREFL, AVGREFL, AVGREFL); + setscolor(acol, AVGREFL, AVGREFL, AVGREFL); /* compute ambient */ - i = doambient(acol, r, amb.weight, + i = doambient(acol, r, amb.weight*sgn, uvw, amb.rad, amb.gpos, amb.gdir, &amb.corral); - scalecolor(acol, 1./AVGREFL); /* undo assumed reflectance */ + scalescolor(acol, 1./AVGREFL); /* undo assumed reflectance */ if (i <= 0 || amb.rad[0] <= FTINY) /* no Hessian or zero radius */ return(i); + uvw[2][0] = sgn*r->ron[0]; /* orient unperturbed normal */ + uvw[2][1] = sgn*r->ron[1]; + uvw[2][2] = sgn*r->ron[2]; /* store value */ VCOPY(amb.pos, r->rop); - amb.ndir = encodedir(r->ron); + amb.ndir = encodedir(uvw[2]); amb.udir = encodedir(uvw[0]); amb.lvl = al; - copycolor(amb.val, acol); - /* insert into tree */ - avsave(&amb); /* and save to file */ - if (rn != r->ron) { /* texture */ - VCOPY(uvw[2], r->ron); + copyscolor(amb.val, acol); + avsave(&amb); /* insert and save to file */ + if (DOT(uvw[2],rn) < 0.9999) /* texture? */ extambient(acol, &amb, r->rop, rn, uvw); - } return(1); } static int extambient( /* extrapolate value at pv, nv */ - COLOR cr, + SCOLOR scr, AMBVAL *ap, FVECT pv, FVECT nv, @@ -567,8 +574,8 @@ extambient( /* extrapolate value at pv, nv */ d = min_d; else if (d > max_d) d = max_d; - copycolor(cr, ap->val); - scalecolor(cr, d); + copyscolor(scr, ap->val); + scalescolor(scr, d); return(d > min_d); } @@ -631,6 +638,7 @@ initambfile( /* initialize ambient file */ if (mybuf == NULL) mybuf = (char *)bmalloc(BUFSIZ+8); setbuf(ambfp, mybuf); +retry: if (cre8) { /* new file */ newheader("RADIANCE", ambfp); fprintf(ambfp, "%s -av %g %g %g -aw %d -ab %d -aa %g ", @@ -643,16 +651,40 @@ initambfile( /* initialize ambient file */ srcsizerat, shadthresh, shadcert); fprintf(ambfp, "-ss %g -st %g -lr %d -lw %g ", specjitter, specthresh, maxdepth, minweight); + fprintf(ambfp, "-cw %g %g -cs %d ", WLPART[3], WLPART[0], NCSAMP); if (octname != NULL) fputs(octname, ambfp); - fputc('\n', ambfp); + fputc('\n', ambfp); /* end of command line, not header! */ fprintf(ambfp, "SOFTWARE= %s\n", VersionID); fputnow(ambfp); + AMB_CNDX = CNDX; /* use current spectral sampling */ + AMB_WLPART = WLPART; + fputwlsplit(WLPART, ambfp); + fputncomp(NCSAMP, ambfp); fputformat(AMBFMT, ambfp); fputc('\n', ambfp); putambmagic(ambfp); - } else if (checkheader(ambfp, AMBFMT, NULL) < 0 || !hasambmagic(ambfp)) - error(USER, "bad ambient file"); + } else if (getheader(ambfp, amb_headline, NULL) < 0 || !hasambmagic(ambfp)) { +#ifndef F_SETLKW + static int ntries = 3; + if (--ntries > 0 && ftell(ambfp) == 0) { + clearerr(ambfp); + sleep(2); + goto retry; + } +#endif + error(USER, "bad/incompatible ambient file"); + } + if ((AMB_CNDX != CNDX) | (AMB_WLPART != WLPART)) { + if (setspectrsamp(AMB_CNDX, AMB_WLPART) < 0) + error(USER, "bad wavelength sampling in ambient file"); + if (AMB_CNDX[3] == CNDX[3] && FABSEQ(AMB_WLPART[0],WLPART[0]) && + FABSEQ(AMB_WLPART[3],WLPART[3])) { + AMB_CNDX = CNDX; + AMB_WLPART = WLPART; /* just the same */ + } else + error(WARNING, "different ambient file wavelength sampling"); + } } @@ -685,10 +717,10 @@ avstore( /* allocate memory and save aval */ if ((av = newambval()) == NULL) error(SYSTEM, "out of memory in avstore"); - *av = *aval; + memcpy(av, aval, AVSIZE); /* AVSIZE <= sizeof(AMBVAL) */ av->next = NULL; nambvals++; - d = bright(av->val); + d = pbright(av->val); if (d > FTINY) { /* add to log sum for averaging */ avsum += log(d); navsum++;