--- ray/src/common/bsdf.c 2012/10/13 20:15:43 2.43 +++ ray/src/common/bsdf.c 2021/04/28 00:59:10 2.60 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: bsdf.c,v 2.43 2012/10/13 20:15:43 greg Exp $"; +static const char RCSid[] = "$Id: bsdf.c,v 2.60 2021/04/28 00:59:10 greg Exp $"; #endif /* * bsdf.c @@ -35,6 +35,9 @@ const char *SDerrorEnglish[] = { "Unknown error" }; +/* Pointer to error list in preferred language */ +const char **SDerrorList = SDerrorEnglish; + /* Additional information on last error (ASCII English) */ char SDerrorDetail[256]; @@ -44,12 +47,15 @@ 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; -/* Report any error to the indicated stream (in English) */ +/* Maximum cache size for any given BSDF? */ +unsigned long SDmaxCache = 0; /* 0 == unlimited */ + +/* Report any error to the indicated stream */ SDError -SDreportEnglish(SDError ec, FILE *fp) +SDreportError(SDError ec, FILE *fp) { if (!ec) return SDEnone; @@ -59,7 +65,7 @@ SDreportEnglish(SDError ec, FILE *fp) } if (fp == NULL) return ec; - fputs(SDerrorEnglish[ec], fp); + fputs(SDerrorList[ec], fp); if (SDerrorDetail[0]) { fputs(": ", fp); fputs(SDerrorDetail, fp); @@ -196,7 +202,7 @@ SDloadFile(SDData *sd, const char *fname) } wtl = ezxml_child(ezxml_child(fl, "Optical"), "Layer"); if (wtl == NULL) { - sprintf(SDerrorDetail, "BSDF \"%s\": no optical layers'", + sprintf(SDerrorDetail, "BSDF \"%s\": no optical layers", sd->name); ezxml_free(fl); return SDEformat; @@ -324,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) @@ -375,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 */ @@ -419,15 +429,17 @@ 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) { - SDreportEnglish(SDEmemory, stderr); + SDreportError(SDEmemory, stderr); return NULL; } if (!SDisLoaded(sd) && (ec = SDloadFile(sd, fname))) { - SDreportEnglish(ec, stderr); + SDreportError(ec, stderr); SDfreeCache(sd); - return NULL; + sd = NULL; } + /* END MUTEX LOCK */ return sd; } @@ -485,16 +497,15 @@ SDsampComponent(SDValue *sv, FVECT ioVec, double randX return SDEargument; /* get cumulative distribution */ VCOPY(inVec, ioVec); + sv->cieY = 0; cd = (*sdc->func->getCDist)(inVec, sdc); - if (cd == NULL) - return SDEmemory; - if (cd->cTotal <= 1e-6) { /* anything to sample? */ + if (cd != NULL) + sv->cieY = cd->cTotal; + if (sv->cieY <= 1e-6) { /* nothing to sample? */ sv->spec = c_dfcolor; - sv->cieY = .0; - memset(ioVec, 0, 3*sizeof(double)); + memset(ioVec, 0, sizeof(FVECT)); return SDEnone; } - sv->cieY = cd->cTotal; /* compute sample direction */ ec = (*sdc->func->sampCDist)(ioVec, randX, cd); if (ec) @@ -511,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; } @@ -556,8 +566,7 @@ SDdiffuseSamp(FVECT outVec, int outFront, double randX SDmultiSamp(outVec, 2, randX); SDsquare2disk(outVec, outVec[0], outVec[1]); outVec[2] = 1. - outVec[0]*outVec[0] - outVec[1]*outVec[1]; - if (outVec[2] > 0) /* a bit of paranoia */ - outVec[2] = sqrt(outVec[2]); + outVec[2] = sqrt(outVec[2]*(outVec[2]>0)); if (!outFront) /* going out back? */ outVec[2] = -outVec[2]; } @@ -594,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, @@ -616,7 +626,8 @@ SDsizeBSDF(double *projSA, const FVECT v1, const RREAL projSA[0] = M_PI; if (qflags == SDqueryMin+SDqueryMax) projSA[1] = M_PI; - } + } else if (qflags == SDqueryMin+SDqueryMax && projSA[0] > projSA[1]) + projSA[0] = projSA[1]; return SDEnone; } @@ -642,10 +653,10 @@ 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; @@ -660,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; } @@ -689,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; @@ -742,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; @@ -753,23 +764,19 @@ SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int return SDEmemory; while (j-- > 0) { /* non-diffuse transmission */ cdarr[i+j] = (*tdf->comp[j].func->getCDist)(inVec, &tdf->comp[j]); - if (cdarr[i+j] == NULL) { - free(cdarr); - return SDEmemory; - } + if (cdarr[i+j] == NULL) + cdarr[i+j] = &SDemptyCD; sv->cieY += cdarr[i+j]->cTotal; } while (i-- > 0) { /* non-diffuse reflection */ cdarr[i] = (*rdf->comp[i].func->getCDist)(inVec, &rdf->comp[i]); - if (cdarr[i] == NULL) { - free(cdarr); - return SDEmemory; - } + if (cdarr[i] == NULL) + cdarr[i] = &SDemptyCD; sv->cieY += cdarr[i]->cTotal; } 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 */ @@ -782,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; @@ -815,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; }