--- ray/src/common/bsdf.c 2015/02/08 22:14:50 2.50 +++ ray/src/common/bsdf.c 2021/12/07 23:49:50 2.61 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: bsdf.c,v 2.50 2015/02/08 22:14:50 greg Exp $"; +static const char RCSid[] = "$Id: bsdf.c,v 2.61 2021/12/07 23:49:50 greg Exp $"; #endif /* * bsdf.c @@ -47,9 +47,12 @@ const SDCDst SDemptyCD; /* Cache of loaded BSDFs */ struct SDCache_s *SDcacheList = NULL; -/* Retain BSDFs in cache list */ +/* Retain BSDFs in cache list? */ int SDretainSet = SDretainNone; +/* Maximum cache size for any given BSDF? */ +unsigned long SDmaxCache = 0; /* 0 == unlimited */ + /* Report any error to the indicated stream */ SDError SDreportError(SDError ec, FILE *fp) @@ -327,6 +330,8 @@ SDclipName(char *res, const char *fname) for (cp = fname; *cp; cp++) if (*cp == '.') dot = cp; + else if (*cp == '/') + dot = NULL; if ((dot == NULL) | (dot < fname+2)) dot = cp; if (dot - fname >= SDnameLn) @@ -378,8 +383,10 @@ SDfreeBSDF(SDData *sd) sd->rLambFront.spec.flags = 0; sd->rLambBack.cieY = .0; sd->rLambBack.spec.flags = 0; - sd->tLamb.cieY = .0; - sd->tLamb.spec.flags = 0; + sd->tLambFront.cieY = .0; + sd->tLambFront.spec.flags = 0; + sd->tLambBack.cieY = .0; + sd->tLambBack.spec.flags = 0; } /* Find writeable BSDF by name, or allocate new cache entry if absent */ @@ -422,6 +429,7 @@ SDcacheFile(const char *fname) if (fname == NULL || !*fname) return NULL; SDerrorDetail[0] = '\0'; + /* PLACE MUTEX LOCK HERE FOR THREAD-SAFE */ if ((sd = SDgetCache(fname)) == NULL) { SDreportError(SDEmemory, stderr); return NULL; @@ -429,8 +437,9 @@ SDcacheFile(const char *fname) if (!SDisLoaded(sd) && (ec = SDloadFile(sd, fname))) { SDreportError(ec, stderr); SDfreeCache(sd); - return NULL; + sd = NULL; } + /* END MUTEX LOCK */ return sd; } @@ -494,7 +503,7 @@ SDsampComponent(SDValue *sv, FVECT ioVec, double randX sv->cieY = cd->cTotal; if (sv->cieY <= 1e-6) { /* nothing to sample? */ sv->spec = c_dfcolor; - memset(ioVec, 0, 3*sizeof(double)); + memset(ioVec, 0, sizeof(FVECT)); return SDEnone; } /* compute sample direction */ @@ -502,7 +511,7 @@ SDsampComponent(SDValue *sv, FVECT ioVec, double randX if (ec) return ec; /* get BSDF color */ - n = (*sdc->func->getBSDFs)(coef, ioVec, inVec, sdc); + n = (*sdc->func->getBSDFs)(coef, inVec, ioVec, sdc); if (n <= 0) { strcpy(SDerrorDetail, "BSDF sample value error"); return SDEinternal; @@ -513,8 +522,7 @@ SDsampComponent(SDValue *sv, FVECT ioVec, double randX c_cmix(&sv->spec, d, &sv->spec, coef[n], &sdc->cspec[n]); d += coef[n]; } - /* make sure everything is set */ - c_ccvt(&sv->spec, C_CSXY+C_CSSPEC); + c_ccvt(&sv->spec, C_CSXY); /* make sure (x,y) is set */ return SDEnone; } @@ -552,15 +560,15 @@ SDmultiSamp(double t[], int n, double randX) /* Generate diffuse hemispherical sample */ static void -SDdiffuseSamp(FVECT outVec, int outFront, double randX) +SDdiffuseSamp(FVECT ioVec, int outFront, double randX) { /* convert to position on hemisphere */ - SDmultiSamp(outVec, 2, randX); - SDsquare2disk(outVec, outVec[0], outVec[1]); - outVec[2] = 1. - outVec[0]*outVec[0] - outVec[1]*outVec[1]; - outVec[2] = sqrt(outVec[2]*(outVec[2]>0)); + SDmultiSamp(ioVec, 2, randX); + SDsquare2disk(ioVec, ioVec[0], ioVec[1]); + ioVec[2] = 1. - ioVec[0]*ioVec[0] - ioVec[1]*ioVec[1]; + ioVec[2] = sqrt(ioVec[2]*(ioVec[2]>0)); if (!outFront) /* going out back? */ - outVec[2] = -outVec[2]; + ioVec[2] = -ioVec[2]; } /* Query projected solid angle coverage for non-diffuse BSDF direction */ @@ -595,11 +603,12 @@ SDsizeBSDF(double *projSA, const FVECT v1, const RREAL rdf = sd->rb; tdf = (sd->tb != NULL) ? sd->tb : sd->tf; } - if (v2 != NULL) /* bidirectional? */ + if (v2 != NULL) { /* bidirectional? */ if (v1[2] > 0 ^ v2[2] > 0) rdf = NULL; else tdf = NULL; + } ec = SDEdata; /* run through components */ for (i = (rdf==NULL) ? 0 : rdf->ncomp; i--; ) { ec = (*rdf->comp[i].func->queryProjSA)(projSA, v1, v2, @@ -624,7 +633,7 @@ SDsizeBSDF(double *projSA, const FVECT v1, const RREAL /* Return BSDF for the given incident and scattered ray vectors */ SDError -SDevalBSDF(SDValue *sv, const FVECT outVec, const FVECT inVec, const SDData *sd) +SDevalBSDF(SDValue *sv, const FVECT inVec, const FVECT outVec, const SDData *sd) { int inFront, outFront; SDSpectralDF *sdf; @@ -644,17 +653,17 @@ SDevalBSDF(SDValue *sv, const FVECT outVec, const FVEC *sv = sd->rLambBack; sdf = sd->rb; } else if (inFront) { - *sv = sd->tLamb; + *sv = sd->tLambFront; sdf = (sd->tf != NULL) ? sd->tf : sd->tb; - } else /* inBack */ { - *sv = sd->tLamb; + } else /* outFront & !inFront */ { + *sv = sd->tLambBack; sdf = (sd->tb != NULL) ? sd->tb : sd->tf; } sv->cieY *= 1./M_PI; /* add non-diffuse components */ i = (sdf != NULL) ? sdf->ncomp : 0; while (i-- > 0) { - nch = (*sdf->comp[i].func->getBSDFs)(coef, outVec, inVec, + nch = (*sdf->comp[i].func->getBSDFs)(coef, inVec, outVec, &sdf->comp[i]); while (nch-- > 0) { c_cmix(&sv->spec, sv->cieY, &sv->spec, @@ -662,8 +671,7 @@ SDevalBSDF(SDValue *sv, const FVECT outVec, const FVEC sv->cieY += coef[nch]; } } - /* make sure everything is set */ - c_ccvt(&sv->spec, C_CSXY+C_CSSPEC); + c_ccvt(&sv->spec, C_CSXY); /* make sure (x,y) is set */ return SDEnone; } @@ -691,7 +699,8 @@ SDdirectHemi(const FVECT inVec, int sflags, const SDDa if ((sflags & SDsampDf+SDsampR) != SDsampDf+SDsampR) hsum = .0; if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) - hsum += sd->tLamb.cieY; + hsum += (inVec[2] > 0) ? + sd->tLambFront.cieY : sd->tLambBack.cieY; /* gather non-diffuse components */ i = (((sflags & SDsampSp+SDsampR) == SDsampSp+SDsampR) & (rdf != NULL)) ? rdf->ncomp : 0; @@ -744,7 +753,7 @@ SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int sv->cieY = .0; rdiff = sv->cieY; if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) - sv->cieY += sd->tLamb.cieY; + sv->cieY += inFront ? sd->tLambFront.cieY : sd->tLambBack.cieY; /* gather non-diffuse components */ i = nr = (((sflags & SDsampSp+SDsampR) == SDsampSp+SDsampR) & (rdf != NULL)) ? rdf->ncomp : 0; @@ -767,7 +776,7 @@ SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int } if (sv->cieY <= 1e-6) { /* anything to sample? */ sv->cieY = .0; - memset(ioVec, 0, 3*sizeof(double)); + memset(ioVec, 0, sizeof(FVECT)); return SDEnone; } /* scale random variable */ @@ -780,15 +789,16 @@ SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int randX -= rdiff; /* diffuse transmission? */ if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) { - if (randX < sd->tLamb.cieY) { - sv->spec = sd->tLamb.spec; - SDdiffuseSamp(ioVec, !inFront, randX/sd->tLamb.cieY); + const SDValue *sdt = inFront ? &sd->tLambFront : &sd->tLambBack; + if (randX < sdt->cieY) { + sv->spec = sdt->spec; + SDdiffuseSamp(ioVec, !inFront, randX/sdt->cieY); goto done; } - randX -= sd->tLamb.cieY; + randX -= sdt->cieY; } /* else one of cumulative dist. */ - for (i = 0; i < n && randX > cdarr[i]->cTotal; i++) + for (i = 0; i < n && randX >= cdarr[i]->cTotal; i++) randX -= cdarr[i]->cTotal; if (i >= n) return SDEinternal; @@ -798,7 +808,7 @@ SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int if (ec) return ec; /* compute color */ - j = (*sdc->func->getBSDFs)(coef, ioVec, inVec, sdc); + j = (*sdc->func->getBSDFs)(coef, inVec, ioVec, sdc); if (j <= 0) { sprintf(SDerrorDetail, "BSDF \"%s\" sampling value error", sd->name); @@ -813,8 +823,7 @@ SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int done: if (cdarr != NULL) free(cdarr); - /* make sure everything is set */ - c_ccvt(&sv->spec, C_CSXY+C_CSSPEC); + c_ccvt(&sv->spec, C_CSXY); /* make sure (x,y) is set */ return SDEnone; }