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.23 by greg, Sun Sep 2 15:33:15 2012 UTC vs.
Revision 3.45 by greg, Tue Jan 25 01:34:20 2022 UTC

# Line 13 | Line 13 | static const char RCSid[] = "$Id$";
13  
14   #define _USE_MATH_DEFINES
15   #include "rtio.h"
16 #include <stdlib.h>
16   #include <math.h>
17   #include <ctype.h>
18   #include "ezxml.h"
# Line 29 | Line 28 | static const char RCSid[] = "$Id$";
28   #define RC_INTERR       (-4)
29   #define RC_MEMERR       (-5)
30  
31 < #define MAXLATS         46              /* maximum number of latitudes */
33 <
34 < /* BSDF angle specification */
35 < typedef struct {
36 <        char    name[64];               /* basis name */
37 <        int     nangles;                /* total number of directions */
38 <        struct {
39 <                float   tmin;                   /* starting theta */
40 <                int     nphis;                  /* number of phis (0 term) */
41 <        } lat[MAXLATS+1];               /* latitudes */
42 < } ANGLE_BASIS;
43 <
44 < #define MAXABASES       7               /* limit on defined bases */
45 <
46 < static ANGLE_BASIS      abase_list[MAXABASES] = {
31 > ANGLE_BASIS     abase_list[MAXABASES] = {
32          {
33                  "LBNL/Klems Full", 145,
34                  { {0., 1},
# Line 77 | Line 62 | static ANGLE_BASIS     abase_list[MAXABASES] = {
62          }
63   };
64  
65 < static int      nabases = 3;    /* current number of defined bases */
65 > int             nabases = 3;            /* current number of defined bases */
66  
67 + C_COLOR         mtx_RGB_prim[3];        /* our RGB primaries  */
68 + float           mtx_RGB_coef[3];        /* corresponding Y coefficients */
69 +
70 + enum {mtx_Y, mtx_X, mtx_Z};             /* matrix components (mtx_Y==0) */
71 +
72 + /* check if two real values are near enough to equal */
73   static int
74   fequal(double a, double b)
75   {
# Line 87 | Line 78 | fequal(double a, double b)
78          return (a <= 1e-6) & (a >= -1e-6);
79   }
80  
81 < /* Returns the given tag's character content or empty string if none */
91 < #ifdef ezxml_txt
92 < #undef ezxml_txt
93 < static char *
94 < ezxml_txt(ezxml_t xml)
95 < {
96 <        if (xml == NULL)
97 <                return "";
98 <        return xml->txt;
99 < }
100 < #endif
101 <
102 < /* Convert error to standard BSDF code */
81 > /* convert error to standard BSDF code */
82   static SDError
83   convert_errcode(int ec)
84   {
# Line 120 | Line 99 | convert_errcode(int ec)
99          return SDEunknown;
100   }
101  
102 < /* Allocate a BSDF matrix of the given size */
102 > /* allocate a BSDF matrix of the given size */
103   static SDMat *
104   SDnewMatrix(int ni, int no)
105   {
# Line 144 | Line 123 | SDnewMatrix(int ni, int no)
123   }
124  
125   /* Free a BSDF matrix */
126 < #define SDfreeMatrix            free
126 > void
127 > SDfreeMatrix(void *ptr)
128 > {
129 >        SDMat   *mp = (SDMat *)ptr;
130  
131 < /* get vector for this angle basis index (front exiting) */
132 < static int
131 >        if (mp->chroma != NULL) free(mp->chroma);
132 >        free(ptr);
133 > }
134 >
135 > /* compute square of real value */
136 > static double sq(double x) { return x*x; }
137 >
138 > /* Get vector for this angle basis index (front exiting) */
139 > int
140   fo_getvec(FVECT v, double ndxr, void *p)
141   {
142          ANGLE_BASIS     *ab = (ANGLE_BASIS *)p;
# Line 155 | Line 144 | fo_getvec(FVECT v, double ndxr, void *p)
144          double          randX = ndxr - ndx;
145          double          rx[2];
146          int             li;
147 <        double          pol, azi, d;
147 >        double          azi, d;
148          
149          if ((ndxr < 0) | (ndx >= ab->nangles))
150                  return RC_FAIL;
151          for (li = 0; ndx >= ab->lat[li].nphis; li++)
152                  ndx -= ab->lat[li].nphis;
153          SDmultiSamp(rx, 2, randX);
154 <        pol = M_PI/180.*( (1.-rx[0])*ab->lat[li].tmin +
155 <                                rx[0]*ab->lat[li+1].tmin );
154 >        d = (1. - rx[0])*sq(cos(M_PI/180.*ab->lat[li].tmin)) +
155 >                rx[0]*sq(cos(M_PI/180.*ab->lat[li+1].tmin));
156 >        v[2] = d = sqrt(d);     /* cos(pol) */
157          azi = 2.*M_PI*(ndx + rx[1] - .5)/ab->lat[li].nphis;
168        v[2] = d = cos(pol);
158          d = sqrt(1. - d*d);     /* sin(pol) */
159          v[0] = cos(azi)*d;
160          v[1] = sin(azi)*d;
161          return RC_GOOD;
162   }
163  
164 < /* get index corresponding to the given vector (front exiting) */
165 < static int
164 > /* Get index corresponding to the given vector (front exiting) */
165 > int
166   fo_getndx(const FVECT v, void *p)
167   {
168          ANGLE_BASIS     *ab = (ANGLE_BASIS *)p;
# Line 182 | Line 171 | fo_getndx(const FVECT v, void *p)
171  
172          if (v == NULL)
173                  return -1;
174 <        if ((v[2] < 0) | (v[2] > 1.))
174 >        if ((v[2] < 0) | (v[2] > 1.00001))
175                  return -1;
176 <        pol = 180.0/M_PI*acos(v[2]);
176 >        pol = 180.0/M_PI*Acos(v[2]);
177          azi = 180.0/M_PI*atan2(v[1], v[0]);
178          if (azi < 0.0) azi += 360.0;
179          for (li = 1; ab->lat[li].tmin <= pol; li++)
# Line 198 | Line 187 | fo_getndx(const FVECT v, void *p)
187          return ndx;
188   }
189  
190 < /* compute square of real value */
191 < static double sq(double x) { return x*x; }
203 <
204 < /* get projected solid angle for this angle basis index (universal) */
205 < 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 void     *last_p = NULL;
195          static int      last_li = -1;
196          static double   last_ohm;
197          ANGLE_BASIS     *ab = (ANGLE_BASIS *)p;
# Line 215 | Line 202 | io_getohm(int ndx, void *p)
202                  return -1.;
203          for (li = 0; ndx >= ab->lat[li].nphis; li++)
204                  ndx -= ab->lat[li].nphis;
205 <        if (li == last_li)                      /* cached latitude? */
205 >        if ((p == last_p) & (li == last_li))            /* cached latitude? */
206                  return last_ohm;
207 +        last_p = p;
208          last_li = li;
209          theta = M_PI/180. * ab->lat[li].tmin;
210          theta1 = M_PI/180. * ab->lat[li+1].tmin;
# Line 224 | Line 212 | io_getohm(int ndx, void *p)
212                                  (double)ab->lat[li].nphis;
213   }
214  
215 < /* get vector for this angle basis index (back incident) */
216 < static int
215 > /* Get vector for this angle basis index (back incident) */
216 > int
217   bi_getvec(FVECT v, double ndxr, void *p)
218   {
219          if (!fo_getvec(v, ndxr, p))
# Line 238 | Line 226 | bi_getvec(FVECT v, double ndxr, void *p)
226          return RC_GOOD;
227   }
228  
229 < /* get index corresponding to the vector (back incident) */
230 < static int
229 > /* Get index corresponding to the vector (back incident) */
230 > int
231   bi_getndx(const FVECT v, void *p)
232   {
233          FVECT  v2;
# Line 251 | Line 239 | bi_getndx(const FVECT v, void *p)
239          return fo_getndx(v2, p);
240   }
241  
242 < /* get vector for this angle basis index (back exiting) */
243 < static int
242 > /* Get vector for this angle basis index (back exiting) */
243 > int
244   bo_getvec(FVECT v, double ndxr, void *p)
245   {
246          if (!fo_getvec(v, ndxr, p))
# Line 263 | Line 251 | bo_getvec(FVECT v, double ndxr, void *p)
251          return RC_GOOD;
252   }
253  
254 < /* get index corresponding to the vector (back exiting) */
255 < static int
254 > /* Get index corresponding to the vector (back exiting) */
255 > int
256   bo_getndx(const FVECT v, void *p)
257   {
258          FVECT  v2;
# Line 276 | Line 264 | bo_getndx(const FVECT v, void *p)
264          return fo_getndx(v2, p);
265   }
266  
267 < /* get vector for this angle basis index (front incident) */
268 < static int
267 > /* Get vector for this angle basis index (front incident) */
268 > int
269   fi_getvec(FVECT v, double ndxr, void *p)
270   {
271          if (!fo_getvec(v, ndxr, p))
# Line 289 | Line 277 | fi_getvec(FVECT v, double ndxr, void *p)
277          return RC_GOOD;
278   }
279  
280 < /* get index corresponding to the vector (front incident) */
281 < static int
280 > /* Get index corresponding to the vector (front incident) */
281 > int
282   fi_getndx(const FVECT v, void *p)
283   {
284          FVECT  v2;
# Line 302 | Line 290 | fi_getndx(const FVECT v, void *p)
290          return fo_getndx(v2, p);
291   }
292  
293 + /* Get color or grayscale value for BSDF for the given direction pair */
294 + int
295 + mBSDF_color(float coef[], const SDMat *dp, int i, int o)
296 + {
297 +        C_COLOR cxy;
298 +        double  d;
299 +
300 +        coef[0] = mBSDF_value(dp, o, i);
301 +                                /* position-specific perturbation */
302 +        d = 2*dp->ninc/(i + .22545) + 4*dp->nout/(o + .70281);
303 +        d -= (int)d;
304 +        coef[0] *= 1. + 6e-4*(d - .5);
305 +        if (dp->chroma == NULL)
306 +                return 1;       /* grayscale */
307 +
308 +        c_decodeChroma(&cxy, mBSDF_chroma(dp,o,i));
309 +        c_toSharpRGB(&cxy, coef[0], coef);
310 +        coef[0] *= mtx_RGB_coef[0];
311 +        coef[1] *= mtx_RGB_coef[1];
312 +        coef[2] *= mtx_RGB_coef[2];
313 +        return 3;               /* RGB color */
314 + }
315 +
316   /* load custom BSDF angle basis */
317   static int
318   load_angle_basis(ezxml_t wab)
# Line 377 | Line 388 | get_extrema(SDSpectralDF *df)
388          for (i = dp->ninc; i--; ) {
389                  double  hemi = .0;
390                  for (o = dp->nout; o--; )
391 <                        hemi += ohma[o] * mBSDF_value(dp, i, o);
391 >                        hemi += ohma[o] * mBSDF_value(dp, o, i);
392                  if (hemi > df->maxHemi)
393                          df->maxHemi = hemi;
394          }
# Line 394 | Line 405 | get_extrema(SDSpectralDF *df)
405  
406   /* load BSDF distribution for this wavelength */
407   static int
408 < load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
408 > load_bsdf_data(SDData *sd, ezxml_t wdb, int ct, int rowinc)
409   {
410          SDSpectralDF    *df;
411          SDMat           *dp;
# Line 409 | Line 420 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
420           * Remember that front and back are reversed from WINDOW 6 orientations
421           */
422          if (!strcasecmp(sdata, "Transmission Front")) {
423 <                if (sd->tf != NULL)
413 <                        SDfreeSpectralDF(sd->tf);
414 <                if ((sd->tf = SDnewSpectralDF(1)) == NULL)
423 >                if (sd->tb == NULL && (sd->tb = SDnewSpectralDF(3)) == NULL)
424                          return RC_MEMERR;
425 <                df = sd->tf;
425 >                df = sd->tb;
426          } else if (!strcasecmp(sdata, "Transmission Back")) {
427 <                if (sd->tb != NULL)
419 <                        SDfreeSpectralDF(sd->tb);
420 <                if ((sd->tb = SDnewSpectralDF(1)) == NULL)
427 >                if (sd->tf == NULL && (sd->tf = SDnewSpectralDF(3)) == NULL)
428                          return RC_MEMERR;
429 <                df = sd->tb;
429 >                df = sd->tf;
430          } else if (!strcasecmp(sdata, "Reflection Front")) {
431 <                if (sd->rb != NULL)     /* note back-front reversal */
425 <                        SDfreeSpectralDF(sd->rb);
426 <                if ((sd->rb = SDnewSpectralDF(1)) == NULL)
431 >                if (sd->rb == NULL && (sd->rb = SDnewSpectralDF(3)) == NULL)
432                          return RC_MEMERR;
433                  df = sd->rb;
434          } else if (!strcasecmp(sdata, "Reflection Back")) {
435 <                if (sd->rf != NULL)     /* note front-back reversal */
431 <                        SDfreeSpectralDF(sd->rf);
432 <                if ((sd->rf = SDnewSpectralDF(1)) == NULL)
435 >                if (sd->rf == NULL && (sd->rf = SDnewSpectralDF(3)) == NULL)
436                          return RC_MEMERR;
437                  df = sd->rf;
438          } else
439                  return RC_FAIL;
440 <        /* XXX should also check "ScatteringDataType" for consistency? */
440 >                                        /* free previous matrix if any */
441 >        if (df->comp[ct].dist != NULL) {
442 >                SDfreeMatrix(df->comp[ct].dist);
443 >                df->comp[ct].dist = NULL;
444 >        }
445                                          /* get angle bases */
446          sdata = ezxml_txt(ezxml_child(wdb,"ColumnAngleBasis"));
447          if (!sdata || !*sdata) {
# Line 491 | Line 498 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
498          }
499          dp->ib_ohm = &io_getohm;
500          dp->ob_ohm = &io_getohm;
501 <        df->comp[0].cspec[0] = c_dfcolor; /* XXX monochrome for now */
502 <        df->comp[0].dist = dp;
496 <        df->comp[0].func = &SDhandleMtx;
501 >        df->comp[ct].dist = dp;
502 >        df->comp[ct].func = &SDhandleMtx;
503                                          /* read BSDF data */
504          sdata = ezxml_txt(ezxml_child(wdb, "ScatteringData"));
505          if (!sdata || !*sdata) {
# Line 502 | Line 508 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
508                  return RC_FORMERR;
509          }
510          for (i = 0; i < dp->ninc*dp->nout; i++) {
511 <                char  *sdnext = fskip(sdata);
511 >                char    *sdnext = fskip(sdata);
512 >                double  val;
513                  if (sdnext == NULL) {
514                          sprintf(SDerrorDetail,
515                                  "Bad/missing BSDF ScatteringData in '%s'",
# Line 512 | Line 519 | load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc)
519                  while (isspace(*sdnext))
520                          sdnext++;
521                  if (*sdnext == ',') sdnext++;
522 +                if ((val = atof(sdata)) < 0)
523 +                        val = 0;        /* don't allow negative values */
524                  if (rowinc) {
525                          int     r = i/dp->nout;
526                          int     c = i - r*dp->nout;
527 <                        mBSDF_value(dp,r,c) = atof(sdata);
527 >                        mBSDF_value(dp,c,r) = val;
528                  } else
529 <                        dp->bsdf[i] = atof(sdata);
529 >                        dp->bsdf[i] = val;
530                  sdata = sdnext;
531          }
532 <        return get_extrema(df);
532 >        return (ct == mtx_Y) ? get_extrema(df) : RC_GOOD;
533   }
534  
535 < /* Subtract minimum (diffuse) scattering amount from BSDF */
535 > /* copy our RGB (x,y) primary chromaticities */
536 > static void
537 > copy_RGB_prims(C_COLOR cspec[])
538 > {
539 >        if (mtx_RGB_coef[1] < .001) {   /* need to initialize */
540 >                int     i = 3;
541 >                while (i--) {
542 >                        float   rgb[3];
543 >                        rgb[0] = rgb[1] = rgb[2] = .0f;
544 >                        rgb[i] = 1.f;
545 >                        mtx_RGB_coef[i] = c_fromSharpRGB(rgb, &mtx_RGB_prim[i]);
546 >                }
547 >        }
548 >        memcpy(cspec, mtx_RGB_prim, sizeof(mtx_RGB_prim));
549 > }
550 >
551 > /* encode chromaticity if XYZ -- reduce to one channel in any case */
552 > static SDSpectralDF *
553 > encode_chroma(SDSpectralDF *df)
554 > {
555 >        SDMat   *mpx, *mpy, *mpz;
556 >        int     n;
557 >
558 >        if (df == NULL || df->ncomp != 3)
559 >                return df;
560 >
561 >        mpy = (SDMat *)df->comp[mtx_Y].dist;
562 >        if (mpy == NULL) {
563 >                free(df);
564 >                return NULL;
565 >        }
566 >        mpx = (SDMat *)df->comp[mtx_X].dist;
567 >        mpz = (SDMat *)df->comp[mtx_Z].dist;
568 >        if (mpx == NULL || (mpx->ninc != mpy->ninc) | (mpx->nout != mpy->nout))
569 >                goto done;
570 >        if (mpz == NULL || (mpz->ninc != mpy->ninc) | (mpz->nout != mpy->nout))
571 >                goto done;
572 >        mpy->chroma = (C_CHROMA *)malloc(sizeof(C_CHROMA)*mpy->ninc*mpy->nout);
573 >        if (mpy->chroma == NULL)
574 >                goto done;              /* XXX punt */
575 >                                        /* encode chroma values */
576 >        for (n = mpy->ninc*mpy->nout; n--; ) {
577 >                const double    sum = mpx->bsdf[n] + mpy->bsdf[n] + mpz->bsdf[n];
578 >                C_COLOR         cxy;
579 >                if (sum > .0)
580 >                        c_cset(&cxy, mpx->bsdf[n]/sum, mpy->bsdf[n]/sum);
581 >                else
582 >                        c_cset(&cxy, 1./3., 1./3.);
583 >                mpy->chroma[n] = c_encodeChroma(&cxy);
584 >        }
585 > done:                                   /* free X & Z channels */
586 >        if (mpx != NULL) SDfreeMatrix(mpx);
587 >        if (mpz != NULL) SDfreeMatrix(mpz);
588 >        if (mpy->chroma == NULL)        /* grayscale after all? */
589 >                df->comp[0].cspec[0] = c_dfcolor;
590 >        else                            /* else copy RGB primaries */
591 >                copy_RGB_prims(df->comp[0].cspec);
592 >        df->ncomp = 1;                  /* return resized struct */
593 >        return (SDSpectralDF *)realloc(df, sizeof(SDSpectralDF));
594 > }
595 >
596 > /* subtract minimum (diffuse) scattering amount from BSDF */
597   static double
598 < subtract_min(SDMat *sm)
598 > subtract_min(C_COLOR *cs, SDMat *sm)
599   {
600 <        float   minv = sm->bsdf[0];
601 <        int     n = sm->ninc*sm->nout;
602 <        int     i;
600 >        const int       ncomp = 1 + 2*(sm->chroma != NULL);
601 >        float           min_coef[3], ymin, coef[3];
602 >        int             i, o, c;
603          
604 <        for (i = n; --i; )
605 <                if (sm->bsdf[i] < minv)
606 <                        minv = sm->bsdf[i];
607 <        
608 <        if (minv <= FTINY)
604 >        min_coef[0] = min_coef[1] = min_coef[2] = FHUGE;
605 >        for (i = 0; i < sm->ninc; i++)
606 >                for (o = 0; o < sm->nout; o++) {
607 >                        c = mBSDF_color(coef, sm, i, o);
608 >                        while (c--)
609 >                                if (coef[c] < min_coef[c])
610 >                                        min_coef[c] = coef[c];
611 >                }
612 >        ymin = 0;
613 >        for (c = ncomp; c--; )
614 >                ymin += min_coef[c];
615 >        if (ymin <= .01/M_PI)           /* not worth bothering about? */
616                  return .0;
617 +        if (ncomp == 1) {               /* subtract grayscale minimum */
618 +                for (i = sm->ninc*sm->nout; i--; )
619 +                        sm->bsdf[i] -= ymin;
620 +                *cs = c_dfcolor;
621 +                return M_PI*ymin;
622 +        }
623 +                                        /* else subtract colored minimum */
624 +        for (i = 0; i < sm->ninc; i++)
625 +                for (o = 0; o < sm->nout; o++) {
626 +                        C_COLOR cxy;
627 +                        c = mBSDF_color(coef, sm, i, o);
628 +                        while (c--)
629 +                                coef[c] = (coef[c] - min_coef[c]) /
630 +                                                mtx_RGB_coef[c];
631 +                        if (c_fromSharpRGB(coef, &cxy) > 1e-5)
632 +                                mBSDF_chroma(sm,o,i) = c_encodeChroma(&cxy);
633 +                        mBSDF_value(sm,o,i) -= ymin;
634 +                }
635 +                                        /* return colored minimum */
636 +        for (i = 3; i--; )
637 +                coef[i] = min_coef[i]/mtx_RGB_coef[i];
638 +        c_fromSharpRGB(coef, cs);
639  
640 <        for (i = n; i--; )
542 <                sm->bsdf[i] -= minv;
543 <
544 <        return minv*M_PI;               /* be sure to include multiplier */
640 >        return M_PI*ymin;
641   }
642  
643 < /* Extract and separate diffuse portion of BSDF */
644 < static void
643 > /* Extract and separate diffuse portion of BSDF & convert color */
644 > static SDSpectralDF *
645   extract_diffuse(SDValue *dv, SDSpectralDF *df)
646   {
551        int     n;
647  
648 +        df = encode_chroma(df);         /* reduce XYZ to Y + chroma */
649          if (df == NULL || df->ncomp <= 0) {
650                  dv->spec = c_dfcolor;
651                  dv->cieY = .0;
652 <                return;
652 >                return df;
653          }
654 <        dv->spec = df->comp[0].cspec[0];
655 <        dv->cieY = subtract_min((SDMat *)df->comp[0].dist);
560 <                                        /* in case of multiple components */
561 <        for (n = df->ncomp; --n; ) {
562 <                double  ymin = subtract_min((SDMat *)df->comp[n].dist);
563 <                c_cmix(&dv->spec, dv->cieY, &dv->spec, ymin, &df->comp[n].cspec[0]);
564 <                dv->cieY += ymin;
565 <        }
654 >                                        /* subtract minimum value */
655 >        dv->cieY = subtract_min(&dv->spec, (SDMat *)df->comp[0].dist);
656          df->maxHemi -= dv->cieY;        /* adjust maximum hemispherical */
657 <                                        /* make sure everything is set */
658 <        c_ccvt(&dv->spec, C_CSXY+C_CSSPEC);
657 >                                
658 >        c_ccvt(&dv->spec, C_CSXY);      /* make sure (x,y) is set */
659 >        return df;
660   }
661  
662   /* Load a BSDF matrix from an open XML file */
# Line 605 | Line 696 | SDloadMtx(SDData *sd, ezxml_t wtl)
696                                          /* load BSDF components */
697          for (wld = ezxml_child(wtl, "WavelengthData");
698                                  wld != NULL; wld = wld->next) {
699 <                if (strcasecmp(ezxml_txt(ezxml_child(wld,"Wavelength")),
700 <                                "Visible"))
701 <                        continue;       /* just visible for now */
699 >                const char      *cnm = ezxml_txt(ezxml_child(wld,"Wavelength"));
700 >                int             ct = -1;
701 >                if (!strcasecmp(cnm, "Visible"))
702 >                        ct = mtx_Y;
703 >                else if (!strcasecmp(cnm, "CIE-X"))
704 >                        ct = mtx_X;
705 >                else if (!strcasecmp(cnm, "CIE-Z"))
706 >                        ct = mtx_Z;
707 >                else
708 >                        continue;
709                  for (wdb = ezxml_child(wld, "WavelengthDataBlock");
710                                          wdb != NULL; wdb = wdb->next)
711 <                        if ((rval = load_bsdf_data(sd, wdb, rowIn)) < 0)
711 >                        if ((rval = load_bsdf_data(sd, wdb, ct, rowIn)) < 0)
712                                  return convert_errcode(rval);
713          }
714                                          /* separate diffuse components */
715 <        extract_diffuse(&sd->rLambFront, sd->rf);
716 <        extract_diffuse(&sd->rLambBack, sd->rb);
717 <        extract_diffuse(&sd->tLamb, (sd->tf != NULL) ? sd->tf : sd->tb);
715 >        sd->rf = extract_diffuse(&sd->rLambFront, sd->rf);
716 >        sd->rb = extract_diffuse(&sd->rLambBack, sd->rb);
717 >        sd->tf = extract_diffuse(&sd->tLambFront, sd->tf);
718 >        if (sd->tb != NULL) {
719 >                sd->tb = extract_diffuse(&sd->tLambBack, sd->tb);
720 >                if (sd->tf == NULL)
721 >                        sd->tLambFront = sd->tLambBack;
722 >        } else if (sd->tf != NULL)
723 >                sd->tLambBack = sd->tLambFront;
724                                          /* return success */
725          return SDEnone;
726   }
727  
728   /* Get Matrix BSDF value */
729   static int
730 < SDgetMtxBSDF(float coef[SDmaxCh], const FVECT outVec,
731 <                                const FVECT inVec, SDComponent *sdc)
730 > SDgetMtxBSDF(float coef[SDmaxCh], const FVECT inVec,
731 >                                const FVECT outVec, SDComponent *sdc)
732   {
733          const SDMat     *dp;
734          int             i_ndx, o_ndx;
# Line 642 | Line 746 | SDgetMtxBSDF(float coef[SDmaxCh], const FVECT outVec,
746          }
747          if ((i_ndx < 0) | (o_ndx < 0))
748                  return 0;               /* nothing from this component */
749 <        coef[0] = mBSDF_value(dp, i_ndx, o_ndx);
750 <        return 1;                       /* XXX monochrome for now */
749 >
750 >        return mBSDF_color(coef, dp, i_ndx, o_ndx);
751   }
752  
753   /* Query solid angle for vector(s) */
# Line 709 | Line 813 | make_cdist(SDMatCDst *cd, const FVECT inVec, SDMat *dp
813          cmtab[0] = .0;
814          for (o = 0; o < cd->calen; o++) {
815                  if (rev)
816 <                        cmtab[o+1] = mBSDF_value(dp, o, cd->indx) *
816 >                        cmtab[o+1] = mBSDF_value(dp, cd->indx, o) *
817                                          (*dp->ib_ohm)(o, dp->ib_priv);
818                  else
819 <                        cmtab[o+1] = mBSDF_value(dp, cd->indx, o) *
819 >                        cmtab[o+1] = mBSDF_value(dp, o, cd->indx) *
820                                          (*dp->ob_ohm)(o, dp->ob_priv);
821                  cmtab[o+1] += cmtab[o];
822          }
# Line 755 | Line 859 | SDgetMtxCDist(const FVECT inVec, SDComponent *sdc)
859                  reverse = 1;
860          }
861          cdlast = NULL;                  /* check for it in cache list */
862 +        /* PLACE MUTEX LOCK HERE FOR THREAD-SAFE */
863          for (cd = (SDMatCDst *)sdc->cdList; cd != NULL;
864                                          cdlast = cd, cd = cd->next)
865                  if (cd->indx == myCD.indx && (cd->calen == myCD.calen) &
# Line 778 | Line 883 | SDgetMtxCDist(const FVECT inVec, SDComponent *sdc)
883                  cd->next = (SDMatCDst *)sdc->cdList;
884                  sdc->cdList = (SDCDst *)cd;
885          }
886 +        /* END MUTEX LOCK */
887          return (SDCDst *)cd;            /* ready to go */
888   }
889  
# Line 810 | Line 916 | SDsampMtxCDist(FVECT ioVec, double randX, const SDCDst
916   }
917  
918   /* Fixed resolution BSDF methods */
919 < SDFunc                  SDhandleMtx = {
919 > const SDFunc            SDhandleMtx = {
920                                  &SDgetMtxBSDF,
921                                  &SDqueryMtxProjSA,
922                                  &SDgetMtxCDist,

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines