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.37 by greg, Sun Apr 5 01:32:01 2015 UTC vs.
Revision 3.53 by greg, Wed Dec 15 01:38:50 2021 UTC

# Line 518 | Line 518 | SDyuv2rgb(double yval, double uprime, double vprime, f
518   /* Query BSDF value and sample hypercube for the given vectors */
519   static int
520   SDqueryTre(const SDTre *sdt, float *coef,
521 <                const FVECT outVec, const FVECT inVec, double *hc)
521 >                const FVECT inVec, const FVECT outVec, double *hc)
522   {
523          const RREAL     *vtmp;
524          float           yval;
525          FVECT           rOutVec;
526 <        double          gridPos[4];
526 >        RREAL           gridPos[4];
527  
528          if (sdt->stc[tt_Y] == NULL)     /* paranoia, I hope */
529                  return 0;
# Line 561 | Line 561 | SDqueryTre(const SDTre *sdt, float *coef,
561                  spinvector(rOutVec, outVec, zvec, -atan2(-inVec[1],-inVec[0]));
562                  gridPos[0] = (.5-FTINY) -
563                                  .5*sqrt(inVec[0]*inVec[0] + inVec[1]*inVec[1]);
564 <                SDdisk2square(gridPos+1, rOutVec[0], rOutVec[1]);
564 >                disk2square(gridPos+1, rOutVec[0], rOutVec[1]);
565          } else if (sdt->stc[tt_Y]->ndim == 4) {
566 <                SDdisk2square(gridPos, -inVec[0], -inVec[1]);
567 <                SDdisk2square(gridPos+2, outVec[0], outVec[1]);
566 >                disk2square(gridPos, -inVec[0], -inVec[1]);
567 >                disk2square(gridPos+2, outVec[0], outVec[1]);
568          } else
569                  return 0;               /* should be internal error */
570                                          /* get BSDF value */
571          yval = SDlookupTre(sdt->stc[tt_Y], gridPos, hc);
572 +        if (coef == NULL)               /* just getting hypercube? */
573 +                return 1;
574          if (sdt->stc[tt_u] == NULL || sdt->stc[tt_v] == NULL) {
575 <                if (coef != NULL) *coef = yval;
575 >                *coef = yval;
576                  return 1;               /* no color */
577          }
576        if (coef == NULL)               /* just getting hypercube? */
577                return 1;
578                                          /* else decode color */
579          SDyuv2rgb(yval, SDlookupTre(sdt->stc[tt_u], gridPos, NULL),
580                          SDlookupTre(sdt->stc[tt_v], gridPos, NULL), coef);
# Line 744 | Line 744 | make_cdist(const SDTre *sdt, const double *invec, int
744   const SDCDst *
745   SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
746   {
747 +        unsigned long   cacheLeft = SDmaxCache;
748          const SDTre     *sdt;
749 <        double          inCoord[2];
749 >        RREAL           inCoord[2];
750          int             i;
751          int             mode;
752 <        SDTreCDst       *cd, *cdlast;
752 >        SDTreCDst       *cd, *cdlast, *cdlimit;
753                                          /* check arguments */
754          if ((inVec == NULL) | (sdc == NULL) ||
755                          (sdt = (SDTre *)sdc->dist) == NULL)
# Line 780 | Line 781 | SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
781                                  .5*sqrt(inVec[0]*inVec[0] + inVec[1]*inVec[1]);
782          } else if (sdt->stc[tt_Y]->ndim == 4) {
783                  if (mode != sdt->sidef) /* use reciprocity? */
784 <                        SDdisk2square(inCoord, inVec[0], inVec[1]);
784 >                        disk2square(inCoord, inVec[0], inVec[1]);
785                  else
786 <                        SDdisk2square(inCoord, -inVec[0], -inVec[1]);
786 >                        disk2square(inCoord, -inVec[0], -inVec[1]);
787          } else
788                  return NULL;            /* should be internal error */
789                                          /* quantize to avoid f.p. errors */
790          for (i = sdt->stc[tt_Y]->ndim - 2; i--; )
791                  inCoord[i] = floor(inCoord[i]/quantum)*quantum + .5*quantum;
792 <        cdlast = NULL;                  /* check for direction in cache list */
792 >        cdlast = cdlimit = NULL;        /* check for direction in cache list */
793 >        /* PLACE MUTEX LOCK HERE FOR THREAD-SAFE */
794          for (cd = (SDTreCDst *)sdc->cdList; cd != NULL;
795                                          cdlast = cd, cd = cd->next) {
796 +                if (cacheLeft) {        /* check cache size limit */
797 +                        long    csiz = sizeof(SDTreCDst) +
798 +                                        sizeof(cd->carr[0])*cd->calen;
799 +                        if (cacheLeft > csiz)
800 +                                cacheLeft -= csiz;
801 +                        else {
802 +                                cdlimit = cdlast;
803 +                                cacheLeft = 0;
804 +                        }
805 +                }
806                  if (cd->sidef != mode)
807                          continue;
808                  for (i = sdt->stc[tt_Y]->ndim - 2; i--; )
# Line 800 | Line 812 | SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
812                  if (i < 0)
813                          break;          /* means we have a match */
814          }
815 <        if (cd == NULL)                 /* need to create new entry? */
815 >        if (cd == NULL) {               /* need to create new entry? */
816 >                if (cdlimit != NULL)    /* exceeded cache size limit? */
817 >                        while ((cd = cdlimit->next) != NULL) {
818 >                                cdlimit->next = cd->next;
819 >                                free(cd);
820 >                        }
821                  cdlast = cd = make_cdist(sdt, inCoord, mode != sdt->sidef);
822 +        }
823          if (cdlast != NULL) {           /* move entry to head of cache list */
824                  cdlast->next = cd->next;
825                  cd->next = (SDTreCDst *)sdc->cdList;
826                  sdc->cdList = (SDCDst *)cd;
827          }
828 +        /* END MUTEX LOCK */
829          return (SDCDst *)cd;            /* ready to go */
830   }
831  
# Line 869 | Line 888 | SDsampTreCDist(FVECT ioVec, double randX, const SDCDst
888          const SDTreCDst *cd = (const SDTreCDst *)cdp;
889          const unsigned  target = randX*cumlmax;
890          bitmask_t       hndx, hcoord[2];
891 <        double          gpos[3], rotangle;
891 >        FVECT           gpos;
892 >        double          rotangle;
893          int             i, iupper, ilower;
894                                          /* check arguments */
895          if ((ioVec == NULL) | (cd == NULL))
# Line 899 | Line 919 | SDsampTreCDist(FVECT ioVec, double randX, const SDCDst
919          for (i = 2; i--; )
920                  gpos[i] = ((double)hcoord[i] + rand()*(1./(RAND_MAX+.5))) /
921                                  (double)((bitmask_t)1 << nBitsC);
922 <        SDsquare2disk(gpos, gpos[0], gpos[1]);
922 >        square2disk(gpos, gpos[0], gpos[1]);
923                                          /* compute Z-coordinate */
924          gpos[2] = 1. - gpos[0]*gpos[0] - gpos[1]*gpos[1];
925          gpos[2] = sqrt(gpos[2]*(gpos[2]>0));
# Line 924 | Line 944 | next_token(char **spp)
944   }
945  
946   /* Advance pointer past matching token (or any token if c==0) */
947 < #define eat_token(spp,c)        (next_token(spp)==(c) ^ !(c) ? *(*(spp))++ : 0)
947 > #define eat_token(spp,c)        ((next_token(spp)==(c)) ^ !(c) ? *(*(spp))++ : 0)
948  
949   /* Count words from this point in string to '}' */
950   static int
# Line 1174 | Line 1194 | SDsubtractTreVal(SDNode *st, float val)
1194   static double
1195   subtract_min_Y(SDNode *st)
1196   {
1197 <        float   vmin;
1197 >        const float     vmaxmin = 1.5/M_PI;
1198 >        float           vmin;
1199                                          /* be sure to skip unused portion */
1200          if (st->ndim == 3) {
1201                  int     n;
1202 <                vmin = 1./M_PI;
1202 >                vmin = vmaxmin;
1203                  if (st->log2GR < 0) {
1204                          for (n = 0; n < 8; n += 2) {
1205                                  float   v = SDgetTreMin(st->u.t[n]);
# Line 1194 | Line 1215 | subtract_min_Y(SDNode *st)
1215          } else                          /* anisotropic covers entire tree */
1216                  vmin = SDgetTreMin(st);
1217  
1218 <        if (vmin <= FTINY)
1219 <                return .0;
1218 >        if ((vmin >= vmaxmin) | (vmin <= .01/M_PI))
1219 >                return .0;              /* not worth bothering about */
1220  
1221          SDsubtractTreVal(st, vmin);
1222  
# Line 1241 | Line 1262 | adjust_utree(float uprime, const double *cmin, double
1262   {
1263          SDextRGBs       *mp = (SDextRGBs *)cptr;
1264          double          cmax[SD_MAXDIM];
1265 +        double          yval;
1266          float           rgb[3];
1267 <        int             ok;
1267 >        C_COLOR         clr;
1268  
1269          if (mp->stc[tt_Y]->ndim == 3) {
1270                  if (cmin[0] + .5*csiz >= .5)
# Line 1253 | Line 1275 | adjust_utree(float uprime, const double *cmin, double
1275          cmax[1] = cmin[1] + csiz;
1276          cmax[2] = cmin[2] + csiz;
1277                                          /* average RGB color over voxel */
1278 <        SDyuv2rgb(SDavgTreBox(mp->stc[tt_Y], cmin, cmax), uprime,
1278 >        SDyuv2rgb(yval=SDavgTreBox(mp->stc[tt_Y], cmin, cmax), uprime,
1279                          SDavgTreBox(mp->stc[tt_v], cmin, cmax), rgb);
1280 <                                        /* subtract minimum */
1281 <        ok = (rgb[0] -= mp->rgb[0]) > 1e-5;
1282 <        ok &= (rgb[1] -= mp->rgb[1]) > 1e-5;
1283 <        ok &= (rgb[2] -= mp->rgb[2]) > 1e-5;
1284 <        if (ok) {                       /* compute new u' for adj. RGB */
1285 <                C_COLOR clr;
1264 <                c_fromSharpRGB(rgb, &clr);
1265 <                uprime = 4.*clr.cx/(-2.*clr.cx + 12.*clr.cy + 3.);
1266 <        } else
1267 <                uprime = 4./3./(-2./3. + 12./3. + 3.);
1280 >                                        /* subtract minimum (& clamp) */
1281 >        if ((rgb[0] -= mp->rgb[0]) < 1e-5*yval) rgb[0] = 1e-5*yval;
1282 >        if ((rgb[1] -= mp->rgb[1]) < 1e-5*yval) rgb[1] = 1e-5*yval;
1283 >        if ((rgb[2] -= mp->rgb[2]) < 1e-5*yval) rgb[2] = 1e-5*yval;
1284 >        c_fromSharpRGB(rgb, &clr);      /* compute new u' for adj. RGB */
1285 >        uprime = 4.*clr.cx/(-2.*clr.cx + 12.*clr.cy + 3.);
1286                                          /* assign in new u' tree */
1287          mp->new_stu = SDsetVoxel(mp->new_stu, mp->stc[tt_Y]->ndim,
1288                                          cmin, csiz, uprime);
# Line 1277 | Line 1295 | adjust_vtree(float vprime, const double *cmin, double
1295   {
1296          SDextRGBs       *mp = (SDextRGBs *)cptr;
1297          double          cmax[SD_MAXDIM];
1298 +        double          yval;
1299          float           rgb[3];
1300 <        int             ok;
1300 >        C_COLOR         clr;
1301  
1302          if (mp->stc[tt_Y]->ndim == 3) {
1303                  if (cmin[0] + .5*csiz >= .5)
# Line 1289 | Line 1308 | adjust_vtree(float vprime, const double *cmin, double
1308          cmax[1] = cmin[1] + csiz;
1309          cmax[2] = cmin[2] + csiz;
1310                                          /* average RGB color over voxel */
1311 <        SDyuv2rgb(SDavgTreBox(mp->stc[tt_Y], cmin, cmax),
1311 >        SDyuv2rgb(yval=SDavgTreBox(mp->stc[tt_Y], cmin, cmax),
1312                          SDavgTreBox(mp->stc[tt_u], cmin, cmax),
1313                          vprime, rgb);
1314 <                                        /* subtract minimum */
1315 <        ok = (rgb[0] -= mp->rgb[0]) > 1e-5;
1316 <        ok &= (rgb[1] -= mp->rgb[1]) > 1e-5;
1317 <        ok &= (rgb[2] -= mp->rgb[2]) > 1e-5;
1318 <        if (ok) {                       /* compute new v' for adj. RGB */
1319 <                C_COLOR clr;
1301 <                c_fromSharpRGB(rgb, &clr);
1302 <                vprime = 9.*clr.cy/(-2.*clr.cx + 12.*clr.cy + 3.);
1303 <        } else
1304 <                vprime = 9./3./(-2./3. + 12./3. + 3.);
1314 >                                        /* subtract minimum (& clamp) */
1315 >        if ((rgb[0] -= mp->rgb[0]) < 1e-5*yval) rgb[0] = 1e-5*yval;
1316 >        if ((rgb[1] -= mp->rgb[1]) < 1e-5*yval) rgb[1] = 1e-5*yval;
1317 >        if ((rgb[2] -= mp->rgb[2]) < 1e-5*yval) rgb[2] = 1e-5*yval;
1318 >        c_fromSharpRGB(rgb, &clr);      /* compute new v' for adj. RGB */
1319 >        vprime = 9.*clr.cy/(-2.*clr.cx + 12.*clr.cy + 3.);
1320                                          /* assign in new v' tree */
1321          mp->new_stv = SDsetVoxel(mp->new_stv, mp->stc[tt_Y]->ndim,
1322                                          cmin, csiz, vprime);
# Line 1320 | Line 1335 | subtract_min_RGB(C_COLOR *cs, SDNode *stc[])
1335          my_min.new_stu = my_min.new_stv = NULL;
1336                                          /* get minimum RGB value */
1337          SDtraverseTre(stc[tt_Y], NULL, 0, get_min_RGB, &my_min);
1338 <        ymin = tt_RGB_coef[0]*my_min.rgb[0] +
1339 <                        tt_RGB_coef[1]*my_min.rgb[1] +
1340 <                                        tt_RGB_coef[2]*my_min.rgb[2];
1341 <        if (ymin <= 1e-5) {
1342 <                *cs = c_dfcolor;
1328 <                return .0;              /* not worth bothering about */
1329 <        }
1330 <                                        /* adjust u' & v' values */
1338 >                                        /* convert to C_COLOR */
1339 >        ymin =  c_fromSharpRGB(my_min.rgb, cs);
1340 >        if ((ymin >= .5*FHUGE) | (ymin <= .01/M_PI))
1341 >                return .0;              /* close to zero or no tree */
1342 >                                        /* adjust u' & v' trees */
1343          SDtraverseTre(stc[tt_u], NULL, 0, adjust_utree, &my_min);
1344          SDtraverseTre(stc[tt_v], NULL, 0, adjust_vtree, &my_min);
1345          SDfreeTre(stc[tt_u]); SDfreeTre(stc[tt_v]);
1346          stc[tt_u] = SDsimplifyTre(my_min.new_stu);
1347          stc[tt_v] = SDsimplifyTre(my_min.new_stv);
1348 <                                        /* finally, subtract Y value */
1348 >                                        /* subtract Y & return hemispherical */
1349          SDsubtractTreVal(stc[tt_Y], ymin);
1350 <                                        /* return color and Y */
1351 <        c_fromSharpRGB(my_min.rgb, cs);
1340 <        return M_PI*ymin;
1350 >
1351 >        return M_PI * ymin;
1352   }
1353  
1354   /* Extract and separate diffuse portion of BSDF */
# Line 1364 | Line 1375 | extract_diffuse(SDValue *dv, SDSpectralDF *df)
1375                  memcpy(df->comp[0].cspec, tt_RGB_prim, sizeof(tt_RGB_prim));
1376                  dv->cieY = subtract_min_RGB(&dv->spec, sdt->stc);
1377          } else {
1378 <                df->comp[0].cspec[0] = c_dfcolor;
1378 >                df->comp[0].cspec[0] = dv->spec = c_dfcolor;
1379                  dv->cieY = subtract_min_Y(sdt->stc[tt_Y]);
1380          }
1381          df->maxHemi -= dv->cieY;        /* adjust maximum hemispherical */
1382 <                                        /* make sure everything is set */
1383 <        c_ccvt(&dv->spec, C_CSXY+C_CSSPEC);
1382 >                                
1383 >        c_ccvt(&dv->spec, C_CSXY);      /* make sure (x,y) is set */
1384   }
1385  
1386   /* Load a variable-resolution BSDF tree from an open XML file */
# Line 1420 | Line 1431 | SDloadTre(SDData *sd, ezxml_t wtl)
1431                                          /* separate diffuse components */
1432          extract_diffuse(&sd->rLambFront, sd->rf);
1433          extract_diffuse(&sd->rLambBack, sd->rb);
1434 <        if (sd->tf != NULL)
1435 <                extract_diffuse(&sd->tLamb, sd->tf);
1436 <        if (sd->tb != NULL)
1437 <                extract_diffuse(&sd->tLamb, sd->tb);
1434 >        extract_diffuse(&sd->tLambFront, sd->tf);
1435 >        if (sd->tb != NULL) {
1436 >                extract_diffuse(&sd->tLambBack, sd->tb);
1437 >                if (sd->tf == NULL)
1438 >                        sd->tLambFront = sd->tLambBack;
1439 >        } else if (sd->tf != NULL)
1440 >                sd->tLambBack = sd->tLambFront;
1441                                          /* return success */
1442          return SDEnone;
1443   }
1444  
1445   /* Variable resolution BSDF methods */
1446 < SDFunc SDhandleTre = {
1446 > const SDFunc SDhandleTre = {
1447          &SDgetTreBSDF,
1448          &SDqueryTreProjSA,
1449          &SDgetTreCDist,

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines