ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/bsdf_t.c
(Generate patch)

Comparing ray/src/common/bsdf_t.c (file contents):
Revision 3.38 by greg, Sun Apr 5 06:02:43 2015 UTC vs.
Revision 3.54 by greg, Tue Jan 25 01:34:20 2022 UTC

# Line 515 | Line 515 | SDyuv2rgb(double yval, double uprime, double vprime, f
515          c_toSharpRGB(&cxy, yval, rgb);
516   }
517  
518 + static double
519 + pfrac(double x)
520 + {
521 +        return( x - (int)x );
522 + }
523 +
524   /* Query BSDF value and sample hypercube for the given vectors */
525   static int
526   SDqueryTre(const SDTre *sdt, float *coef,
527 <                const FVECT outVec, const FVECT inVec, double *hc)
527 >                const FVECT inVec, const FVECT outVec, double *hc)
528   {
529          const RREAL     *vtmp;
530 +        double          hcube[SD_MAXDIM+1];
531          float           yval;
532          FVECT           rOutVec;
533 <        double          gridPos[4];
533 >        RREAL           gridPos[4];
534 >        double          d;
535 >        int             i;
536  
537          if (sdt->stc[tt_Y] == NULL)     /* paranoia, I hope */
538                  return 0;
# Line 561 | Line 570 | SDqueryTre(const SDTre *sdt, float *coef,
570                  spinvector(rOutVec, outVec, zvec, -atan2(-inVec[1],-inVec[0]));
571                  gridPos[0] = (.5-FTINY) -
572                                  .5*sqrt(inVec[0]*inVec[0] + inVec[1]*inVec[1]);
573 <                SDdisk2square(gridPos+1, rOutVec[0], rOutVec[1]);
573 >                disk2square(gridPos+1, rOutVec[0], rOutVec[1]);
574          } else if (sdt->stc[tt_Y]->ndim == 4) {
575 <                SDdisk2square(gridPos, -inVec[0], -inVec[1]);
576 <                SDdisk2square(gridPos+2, outVec[0], outVec[1]);
575 >                disk2square(gridPos, -inVec[0], -inVec[1]);
576 >                disk2square(gridPos+2, outVec[0], outVec[1]);
577          } else
578                  return 0;               /* should be internal error */
579 <                                        /* get BSDF value */
579 >
580 >        if (hc == NULL) hc = hcube;     /* get BSDF value */
581          yval = SDlookupTre(sdt->stc[tt_Y], gridPos, hc);
582 +        if (coef == NULL)               /* just getting hypercube? */
583 +                return 1;
584 +        d = 0;                          /* position-specific perturbation */
585 +        for (i = sdt->stc[tt_Y]->ndim; i--; )
586 +                d += pfrac((2<<i)/(hc[i]+.01687)) - .5;
587 +        yval *= 1. + 1e-4*d;            /* assumes tolerance is > 0.04% */
588          if (sdt->stc[tt_u] == NULL || sdt->stc[tt_v] == NULL) {
589 <                if (coef != NULL) *coef = yval;
589 >                *coef = yval;
590                  return 1;               /* no color */
591          }
576        if (coef == NULL)               /* just getting hypercube? */
577                return 1;
592                                          /* else decode color */
593          SDyuv2rgb(yval, SDlookupTre(sdt->stc[tt_u], gridPos, NULL),
594                          SDlookupTre(sdt->stc[tt_v], gridPos, NULL), coef);
# Line 744 | Line 758 | make_cdist(const SDTre *sdt, const double *invec, int
758   const SDCDst *
759   SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
760   {
761 +        unsigned long   cacheLeft = SDmaxCache;
762          const SDTre     *sdt;
763 <        double          inCoord[2];
763 >        RREAL           inCoord[2];
764          int             i;
765          int             mode;
766 <        SDTreCDst       *cd, *cdlast;
766 >        SDTreCDst       *cd, *cdlast, *cdlimit;
767                                          /* check arguments */
768          if ((inVec == NULL) | (sdc == NULL) ||
769                          (sdt = (SDTre *)sdc->dist) == NULL)
# Line 780 | Line 795 | SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
795                                  .5*sqrt(inVec[0]*inVec[0] + inVec[1]*inVec[1]);
796          } else if (sdt->stc[tt_Y]->ndim == 4) {
797                  if (mode != sdt->sidef) /* use reciprocity? */
798 <                        SDdisk2square(inCoord, inVec[0], inVec[1]);
798 >                        disk2square(inCoord, inVec[0], inVec[1]);
799                  else
800 <                        SDdisk2square(inCoord, -inVec[0], -inVec[1]);
800 >                        disk2square(inCoord, -inVec[0], -inVec[1]);
801          } else
802                  return NULL;            /* should be internal error */
803                                          /* quantize to avoid f.p. errors */
804          for (i = sdt->stc[tt_Y]->ndim - 2; i--; )
805                  inCoord[i] = floor(inCoord[i]/quantum)*quantum + .5*quantum;
806 <        cdlast = NULL;                  /* check for direction in cache list */
806 >        cdlast = cdlimit = NULL;        /* check for direction in cache list */
807 >        /* PLACE MUTEX LOCK HERE FOR THREAD-SAFE */
808          for (cd = (SDTreCDst *)sdc->cdList; cd != NULL;
809                                          cdlast = cd, cd = cd->next) {
810 +                if (cacheLeft) {        /* check cache size limit */
811 +                        long    csiz = sizeof(SDTreCDst) +
812 +                                        sizeof(cd->carr[0])*cd->calen;
813 +                        if (cacheLeft > csiz)
814 +                                cacheLeft -= csiz;
815 +                        else {
816 +                                cdlimit = cdlast;
817 +                                cacheLeft = 0;
818 +                        }
819 +                }
820                  if (cd->sidef != mode)
821                          continue;
822                  for (i = sdt->stc[tt_Y]->ndim - 2; i--; )
# Line 800 | Line 826 | SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
826                  if (i < 0)
827                          break;          /* means we have a match */
828          }
829 <        if (cd == NULL)                 /* need to create new entry? */
829 >        if (cd == NULL) {               /* need to create new entry? */
830 >                if (cdlimit != NULL)    /* exceeded cache size limit? */
831 >                        while ((cd = cdlimit->next) != NULL) {
832 >                                cdlimit->next = cd->next;
833 >                                free(cd);
834 >                        }
835                  cdlast = cd = make_cdist(sdt, inCoord, mode != sdt->sidef);
836 +        }
837          if (cdlast != NULL) {           /* move entry to head of cache list */
838                  cdlast->next = cd->next;
839                  cd->next = (SDTreCDst *)sdc->cdList;
840                  sdc->cdList = (SDCDst *)cd;
841          }
842 +        /* END MUTEX LOCK */
843          return (SDCDst *)cd;            /* ready to go */
844   }
845  
# Line 869 | Line 902 | SDsampTreCDist(FVECT ioVec, double randX, const SDCDst
902          const SDTreCDst *cd = (const SDTreCDst *)cdp;
903          const unsigned  target = randX*cumlmax;
904          bitmask_t       hndx, hcoord[2];
905 <        double          gpos[3], rotangle;
905 >        FVECT           gpos;
906 >        double          rotangle;
907          int             i, iupper, ilower;
908                                          /* check arguments */
909          if ((ioVec == NULL) | (cd == NULL))
# Line 899 | Line 933 | SDsampTreCDist(FVECT ioVec, double randX, const SDCDst
933          for (i = 2; i--; )
934                  gpos[i] = ((double)hcoord[i] + rand()*(1./(RAND_MAX+.5))) /
935                                  (double)((bitmask_t)1 << nBitsC);
936 <        SDsquare2disk(gpos, gpos[0], gpos[1]);
936 >        square2disk(gpos, gpos[0], gpos[1]);
937                                          /* compute Z-coordinate */
938          gpos[2] = 1. - gpos[0]*gpos[0] - gpos[1]*gpos[1];
939          gpos[2] = sqrt(gpos[2]*(gpos[2]>0));
# Line 924 | Line 958 | next_token(char **spp)
958   }
959  
960   /* Advance pointer past matching token (or any token if c==0) */
961 < #define eat_token(spp,c)        (next_token(spp)==(c) ^ !(c) ? *(*(spp))++ : 0)
961 > #define eat_token(spp,c)        ((next_token(spp)==(c)) ^ !(c) ? *(*(spp))++ : 0)
962  
963   /* Count words from this point in string to '}' */
964   static int
# Line 1174 | Line 1208 | SDsubtractTreVal(SDNode *st, float val)
1208   static double
1209   subtract_min_Y(SDNode *st)
1210   {
1211 <        float   vmin;
1211 >        const float     vmaxmin = 1.5/M_PI;
1212 >        float           vmin;
1213                                          /* be sure to skip unused portion */
1214          if (st->ndim == 3) {
1215                  int     n;
1216 <                vmin = 1./M_PI;
1216 >                vmin = vmaxmin;
1217                  if (st->log2GR < 0) {
1218                          for (n = 0; n < 8; n += 2) {
1219                                  float   v = SDgetTreMin(st->u.t[n]);
# Line 1194 | Line 1229 | subtract_min_Y(SDNode *st)
1229          } else                          /* anisotropic covers entire tree */
1230                  vmin = SDgetTreMin(st);
1231  
1232 <        if (vmin <= FTINY)
1233 <                return .0;
1232 >        if ((vmin >= vmaxmin) | (vmin <= .01/M_PI))
1233 >                return .0;              /* not worth bothering about */
1234  
1235          SDsubtractTreVal(st, vmin);
1236  
# Line 1314 | Line 1349 | subtract_min_RGB(C_COLOR *cs, SDNode *stc[])
1349          my_min.new_stu = my_min.new_stv = NULL;
1350                                          /* get minimum RGB value */
1351          SDtraverseTre(stc[tt_Y], NULL, 0, get_min_RGB, &my_min);
1352 <        ymin = tt_RGB_coef[0]*my_min.rgb[0] +
1353 <                        tt_RGB_coef[1]*my_min.rgb[1] +
1354 <                                        tt_RGB_coef[2]*my_min.rgb[2];
1355 <        if (ymin <= 1e-5) {
1356 <                *cs = c_dfcolor;
1322 <                return .0;              /* not worth bothering about */
1323 <        }
1324 <                                        /* adjust u' & v' values */
1352 >                                        /* convert to C_COLOR */
1353 >        ymin =  c_fromSharpRGB(my_min.rgb, cs);
1354 >        if ((ymin >= .5*FHUGE) | (ymin <= .01/M_PI))
1355 >                return .0;              /* close to zero or no tree */
1356 >                                        /* adjust u' & v' trees */
1357          SDtraverseTre(stc[tt_u], NULL, 0, adjust_utree, &my_min);
1358          SDtraverseTre(stc[tt_v], NULL, 0, adjust_vtree, &my_min);
1359          SDfreeTre(stc[tt_u]); SDfreeTre(stc[tt_v]);
1360          stc[tt_u] = SDsimplifyTre(my_min.new_stu);
1361          stc[tt_v] = SDsimplifyTre(my_min.new_stv);
1362 <                                        /* finally, subtract Y value */
1362 >                                        /* subtract Y & return hemispherical */
1363          SDsubtractTreVal(stc[tt_Y], ymin);
1364 <                                        /* return color and Y */
1365 <        c_fromSharpRGB(my_min.rgb, cs);
1334 <        return M_PI*ymin;
1364 >
1365 >        return M_PI * ymin;
1366   }
1367  
1368   /* Extract and separate diffuse portion of BSDF */
# Line 1358 | Line 1389 | extract_diffuse(SDValue *dv, SDSpectralDF *df)
1389                  memcpy(df->comp[0].cspec, tt_RGB_prim, sizeof(tt_RGB_prim));
1390                  dv->cieY = subtract_min_RGB(&dv->spec, sdt->stc);
1391          } else {
1392 <                df->comp[0].cspec[0] = c_dfcolor;
1392 >                df->comp[0].cspec[0] = dv->spec = c_dfcolor;
1393                  dv->cieY = subtract_min_Y(sdt->stc[tt_Y]);
1394          }
1395          df->maxHemi -= dv->cieY;        /* adjust maximum hemispherical */
1396 <                                        /* make sure everything is set */
1397 <        c_ccvt(&dv->spec, C_CSXY+C_CSSPEC);
1396 >                                
1397 >        c_ccvt(&dv->spec, C_CSXY);      /* make sure (x,y) is set */
1398   }
1399  
1400   /* Load a variable-resolution BSDF tree from an open XML file */
# Line 1414 | Line 1445 | SDloadTre(SDData *sd, ezxml_t wtl)
1445                                          /* separate diffuse components */
1446          extract_diffuse(&sd->rLambFront, sd->rf);
1447          extract_diffuse(&sd->rLambBack, sd->rb);
1448 <        if (sd->tf != NULL)
1449 <                extract_diffuse(&sd->tLamb, sd->tf);
1450 <        if (sd->tb != NULL)
1451 <                extract_diffuse(&sd->tLamb, sd->tb);
1448 >        extract_diffuse(&sd->tLambFront, sd->tf);
1449 >        if (sd->tb != NULL) {
1450 >                extract_diffuse(&sd->tLambBack, sd->tb);
1451 >                if (sd->tf == NULL)
1452 >                        sd->tLambFront = sd->tLambBack;
1453 >        } else if (sd->tf != NULL)
1454 >                sd->tLambBack = sd->tLambFront;
1455                                          /* return success */
1456          return SDEnone;
1457   }
1458  
1459   /* Variable resolution BSDF methods */
1460 < SDFunc SDhandleTre = {
1460 > const SDFunc SDhandleTre = {
1461          &SDgetTreBSDF,
1462          &SDqueryTreProjSA,
1463          &SDgetTreCDist,

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines