--- ray/src/common/bsdf_m.c 2011/06/28 21:13:46 3.17 +++ ray/src/common/bsdf_m.c 2014/03/21 17:49:53 3.28 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: bsdf_m.c,v 3.17 2011/06/28 21:13:46 greg Exp $"; +static const char RCSid[] = "$Id: bsdf_m.c,v 3.28 2014/03/21 17:49:53 greg Exp $"; #endif /* * bsdf_m.c @@ -29,24 +29,10 @@ static const char RCSid[] = "$Id: bsdf_m.c,v 3.17 2011 #define RC_INTERR (-4) #define RC_MEMERR (-5) -#define MAXLATS 46 /* maximum number of latitudes */ - -/* BSDF angle specification */ -typedef struct { - char name[64]; /* basis name */ - int nangles; /* total number of directions */ - struct { - float tmin; /* starting theta */ - int nphis; /* number of phis (0 term) */ - } lat[MAXLATS+1]; /* latitudes */ -} ANGLE_BASIS; - -#define MAXABASES 7 /* limit on defined bases */ - -static ANGLE_BASIS abase_list[MAXABASES] = { +ANGLE_BASIS abase_list[MAXABASES] = { { "LBNL/Klems Full", 145, - { {-5., 1}, + { {0., 1}, {5., 8}, {15., 16}, {25., 20}, @@ -58,7 +44,7 @@ static ANGLE_BASIS abase_list[MAXABASES] = { {90., 0} } }, { "LBNL/Klems Half", 73, - { {-6.5, 1}, + { {0., 1}, {6.5, 8}, {19.5, 12}, {32.5, 16}, @@ -68,7 +54,7 @@ static ANGLE_BASIS abase_list[MAXABASES] = { {90., 0} } }, { "LBNL/Klems Quarter", 41, - { {-9., 1}, + { {0., 1}, {9., 8}, {27., 12}, {46., 12}, @@ -77,7 +63,7 @@ static ANGLE_BASIS abase_list[MAXABASES] = { } }; -static int nabases = 3; /* current number of defined bases */ +int nabases = 3; /* current number of defined bases */ static int fequal(double a, double b) @@ -146,8 +132,8 @@ SDnewMatrix(int ni, int no) /* Free a BSDF matrix */ #define SDfreeMatrix free -/* get vector for this angle basis index (front exiting) */ -static int +/* Get vector for this angle basis index (front exiting) */ +int fo_getvec(FVECT v, double ndxr, void *p) { ANGLE_BASIS *ab = (ANGLE_BASIS *)p; @@ -172,8 +158,8 @@ fo_getvec(FVECT v, double ndxr, void *p) return RC_GOOD; } -/* get index corresponding to the given vector (front exiting) */ -static int +/* Get index corresponding to the given vector (front exiting) */ +int fo_getndx(const FVECT v, void *p) { ANGLE_BASIS *ab = (ANGLE_BASIS *)p; @@ -184,7 +170,7 @@ fo_getndx(const FVECT v, void *p) return -1; if ((v[2] < 0) | (v[2] > 1.)) return -1; - pol = 180.0/M_PI*acos(v[2]); + pol = 180.0/M_PI*Acos(v[2]); azi = 180.0/M_PI*atan2(v[1], v[0]); if (azi < 0.0) azi += 360.0; for (li = 1; ab->lat[li].tmin <= pol; li++) @@ -201,8 +187,8 @@ fo_getndx(const FVECT v, void *p) /* compute square of real value */ static double sq(double x) { return x*x; } -/* get projected solid angle for this angle basis index (universal) */ -static double +/* Get projected solid angle for this angle basis index (universal) */ +double io_getohm(int ndx, void *p) { static int last_li = -1; @@ -218,16 +204,14 @@ io_getohm(int ndx, void *p) if (li == last_li) /* cached latitude? */ return last_ohm; last_li = li; - theta1 = M_PI/180. * ab->lat[li+1].tmin; - if (ab->lat[li].nphis == 1) /* special case */ - return last_ohm = M_PI*(1. - sq(cos(theta1))); theta = M_PI/180. * ab->lat[li].tmin; + theta1 = M_PI/180. * ab->lat[li+1].tmin; return last_ohm = M_PI*(sq(cos(theta)) - sq(cos(theta1))) / (double)ab->lat[li].nphis; } -/* get vector for this angle basis index (back incident) */ -static int +/* Get vector for this angle basis index (back incident) */ +int bi_getvec(FVECT v, double ndxr, void *p) { if (!fo_getvec(v, ndxr, p)) @@ -240,8 +224,8 @@ bi_getvec(FVECT v, double ndxr, void *p) return RC_GOOD; } -/* get index corresponding to the vector (back incident) */ -static int +/* Get index corresponding to the vector (back incident) */ +int bi_getndx(const FVECT v, void *p) { FVECT v2; @@ -253,8 +237,8 @@ bi_getndx(const FVECT v, void *p) return fo_getndx(v2, p); } -/* get vector for this angle basis index (back exiting) */ -static int +/* Get vector for this angle basis index (back exiting) */ +int bo_getvec(FVECT v, double ndxr, void *p) { if (!fo_getvec(v, ndxr, p)) @@ -265,8 +249,8 @@ bo_getvec(FVECT v, double ndxr, void *p) return RC_GOOD; } -/* get index corresponding to the vector (back exiting) */ -static int +/* Get index corresponding to the vector (back exiting) */ +int bo_getndx(const FVECT v, void *p) { FVECT v2; @@ -278,8 +262,8 @@ bo_getndx(const FVECT v, void *p) return fo_getndx(v2, p); } -/* get vector for this angle basis index (front incident) */ -static int +/* Get vector for this angle basis index (front incident) */ +int fi_getvec(FVECT v, double ndxr, void *p) { if (!fo_getvec(v, ndxr, p)) @@ -291,8 +275,8 @@ fi_getvec(FVECT v, double ndxr, void *p) return RC_GOOD; } -/* get index corresponding to the vector (front incident) */ -static int +/* Get index corresponding to the vector (front incident) */ +int fi_getndx(const FVECT v, void *p) { FVECT v2; @@ -335,8 +319,7 @@ load_angle_basis(ezxml_t wab) ezxml_child(ezxml_child(wbb, "ThetaBounds"), "UpperTheta"))); if (!i) - abase_list[nabases].lat[i].tmin = - -abase_list[nabases].lat[i+1].tmin; + abase_list[nabases].lat[0].tmin = 0; else if (!fequal(atof(ezxml_txt(ezxml_child(ezxml_child(wbb, "ThetaBounds"), "LowerTheta"))), abase_list[nabases].lat[i].tmin)) { @@ -402,7 +385,6 @@ load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc) SDSpectralDF *df; SDMat *dp; char *sdata; - int tfront; int inbi, outbi; int i; /* allocate BSDF component */ @@ -411,24 +393,27 @@ load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc) return RC_FAIL; /* * Remember that front and back are reversed from WINDOW 6 orientations - * Favor their "Front" (incoming light) since that's more often valid */ - tfront = !strcasecmp(sdata, "Transmission Back"); - if (!strcasecmp(sdata, "Transmission Front") || - tfront & (sd->tf == NULL)) { + if (!strcasecmp(sdata, "Transmission Front")) { + if (sd->tb != NULL) + SDfreeSpectralDF(sd->tb); + if ((sd->tb = SDnewSpectralDF(1)) == NULL) + return RC_MEMERR; + df = sd->tb; + } else if (!strcasecmp(sdata, "Transmission Back")) { if (sd->tf != NULL) SDfreeSpectralDF(sd->tf); if ((sd->tf = SDnewSpectralDF(1)) == NULL) return RC_MEMERR; df = sd->tf; } else if (!strcasecmp(sdata, "Reflection Front")) { - if (sd->rb != NULL) /* note back-front reversal */ + if (sd->rb != NULL) SDfreeSpectralDF(sd->rb); if ((sd->rb = SDnewSpectralDF(1)) == NULL) return RC_MEMERR; df = sd->rb; } else if (!strcasecmp(sdata, "Reflection Back")) { - if (sd->rf != NULL) /* note front-back reversal */ + if (sd->rf != NULL) SDfreeSpectralDF(sd->rf); if ((sd->rf = SDnewSpectralDF(1)) == NULL) return RC_MEMERR; @@ -470,17 +455,15 @@ load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc) dp->ib_priv = &abase_list[inbi]; dp->ob_priv = &abase_list[outbi]; if (df == sd->tf) { - if (tfront) { - dp->ib_vec = &fi_getvec; - dp->ib_ndx = &fi_getndx; - dp->ob_vec = &bo_getvec; - dp->ob_ndx = &bo_getndx; - } else { - dp->ib_vec = &bi_getvec; - dp->ib_ndx = &bi_getndx; - dp->ob_vec = &fo_getvec; - dp->ob_ndx = &fo_getndx; - } + dp->ib_vec = &fi_getvec; + dp->ib_ndx = &fi_getndx; + dp->ob_vec = &bo_getvec; + dp->ob_ndx = &bo_getndx; + } else if (df == sd->tb) { + dp->ib_vec = &bi_getvec; + dp->ib_ndx = &bi_getndx; + dp->ob_vec = &fo_getvec; + dp->ob_ndx = &fo_getndx; } else if (df == sd->rf) { dp->ib_vec = &fi_getvec; dp->ib_ndx = &fi_getndx; @@ -505,7 +488,8 @@ load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc) return RC_FORMERR; } for (i = 0; i < dp->ninc*dp->nout; i++) { - char *sdnext = fskip(sdata); + char *sdnext = fskip(sdata); + double val; if (sdnext == NULL) { sprintf(SDerrorDetail, "Bad/missing BSDF ScatteringData in '%s'", @@ -515,12 +499,14 @@ load_bsdf_data(SDData *sd, ezxml_t wdb, int rowinc) while (isspace(*sdnext)) sdnext++; if (*sdnext == ',') sdnext++; + if ((val = atof(sdata)) < 0) + val = 0; /* don't allow negative values */ if (rowinc) { int r = i/dp->nout; int c = i - r*dp->nout; - mBSDF_value(dp,r,c) = atof(sdata); + mBSDF_value(dp,r,c) = val; } else - dp->bsdf[i] = atof(sdata); + dp->bsdf[i] = val; sdata = sdnext; } return get_extrema(df); @@ -598,11 +584,13 @@ SDloadMtx(SDData *sd, ezxml_t wtl) sd->name); return SDEsupport; } - /* get angle basis */ - rval = load_angle_basis(ezxml_child(ezxml_child(wtl, - "DataDefinition"), "AngleBasis")); - if (rval < 0) - return convert_errcode(rval); + /* get angle bases */ + for (wld = ezxml_child(ezxml_child(wtl, "DataDefinition"), "AngleBasis"); + wld != NULL; wld = wld->next) { + rval = load_angle_basis(wld); + if (rval < 0) + return convert_errcode(rval); + } /* load BSDF components */ for (wld = ezxml_child(wtl, "WavelengthData"); wld != NULL; wld = wld->next) { @@ -617,7 +605,10 @@ SDloadMtx(SDData *sd, ezxml_t wtl) /* separate diffuse components */ extract_diffuse(&sd->rLambFront, sd->rf); extract_diffuse(&sd->rLambBack, sd->rb); - extract_diffuse(&sd->tLamb, sd->tf); + if (sd->tf != NULL) + extract_diffuse(&sd->tLamb, sd->tf); + if (sd->tb != NULL) + extract_diffuse(&sd->tLamb, sd->tb); /* return success */ return SDEnone; } @@ -757,7 +748,7 @@ SDgetMtxCDist(const FVECT inVec, SDComponent *sdc) } cdlast = NULL; /* check for it in cache list */ for (cd = (SDMatCDst *)sdc->cdList; cd != NULL; - cdlast = cd, cd = (SDMatCDst *)cd->next) + cdlast = cd, cd = cd->next) if (cd->indx == myCD.indx && (cd->calen == myCD.calen) & (cd->ob_priv == myCD.ob_priv) & (cd->ob_vec == myCD.ob_vec)) @@ -776,7 +767,7 @@ SDgetMtxCDist(const FVECT inVec, SDComponent *sdc) } if (cdlast != NULL) { /* move entry to head of cache list */ cdlast->next = cd->next; - cd->next = sdc->cdList; + cd->next = (SDMatCDst *)sdc->cdList; sdc->cdList = (SDCDst *)cd; } return (SDCDst *)cd; /* ready to go */ @@ -796,7 +787,7 @@ SDsampMtxCDist(FVECT ioVec, double randX, const SDCDst /* binary search to find index */ ilower = 0; iupper = mcd->calen; while ((i = (iupper + ilower) >> 1) != ilower) - if ((long)target >= (long)mcd->carr[i]) + if (target >= mcd->carr[i]) ilower = i; else iupper = i;