--- ray/src/common/bsdf_t.c 2011/07/07 15:25:09 3.19 +++ ray/src/common/bsdf_t.c 2011/08/22 18:21:05 3.23 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: bsdf_t.c,v 3.19 2011/07/07 15:25:09 greg Exp $"; +static const char RCSid[] = "$Id: bsdf_t.c,v 3.23 2011/08/22 18:21:05 greg Exp $"; #endif /* * bsdf_t.c @@ -26,11 +26,13 @@ typedef int SDtreCallback(float val, const double *cmi /* reference width maximum (1.0) */ static const unsigned iwbits = sizeof(unsigned)*4; -static const unsigned iwmax = (1<<(sizeof(unsigned)*4))-1; +static const unsigned iwmax = 1<<(sizeof(unsigned)*4); /* maximum cumulative value */ static const unsigned cumlmax = ~0; /* constant z-vector */ static const FVECT zvec = {.0, .0, 1.}; + /* quantization value */ +static double quantum = 1./256.; /* Struct used for our distribution-building callback */ typedef struct { @@ -614,15 +616,18 @@ SDgetTreCDist(const FVECT inVec, SDComponent *sdc) if ((inVec == NULL) | (sdc == NULL) || (sdt = (SDTre *)sdc->dist) == NULL) return NULL; - if (sdt->st->ndim == 3) /* isotropic BSDF? */ + if (sdt->st->ndim == 3) { /* isotropic BSDF? */ inCoord[0] = .5 - .5*sqrt(inVec[0]*inVec[0] + inVec[1]*inVec[1]); - else if (sdt->st->ndim == 4) + } else if (sdt->st->ndim == 4) { SDdisk2square(inCoord, -inVec[0], -inVec[1]); - else + } else return NULL; /* should be internal error */ + /* quantize to avoid f.p. errors */ + for (i = sdt->st->ndim - 2; i--; ) + inCoord[i] = floor(inCoord[i]/quantum)*quantum + .5*quantum; cdlast = NULL; /* check for direction in cache list */ for (cd = (SDTreCDst *)sdc->cdList; cd != NULL; - cdlast = cd, cd = (SDTreCDst *)cd->next) { + cdlast = cd, cd = cd->next) { for (i = sdt->st->ndim - 2; i--; ) if ((cd->clim[i][0] > inCoord[i]) | (inCoord[i] >= cd->clim[i][1])) @@ -634,7 +639,7 @@ SDgetTreCDist(const FVECT inVec, SDComponent *sdc) cdlast = cd = make_cdist(sdt, inCoord); if (cdlast != NULL) { /* move entry to head of cache list */ cdlast->next = cd->next; - cd->next = sdc->cdList; + cd->next = (SDTreCDst *)sdc->cdList; sdc->cdList = (SDCDst *)cd; } return (SDCDst *)cd; /* ready to go */ @@ -841,6 +846,8 @@ get_extrema(SDSpectralDF *df) double stepWidth, dhemi, bmin[4], bmax[4]; stepWidth = SDsmallestLeaf(st); + if (quantum > stepWidth) /* adjust quantization factor */ + quantum = stepWidth; df->minProjSA = M_PI*stepWidth*stepWidth; if (stepWidth < .03125) stepWidth = .03125; /* 1/32 resolution good enough */