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

Comparing ray/src/common/bsdf_m.c (file contents):
Revision 3.12 by greg, Sun Apr 24 19:39:21 2011 UTC vs.
Revision 3.27 by greg, Sat Jun 29 21:03:44 2013 UTC

# Line 11 | Line 11 | static const char RCSid[] = "$Id$";
11   *
12   */
13  
14 + #define _USE_MATH_DEFINES
15   #include "rtio.h"
16   #include <stdlib.h>
17   #include <math.h>
# Line 28 | Line 29 | static const char RCSid[] = "$Id$";
29   #define RC_INTERR       (-4)
30   #define RC_MEMERR       (-5)
31  
32 < #define MAXLATS         46              /* maximum number of latitudes */
32 <
33 < /* BSDF angle specification */
34 < typedef struct {
35 <        char    name[64];               /* basis name */
36 <        int     nangles;                /* total number of directions */
37 <        struct {
38 <                float   tmin;                   /* starting theta */
39 <                int     nphis;                  /* number of phis (0 term) */
40 <        } lat[MAXLATS+1];               /* latitudes */
41 < } ANGLE_BASIS;
42 <
43 < #define MAXABASES       7               /* limit on defined bases */
44 <
45 < static ANGLE_BASIS      abase_list[MAXABASES] = {
32 > ANGLE_BASIS     abase_list[MAXABASES] = {
33          {
34                  "LBNL/Klems Full", 145,
35 <                { {-5., 1},
35 >                { {0., 1},
36                  {5., 8},
37                  {15., 16},
38                  {25., 20},
# Line 57 | Line 44 | static ANGLE_BASIS     abase_list[MAXABASES] = {
44                  {90., 0} }
45          }, {
46                  "LBNL/Klems Half", 73,
47 <                { {-6.5, 1},
47 >                { {0., 1},
48                  {6.5, 8},
49                  {19.5, 12},
50                  {32.5, 16},
# Line 67 | Line 54 | static ANGLE_BASIS     abase_list[MAXABASES] = {
54                  {90., 0} }
55          }, {
56                  "LBNL/Klems Quarter", 41,
57 <                { {-9., 1},
57 >                { {0., 1},
58                  {9., 8},
59                  {27., 12},
60                  {46., 12},
# Line 76 | Line 63 | static ANGLE_BASIS     abase_list[MAXABASES] = {
63          }
64   };
65  
66 < static int      nabases = 3;    /* current number of defined bases */
66 > int             nabases = 3;            /* current number of defined bases */
67  
68   static int
69   fequal(double a, double b)
# Line 86 | Line 73 | fequal(double a, double b)
73          return (a <= 1e-6) & (a >= -1e-6);
74   }
75  
89 /* Returns the name of the given tag */
90 #ifdef ezxml_name
91 #undef ezxml_name
92 static char *
93 ezxml_name(ezxml_t xml)
94 {
95        if (xml == NULL)
96                return NULL;
97        return xml->name;
98 }
99 #endif
100
76   /* Returns the given tag's character content or empty string if none */
77   #ifdef ezxml_txt
78   #undef ezxml_txt
# Line 157 | Line 132 | SDnewMatrix(int ni, int no)
132   /* Free a BSDF matrix */
133   #define SDfreeMatrix            free
134  
135 < /* get vector for this angle basis index (front exiting) */
136 < static int
135 > /* Get vector for this angle basis index (front exiting) */
136 > int
137   fo_getvec(FVECT v, double ndxr, void *p)
138   {
139          ANGLE_BASIS     *ab = (ANGLE_BASIS *)p;
# Line 183 | Line 158 | fo_getvec(FVECT v, double ndxr, void *p)
158          return RC_GOOD;
159   }
160  
161 < /* get index corresponding to the given vector (front exiting) */
162 < static int
161 > /* Get index corresponding to the given vector (front exiting) */
162 > int
163   fo_getndx(const FVECT v, void *p)
164   {
165          ANGLE_BASIS     *ab = (ANGLE_BASIS *)p;
166          int     li, ndx;
167 <        double  pol, azi, d;
167 >        double  pol, azi;
168  
169          if (v == NULL)
170                  return -1;
171          if ((v[2] < 0) | (v[2] > 1.))
172                  return -1;
173 <        pol = 180.0/M_PI*acos(v[2]);
173 >        pol = 180.0/M_PI*Acos(v[2]);
174          azi = 180.0/M_PI*atan2(v[1], v[0]);
175          if (azi < 0.0) azi += 360.0;
176          for (li = 1; ab->lat[li].tmin <= pol; li++)
# Line 212 | Line 187 | fo_getndx(const FVECT v, void *p)
187   /* compute square of real value */
188   static double sq(double x) { return x*x; }
189  
190 < /* get projected solid angle for this angle basis index (universal) */
191 < static double
190 > /* Get projected solid angle for this angle basis index (universal) */
191 > double
192   io_getohm(int ndx, void *p)
193   {
194          static int      last_li = -1;
# Line 229 | Line 204 | io_getohm(int ndx, void *p)
204          if (li == last_li)                      /* cached latitude? */
205                  return last_ohm;
206          last_li = li;
232        theta1 = M_PI/180. * ab->lat[li+1].tmin;
233        if (ab->lat[li].nphis == 1)             /* special case */
234                return last_ohm = M_PI*(1. - sq(cos(theta1)));
207          theta = M_PI/180. * ab->lat[li].tmin;
208 +        theta1 = M_PI/180. * ab->lat[li+1].tmin;
209          return last_ohm = M_PI*(sq(cos(theta)) - sq(cos(theta1))) /
210                                  (double)ab->lat[li].nphis;
211   }
212  
213 < /* get vector for this angle basis index (back incident) */
214 < static int
213 > /* Get vector for this angle basis index (back incident) */
214 > int
215   bi_getvec(FVECT v, double ndxr, void *p)
216   {
217          if (!fo_getvec(v, ndxr, p))
# Line 251 | Line 224 | bi_getvec(FVECT v, double ndxr, void *p)
224          return RC_GOOD;
225   }
226  
227 < /* get index corresponding to the vector (back incident) */
228 < static int
227 > /* Get index corresponding to the vector (back incident) */
228 > int
229   bi_getndx(const FVECT v, void *p)
230   {
231          FVECT  v2;
# Line 264 | Line 237 | bi_getndx(const FVECT v, void *p)
237          return fo_getndx(v2, p);
238   }
239  
240 < /* get vector for this angle basis index (back exiting) */
241 < static int
240 > /* Get vector for this angle basis index (back exiting) */
241 > int
242   bo_getvec(FVECT v, double ndxr, void *p)
243   {
244          if (!fo_getvec(v, ndxr, p))
# Line 276 | Line 249 | bo_getvec(FVECT v, double ndxr, void *p)
249          return RC_GOOD;
250   }
251  
252 < /* get index corresponding to the vector (back exiting) */
253 < static int
252 > /* Get index corresponding to the vector (back exiting) */
253 > int
254   bo_getndx(const FVECT v, void *p)
255   {
256          FVECT  v2;
# Line 289 | Line 262 | bo_getndx(const FVECT v, void *p)
262          return fo_getndx(v2, p);
263   }
264  
265 < /* get vector for this angle basis index (front incident) */
266 < static int
265 > /* Get vector for this angle basis index (front incident) */
266 > int
267   fi_getvec(FVECT v, double ndxr, void *p)
268   {
269          if (!fo_getvec(v, ndxr, p))
# Line 302 | Line 275 | fi_getvec(FVECT v, double ndxr, void *p)
275          return RC_GOOD;
276   }
277  
278 < /* get index corresponding to the vector (front incident) */
279 < static int
278 > /* Get index corresponding to the vector (front incident) */
279 > int
280   fi_getndx(const FVECT v, void *p)
281   {
282          FVECT  v2;
# Line 346 | Line 319 | load_angle_basis(ezxml_t wab)
319                                  ezxml_child(ezxml_child(wbb,
320                                          "ThetaBounds"), "UpperTheta")));
321                  if (!i)
322 <                        abase_list[nabases].lat[i].tmin =
350 <                                        -abase_list[nabases].lat[i+1].tmin;
322 >                        abase_list[nabases].lat[0].tmin = 0;
323                  else if (!fequal(atof(ezxml_txt(ezxml_child(ezxml_child(wbb,
324                                          "ThetaBounds"), "LowerTheta"))),
325                                  abase_list[nabases].lat[i].tmin)) {
# Line 413 | Line 385 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
385          SDSpectralDF    *df;
386          SDMat           *dp;
387          char            *sdata;
416        int             tfront;
388          int             inbi, outbi;
389          int             i;
390                                          /* allocate BSDF component */
391          sdata = ezxml_txt(ezxml_child(wdb, "WavelengthDataDirection"));
392 +        if (!sdata)
393 +                return RC_FAIL;
394          /*
395           * Remember that front and back are reversed from WINDOW 6 orientations
423         * Favor their "Front" (incoming light) since that's more often valid
396           */
397 <        tfront = !strcasecmp(sdata, "Transmission Back");
398 <        if (!strcasecmp(sdata, "Transmission Front") ||
399 <                        tfront & (sd->tf == NULL)) {
397 >        if (!strcasecmp(sdata, "Transmission Front")) {
398 >                if (sd->tb != NULL)
399 >                        SDfreeSpectralDF(sd->tb);
400 >                if ((sd->tb = SDnewSpectralDF(1)) == NULL)
401 >                        return RC_MEMERR;
402 >                df = sd->tb;
403 >        } else if (!strcasecmp(sdata, "Transmission Back")) {
404                  if (sd->tf != NULL)
405                          SDfreeSpectralDF(sd->tf);
406                  if ((sd->tf = SDnewSpectralDF(1)) == NULL)
407                          return RC_MEMERR;
408                  df = sd->tf;
409          } else if (!strcasecmp(sdata, "Reflection Front")) {
410 <                if (sd->rb != NULL)     /* note back-front reversal */
410 >                if (sd->rb != NULL)
411                          SDfreeSpectralDF(sd->rb);
412                  if ((sd->rb = SDnewSpectralDF(1)) == NULL)
413                          return RC_MEMERR;
414                  df = sd->rb;
415          } else if (!strcasecmp(sdata, "Reflection Back")) {
416 <                if (sd->rf != NULL)     /* note front-back reversal */
416 >                if (sd->rf != NULL)
417                          SDfreeSpectralDF(sd->rf);
418                  if ((sd->rf = SDnewSpectralDF(1)) == NULL)
419                          return RC_MEMERR;
# Line 479 | Line 455 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
455          dp->ib_priv = &abase_list[inbi];
456          dp->ob_priv = &abase_list[outbi];
457          if (df == sd->tf) {
458 <                if (tfront) {
459 <                        dp->ib_vec = &fi_getvec;
460 <                        dp->ib_ndx = &fi_getndx;
461 <                        dp->ob_vec = &bo_getvec;
462 <                        dp->ob_ndx = &bo_getndx;
463 <                } else {
464 <                        dp->ib_vec = &bi_getvec;
465 <                        dp->ib_ndx = &bi_getndx;
466 <                        dp->ob_vec = &fo_getvec;
491 <                        dp->ob_ndx = &fo_getndx;
492 <                }
458 >                dp->ib_vec = &fi_getvec;
459 >                dp->ib_ndx = &fi_getndx;
460 >                dp->ob_vec = &bo_getvec;
461 >                dp->ob_ndx = &bo_getndx;
462 >        } else if (df == sd->tb) {
463 >                dp->ib_vec = &bi_getvec;
464 >                dp->ib_ndx = &bi_getndx;
465 >                dp->ob_vec = &fo_getvec;
466 >                dp->ob_ndx = &fo_getndx;
467          } else if (df == sd->rf) {
468                  dp->ib_vec = &fi_getvec;
469                  dp->ib_ndx = &fi_getndx;
# Line 507 | Line 481 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
481          df->comp[0].dist = dp;
482          df->comp[0].func = &SDhandleMtx;
483                                          /* read BSDF data */
484 <        sdata = ezxml_txt(ezxml_child(wdb,"ScatteringData"));
484 >        sdata = ezxml_txt(ezxml_child(wdb, "ScatteringData"));
485          if (!sdata || !*sdata) {
486                  sprintf(SDerrorDetail, "Missing BSDF ScatteringData in '%s'",
487                                  sd->name);
# Line 521 | Line 495 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
495                                          sd->name);
496                          return RC_FORMERR;
497                  }
498 <                while (*sdnext && isspace(*sdnext))
498 >                while (isspace(*sdnext))
499                          sdnext++;
500                  if (*sdnext == ',') sdnext++;
501                  if (rowinc) {
502                          int     r = i/dp->nout;
503 <                        int     c = i - c*dp->nout;
503 >                        int     c = i - r*dp->nout;
504                          mBSDF_value(dp,r,c) = atof(sdata);
505                  } else
506                          dp->bsdf[i] = atof(sdata);
# Line 546 | Line 520 | subtract_min(SDMat *sm)
520          for (i = n; --i; )
521                  if (sm->bsdf[i] < minv)
522                          minv = sm->bsdf[i];
523 +        
524 +        if (minv <= FTINY)
525 +                return .0;
526 +
527          for (i = n; i--; )
528                  sm->bsdf[i] -= minv;
529  
# Line 571 | Line 549 | extract_diffuse(SDValue *dv, SDSpectralDF *df)
549                  c_cmix(&dv->spec, dv->cieY, &dv->spec, ymin, &df->comp[n].cspec[0]);
550                  dv->cieY += ymin;
551          }
552 <        df->maxHemi -= dv->cieY;        /* adjust minimum hemispherical */
552 >        df->maxHemi -= dv->cieY;        /* adjust maximum hemispherical */
553                                          /* make sure everything is set */
554          c_ccvt(&dv->spec, C_CSXY+C_CSSPEC);
555   }
# Line 580 | Line 558 | extract_diffuse(SDValue *dv, SDSpectralDF *df)
558   SDError
559   SDloadMtx(SDData *sd, ezxml_t wtl)
560   {
561 <        ezxml_t                 wld, wdb;
562 <        int                     rowIn;
563 <        struct BSDF_data        *dp;
564 <        char                    *txt;
565 <        int                     rval;
588 <        
561 >        ezxml_t         wld, wdb;
562 >        int             rowIn;
563 >        char            *txt;
564 >        int             rval;
565 >                                        /* basic checks and data ordering */
566          txt = ezxml_txt(ezxml_child(ezxml_child(wtl,
567                          "DataDefinition"), "IncidentDataStructure"));
568          if (txt == NULL || !*txt) {
# Line 604 | Line 581 | SDloadMtx(SDData *sd, ezxml_t wtl)
581                                  sd->name);
582                  return SDEsupport;
583          }
584 <                                /* get angle basis */
585 <        rval = load_angle_basis(ezxml_child(ezxml_child(wtl,
586 <                                "DataDefinition"), "AngleBasis"));
587 <        if (rval < 0)
588 <                return convert_errcode(rval);
589 <                                /* load BSDF components */
584 >                                        /* get angle bases */
585 >        for (wld = ezxml_child(ezxml_child(wtl, "DataDefinition"), "AngleBasis");
586 >                                wld != NULL; wld = wld->next) {
587 >                rval = load_angle_basis(wld);
588 >                if (rval < 0)
589 >                        return convert_errcode(rval);
590 >        }
591 >                                        /* load BSDF components */
592          for (wld = ezxml_child(wtl, "WavelengthData");
593                                  wld != NULL; wld = wld->next) {
594                  if (strcasecmp(ezxml_txt(ezxml_child(wld,"Wavelength")),
# Line 620 | Line 599 | SDloadMtx(SDData *sd, ezxml_t wtl)
599                          if ((rval = load_bsdf_data(sd, wdb, rowIn)) < 0)
600                                  return convert_errcode(rval);
601          }
602 <                                /* separate diffuse components */
602 >                                        /* separate diffuse components */
603          extract_diffuse(&sd->rLambFront, sd->rf);
604          extract_diffuse(&sd->rLambBack, sd->rb);
605 <        extract_diffuse(&sd->tLamb, sd->tf);
606 <                                /* return success */
605 >        if (sd->tf != NULL)
606 >                extract_diffuse(&sd->tLamb, sd->tf);
607 >        if (sd->tb != NULL)
608 >                extract_diffuse(&sd->tLamb, sd->tb);
609 >                                        /* return success */
610          return SDEnone;
611   }
612  
# Line 682 | Line 664 | SDqueryMtxProjSA(double *psa, const FVECT v1, const RR
664                          psa[0] = out_psa;
665                  break;
666          case SDqueryMin+SDqueryMax:
667 <                if (inc_psa > psa[0])
667 >                if (inc_psa > psa[1])
668                          psa[1] = inc_psa;
669 <                if (out_psa > psa[0])
669 >                if (out_psa > psa[1])
670                          psa[1] = out_psa;
671                  /* fall through */
690        case SDqueryMin:
672          case SDqueryVal:
673                  if (qflags == SDqueryVal)
674                          psa[0] = M_PI;
675 +                /* fall through */
676 +        case SDqueryMin:
677                  if ((inc_psa > 0) & (inc_psa < psa[0]))
678                          psa[0] = inc_psa;
679                  if ((out_psa > 0) & (out_psa < psa[0]))
# Line 761 | Line 744 | SDgetMtxCDist(const FVECT inVec, SDComponent *sdc)
744                  reverse = 1;
745          }
746          cdlast = NULL;                  /* check for it in cache list */
747 <        for (cd = (SDMatCDst *)sdc->cdList;
748 <                                cd != NULL; cd = (SDMatCDst *)cd->next) {
747 >        for (cd = (SDMatCDst *)sdc->cdList; cd != NULL;
748 >                                        cdlast = cd, cd = cd->next)
749                  if (cd->indx == myCD.indx && (cd->calen == myCD.calen) &
750                                          (cd->ob_priv == myCD.ob_priv) &
751                                          (cd->ob_vec == myCD.ob_vec))
752                          break;
770                cdlast = cd;
771        }
753          if (cd == NULL) {               /* need to allocate new entry */
754                  cd = (SDMatCDst *)malloc(sizeof(SDMatCDst) +
755 <                                        myCD.calen*sizeof(myCD.carr[0]));
755 >                                        sizeof(myCD.carr[0])*myCD.calen);
756                  if (cd == NULL)
757                          return NULL;
758                  *cd = myCD;             /* compute cumulative distribution */
# Line 783 | Line 764 | SDgetMtxCDist(const FVECT inVec, SDComponent *sdc)
764          }
765          if (cdlast != NULL) {           /* move entry to head of cache list */
766                  cdlast->next = cd->next;
767 <                cd->next = sdc->cdList;
767 >                cd->next = (SDMatCDst *)sdc->cdList;
768                  sdc->cdList = (SDCDst *)cd;
769          }
770          return (SDCDst *)cd;            /* ready to go */
# Line 803 | Line 784 | SDsampMtxCDist(FVECT ioVec, double randX, const SDCDst
784                                          /* binary search to find index */
785          ilower = 0; iupper = mcd->calen;
786          while ((i = (iupper + ilower) >> 1) != ilower)
787 <                if ((long)target >= (long)mcd->carr[i])
787 >                if (target >= mcd->carr[i])
788                          ilower = i;
789                  else
790                          iupper = i;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines