/* Load a BSDF XML file and produce a corresponding Radiance object */ static int cvtBSDF(char *fname) { int retOK; SDData myBSDF; char *pname, *fnbeg; /* find and load the XML file */ retOK = strlen(fname); if (retOK < 5 || strcmp(fname+retOK-4, ".xml")) { fprintf(stderr, "%s: input does not end in '.xml'\n", fname); return(0); } pname = getpath(fname, getrlibpath(), R_OK); if (pname == NULL) { fprintf(stderr, "%s: cannot find BSDF file\n", fname); return(0); } fnbeg = strrchr(fname, DIRSEP); if (fnbeg != NULL) /* eliminate directory */ fname = fnbeg+1; SDclearBSDF(&myBSDF, fname); if (SDreportError(SDloadFile(&myBSDF, pname), stderr)) return(0); retOK = (myBSDF.dim[0] > FTINY) & (myBSDF.dim[1] > FTINY); if (!retOK) { fprintf(stderr, "%s: zero width or height\n", fname); } else { if (!do_stdout) { char rname[SDnameLn+4]; strcpy(rname, myBSDF.name); strcat(rname, ".rad"); retOK = (freopen(rname, "w", stdout) != NULL); } if (retOK) { if (myBSDF.matn[0] && myBSDF.makr[0]) printf("# Material '%s' by '%s'\n\n", myBSDF.matn, myBSDF.makr); if (myBSDF.mgf == NULL) { faceBSDF(&myBSDF, .0); } else { faceBSDF(&myBSDF, myBSDF.dim[2]); if (myBSDF.rb != NULL) faceBSDF(&myBSDF, -myBSDF.dim[2]); retOK = geomBSDF(&myBSDF); } } } SDfreeBSDF(&myBSDF); /* clean up and return */ return(retOK); }
/* Free a BSDF from our cache (clear all if NULL) */ void SDfreeCache(const SDData *sd) { struct SDCache_s *sdl, *sdLast = NULL; if (sd == NULL) { /* free entire list */ while ((sdl = SDcacheList) != NULL) { SDcacheList = sdl->next; SDfreeBSDF(&sdl->bsdf); free(sdl); } return; } for (sdl = SDcacheList; sdl != NULL; sdl = (sdLast=sdl)->next) if (&sdl->bsdf == sd) break; if (sdl == NULL || (sdl->refcnt -= (sdl->refcnt > 0))) return; /* missing or still in use */ /* keep unreferenced data? */ if (SDisLoaded(sd) && SDretainSet) { if (SDretainSet == SDretainAll) return; /* keep everything */ /* else free cumulative data */ SDfreeCumulativeCache(sd->rf); SDfreeCumulativeCache(sd->rb); SDfreeCumulativeCache(sd->tf); SDfreeCumulativeCache(sd->tb); return; } /* remove from list and free */ if (sdLast == NULL) SDcacheList = sdl->next; else sdLast->next = sdl->next; SDfreeBSDF(&sdl->bsdf); free(sdl); }
/* Load a BSDF struct from the given file (free first and keep name) */ SDError SDloadFile(SDData *sd, const char *fname) { SDError lastErr; ezxml_t fl, wtl; if ((sd == NULL) | (fname == NULL || !*fname)) return SDEargument; /* free old data, keeping name */ SDfreeBSDF(sd); /* parse XML file */ fl = ezxml_parse_file(fname); if (fl == NULL) { sprintf(SDerrorDetail, "Cannot open BSDF \"%s\"", fname); return SDEfile; } if (ezxml_error(fl)[0]) { sprintf(SDerrorDetail, "BSDF \"%s\" %s", fname, ezxml_error(fl)); ezxml_free(fl); return SDEformat; } if (strcmp(ezxml_name(fl), "WindowElement")) { sprintf(SDerrorDetail, "BSDF \"%s\": top level node not 'WindowElement'", sd->name); ezxml_free(fl); return SDEformat; } wtl = ezxml_child(fl, "FileType"); if (wtl != NULL && strcmp(ezxml_txt(wtl), "BSDF")) { sprintf(SDerrorDetail, "XML \"%s\": wrong FileType (must be 'BSDF')", sd->name); ezxml_free(fl); return SDEformat; } wtl = ezxml_child(ezxml_child(fl, "Optical"), "Layer"); if (wtl == NULL) { sprintf(SDerrorDetail, "BSDF \"%s\": no optical layers'", sd->name); ezxml_free(fl); return SDEformat; } /* load geometry if present */ lastErr = SDloadGeometry(sd, wtl); if (lastErr) { ezxml_free(fl); return lastErr; } /* try loading variable resolution data */ lastErr = SDloadTre(sd, wtl); /* check our result */ if (lastErr == SDEsupport) /* try matrix BSDF if not tree data */ lastErr = SDloadMtx(sd, wtl); /* done with XML file */ ezxml_free(fl); if (lastErr) { /* was there a load error? */ SDfreeBSDF(sd); return lastErr; } /* remove any insignificant components */ if (sd->rf != NULL && sd->rf->maxHemi <= .001) { SDfreeSpectralDF(sd->rf); sd->rf = NULL; } if (sd->rb != NULL && sd->rb->maxHemi <= .001) { SDfreeSpectralDF(sd->rb); sd->rb = NULL; } if (sd->tf != NULL && sd->tf->maxHemi <= .001) { SDfreeSpectralDF(sd->tf); sd->tf = NULL; } if (sd->tb != NULL && sd->tb->maxHemi <= .001) { SDfreeSpectralDF(sd->tb); sd->tb = NULL; } /* return success */ return SDEnone; }
/* Load and resample XML BSDF description using Klems basis */ static void eval_bsdf(const char *fname) { ANGLE_BASIS *abp = get_basis(kbasis); FILE *cfp[3]; SDData bsd; SDError ec; FVECT vin, vout; SDValue sdv; double sum, xsum, ysum; int i, j, n; initurand(npsamps); SDclearBSDF(&bsd, fname); /* load BSDF file */ if ((ec = SDloadFile(&bsd, fname)) != SDEnone) goto err; if (bsd.mgf != NULL) /* save geometry */ save_geom(bsd.mgf); if (bsd.matn[0]) /* save identifier(s) */ strcpy(bsdf_name, bsd.matn); if (bsd.makr[0]) strcpy(bsdf_manuf, bsd.makr); if (bsd.dim[2] > 0) { /* save dimension(s) */ char buf[64]; if ((bsd.dim[0] > 0) & (bsd.dim[1] > 0)) sprintf(buf, "w=%g;h=%g;t=%g", bsd.dim[0], bsd.dim[1], bsd.dim[2]); else sprintf(buf, "t=%g", bsd.dim[2]); add_wbsdf("-f", 1); add_wbsdf(buf, 0); } /* front reflection */ if (bsd.rf != NULL || bsd.rLambFront.cieY > .002) { input_orient = 1; output_orient = 1; cfp[CIE_Y] = open_component_file(CIE_Y); if (bsd.rf != NULL && bsd.rf->comp[0].cspec[2].flags) { rbf_colorimetry = RBCtristimulus; cfp[CIE_X] = open_component_file(CIE_X); cfp[CIE_Z] = open_component_file(CIE_Z); } else rbf_colorimetry = RBCphotopic; for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ xsum = ysum = 0; for (n = npsamps; n-- > 0; ) { fo_getvec(vout, j+(n+frandom())/npsamps, abp); fi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sdv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sdv.cieY; if (rbf_colorimetry == RBCtristimulus) { xsum += sdv.cieY * sdv.spec.cx; ysum += sdv.cieY * sdv.spec.cy; } } fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps); if (rbf_colorimetry == RBCtristimulus) { fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum)); fprintf(cfp[CIE_Z], "\t%.3e\n", (sum - xsum - ysum)*sum/(npsamps*ysum)); } } fputc('\n', cfp[CIE_Y]); /* extra space between rows */ if (rbf_colorimetry == RBCtristimulus) { fputc('\n', cfp[CIE_X]); fputc('\n', cfp[CIE_Z]); } } if (fclose(cfp[CIE_Y])) { fprintf(stderr, "%s: error writing Y output\n", progname); exit(1); } if (rbf_colorimetry == RBCtristimulus && (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) { fprintf(stderr, "%s: error writing X/Z output\n", progname); exit(1); } } /* back reflection */ if (bsd.rb != NULL || bsd.rLambBack.cieY > .002) { input_orient = -1; output_orient = -1; cfp[CIE_Y] = open_component_file(CIE_Y); if (bsd.rb != NULL && bsd.rb->comp[0].cspec[2].flags) { rbf_colorimetry = RBCtristimulus; cfp[CIE_X] = open_component_file(CIE_X); cfp[CIE_Z] = open_component_file(CIE_Z); } else rbf_colorimetry = RBCphotopic; for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ xsum = ysum = 0; for (n = npsamps; n-- > 0; ) { bo_getvec(vout, j+(n+frandom())/npsamps, abp); bi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sdv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sdv.cieY; if (rbf_colorimetry == RBCtristimulus) { xsum += sdv.cieY * sdv.spec.cx; ysum += sdv.cieY * sdv.spec.cy; } } fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps); if (rbf_colorimetry == RBCtristimulus) { fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum)); fprintf(cfp[CIE_Z], "\t%.3e\n", (sum - xsum - ysum)*sum/(npsamps*ysum)); } } if (rbf_colorimetry == RBCtristimulus) { fputc('\n', cfp[CIE_X]); fputc('\n', cfp[CIE_Z]); } } if (fclose(cfp[CIE_Y])) { fprintf(stderr, "%s: error writing Y output\n", progname); exit(1); } if (rbf_colorimetry == RBCtristimulus && (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) { fprintf(stderr, "%s: error writing X/Z output\n", progname); exit(1); } } /* front transmission */ if (bsd.tf != NULL || bsd.tLamb.cieY > .002) { input_orient = 1; output_orient = -1; cfp[CIE_Y] = open_component_file(CIE_Y); if (bsd.tf != NULL && bsd.tf->comp[0].cspec[2].flags) { rbf_colorimetry = RBCtristimulus; cfp[CIE_X] = open_component_file(CIE_X); cfp[CIE_Z] = open_component_file(CIE_Z); } else rbf_colorimetry = RBCphotopic; for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ xsum = ysum = 0; for (n = npsamps; n-- > 0; ) { bo_getvec(vout, j+(n+frandom())/npsamps, abp); fi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sdv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sdv.cieY; if (rbf_colorimetry == RBCtristimulus) { xsum += sdv.cieY * sdv.spec.cx; ysum += sdv.cieY * sdv.spec.cy; } } fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps); if (rbf_colorimetry == RBCtristimulus) { fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum)); fprintf(cfp[CIE_Z], "\t%.3e\n", (sum - xsum - ysum)*sum/(npsamps*ysum)); } } if (rbf_colorimetry == RBCtristimulus) { fputc('\n', cfp[CIE_X]); fputc('\n', cfp[CIE_Z]); } } if (fclose(cfp[CIE_Y])) { fprintf(stderr, "%s: error writing Y output\n", progname); exit(1); } if (rbf_colorimetry == RBCtristimulus && (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) { fprintf(stderr, "%s: error writing X/Z output\n", progname); exit(1); } } /* back transmission */ if ((bsd.tb != NULL) | (bsd.tf != NULL)) { input_orient = -1; output_orient = 1; cfp[CIE_Y] = open_component_file(CIE_Y); if (bsd.tb != NULL) rbf_colorimetry = bsd.tb->comp[0].cspec[2].flags ? RBCtristimulus : RBCphotopic ; if (rbf_colorimetry == RBCtristimulus) { cfp[CIE_X] = open_component_file(CIE_X); cfp[CIE_Z] = open_component_file(CIE_Z); } for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ xsum = ysum = 0; for (n = npsamps; n-- > 0; ) { fo_getvec(vout, j+(n+frandom())/npsamps, abp); bi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sdv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sdv.cieY; if (rbf_colorimetry == RBCtristimulus) { xsum += sdv.cieY * sdv.spec.cx; ysum += sdv.cieY * sdv.spec.cy; } } fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps); if (rbf_colorimetry == RBCtristimulus) { fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum)); fprintf(cfp[CIE_Z], "\t%.3e\n", (sum - xsum - ysum)*sum/(npsamps*ysum)); } } if (rbf_colorimetry == RBCtristimulus) { fputc('\n', cfp[CIE_X]); fputc('\n', cfp[CIE_Z]); } } if (fclose(cfp[CIE_Y])) { fprintf(stderr, "%s: error writing Y output\n", progname); exit(1); } if (rbf_colorimetry == RBCtristimulus && (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) { fprintf(stderr, "%s: error writing X/Z output\n", progname); exit(1); } } SDfreeBSDF(&bsd); /* all done */ return; err: SDreportError(ec, stderr); exit(1); }
/* Load and resample XML BSDF description using Klems basis */ static void eval_bsdf(const char *fname) { ANGLE_BASIS *abp = get_basis(kbasis); SDData bsd; SDError ec; FVECT vin, vout; SDValue sv; double sum; int i, j, n; SDclearBSDF(&bsd, fname); /* load BSDF file */ if ((ec = SDloadFile(&bsd, fname)) != SDEnone) goto err; xml_prologue(&bsd); /* pass geometry */ /* front reflection */ if (bsd.rf != NULL || bsd.rLambFront.cieY > .002) { input_orient = 1; output_orient = 1; data_prologue(); for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ for (n = npsamps; n-- > 0; ) { fo_getvec(vout, j+(n+frandom())/npsamps, abp); fi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sv.cieY; } printf("\t%.3e\n", sum/npsamps); } putchar('\n'); /* extra space between rows */ } data_epilogue(); } /* back reflection */ if (bsd.rb != NULL || bsd.rLambBack.cieY > .002) { input_orient = -1; output_orient = -1; data_prologue(); for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ for (n = npsamps; n-- > 0; ) { bo_getvec(vout, j+(n+frandom())/npsamps, abp); bi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sv.cieY; } printf("\t%.3e\n", sum/npsamps); } putchar('\n'); /* extra space between rows */ } data_epilogue(); } /* front transmission */ if (bsd.tf != NULL || bsd.tLamb.cieY > .002) { input_orient = 1; output_orient = -1; data_prologue(); for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ for (n = npsamps; n-- > 0; ) { bo_getvec(vout, j+(n+frandom())/npsamps, abp); fi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sv.cieY; } printf("\t%.3e\n", sum/npsamps); } putchar('\n'); /* extra space between rows */ } data_epilogue(); } /* back transmission */ if ((bsd.tb != NULL) | (bsd.tf != NULL)) { input_orient = -1; output_orient = 1; data_prologue(); for (j = 0; j < abp->nangles; j++) { for (i = 0; i < abp->nangles; i++) { sum = 0; /* average over patches */ for (n = npsamps; n-- > 0; ) { fo_getvec(vout, j+(n+frandom())/npsamps, abp); bi_getvec(vin, i+urand(n), abp); ec = SDevalBSDF(&sv, vout, vin, &bsd); if (ec != SDEnone) goto err; sum += sv.cieY; } printf("\t%.3e\n", sum/npsamps); } putchar('\n'); /* extra space between rows */ } data_epilogue(); } SDfreeBSDF(&bsd); /* all done */ return; err: SDreportError(ec, stderr); exit(1); }