--- ray/src/util/wrapBSDF.c 2015/02/14 18:33:07 2.5 +++ ray/src/util/wrapBSDF.c 2015/02/16 19:11:28 2.7 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: wrapBSDF.c,v 2.5 2015/02/14 18:33:07 greg Exp $"; +static const char RCSid[] = "$Id: wrapBSDF.c,v 2.7 2015/02/16 19:11:28 greg Exp $"; #endif /* * Wrap BSDF data in valid WINDOW XML file @@ -18,7 +18,6 @@ const char def_template[] = "minimalBSDFt.xml"; const char win6_template[] = "WINDOW6BSDFt.xml"; const char stdin_name[] = ""; - /* input files (can be stdin_name) */ const char *xml_input = NULL; /* unit for materials & geometry */ @@ -27,12 +26,19 @@ const char legal_units[] = "meter|foot|inch|centimeter /* system materials & geometry */ const char *mgf_geometry = NULL; - /* angle basis */ + /* angle bases */ enum { ABdefault=-1, ABklemsFull=0, ABklemsHalf, ABklemsQuarter, ABtensorTree3, ABtensorTree4, ABend }; int angle_basis = ABdefault; +int correct_solid_angle = 0; + +const char *klems_basis_name[] = { + "LBNL/Klems Full", + "LBNL/Klems Half", + "LBNL/Klems Quarter", +}; /* field IDs and nicknames */ struct s_fieldID { char nickName[4]; @@ -57,7 +63,6 @@ struct s_fieldID { const char *field_assignment[MAXASSIGN]; int nfield_assign = 0; #define FASEP ';' - /* data file(s) & spectra */ enum { DTtransForward, DTtransBackward, DTreflForward, DTreflBackward }; @@ -378,10 +383,55 @@ determine_angle_basis(const char *fn, ezxml_t wtl) return -1; } +/* Filter Klems angle basis, factoring out incident projected solid angle */ +static int +filter_klems_matrix(FILE *fp) +{ +#define MAX_COLUMNS 145 + const char *bn = klems_basis_name[angle_basis]; + float col_corr[MAX_COLUMNS]; + int i, j, n = nabases; + /* get angle basis */ + while (n-- > 0) + if (!strcasecmp(bn, abase_list[n].name)) + break; + if (n < 0) + return 0; + if (abase_list[n].nangles > MAX_COLUMNS) { + fputs("Internal error - too many Klems columns!\n", stderr); + return 0; + } + /* get correction factors */ + for (j = abase_list[n].nangles; j--; ) + col_corr[j] = 1.f / io_getohm(j, &abase_list[n]); + /* read/correct/write matrix */ + for (i = 0; i < abase_list[n].nangles; i++) { + for (j = 0; j < abase_list[n].nangles; j++) { + double d; + if (fscanf(fp, "%lf", &d) != 1) + return 0; + if (d < -1e-3) { + fputs("Negative BSDF data!\n", stderr); + return 0; + } + printf(" %.3e", d*col_corr[j]*(d > 0)); + } + fputc('\n', stdout); + } + while ((i = getc(fp)) != EOF) + if (!isspace(i)) { + fputs("Unexpected data past EOF\n", stderr); + return 0; + } + return 1; /* all is good */ +#undef MAX_COLUMNS +} + /* Write out BSDF data block with surrounding tags */ static int writeBSDFblock(const char *caller, struct s_dfile *df) { + int correct_klems = correct_solid_angle; char *cp; puts("\t"); @@ -389,7 +439,7 @@ writeBSDFblock(const char *caller, struct s_dfile *df) switch (df->spectrum) { case DSvisible: puts("\t\tVisible"); - puts("\t\tSourceSpectrum>CIE Illuminant D65 1nm.ssp"); + puts("\t\tCIE Illuminant D65 1nm.ssp"); puts("\t\tASTM E308 1931 Y.dsp"); break; case DSxbar31: @@ -447,17 +497,19 @@ writeBSDFblock(const char *caller, struct s_dfile *df) puts(""); switch (angle_basis) { case ABklemsFull: - puts("\t\t\tLBNL/Klems Full"); - break; case ABklemsHalf: - puts("\t\t\tLBNL/Klems Half"); - break; case ABklemsQuarter: - puts("\t\t\tLBNL/Klems Quarter"); + fputs("\t\t\t", stdout); + fputs(klems_basis_name[angle_basis], stdout); + puts(""); + fputs("\t\t\t", stdout); + fputs(klems_basis_name[angle_basis], stdout); + puts(""); break; case ABtensorTree3: case ABtensorTree4: puts("\t\t\tLBNL/Shirley-Chiu"); + correct_klems = 0; break; default: fprintf(stderr, "%s: bad angle basis (%d)\n", caller, angle_basis); @@ -466,7 +518,30 @@ writeBSDFblock(const char *caller, struct s_dfile *df) puts("\t\t\tBTDF"); puts("\t\t\t"); fflush(stdout); - if (df->fname == stdin_name) { + if (correct_klems) { /* correct Klems matrix data */ + FILE *fp = stdin; + if (df->fname[0] == '!') + fp = popen(df->fname+1, "r"); + else if (df->fname != stdin_name) + fp = fopen(df->fname, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: cannot open '%s'\n", + caller, df->fname); + return 0; + } + if (!filter_klems_matrix(fp)) { + fprintf(stderr, "%s: Klems data error from '%s'\n", + caller, df->fname); + return 0; + } + if (df->fname[0] != '!') { + fclose(fp); + } else if (pclose(fp)) { + fprintf(stderr, "%s: error running '%s'\n", + caller, df->fname); + return 0; + } + } else if (df->fname == stdin_name) { copy_and_close(fileno(stdin)); } else if (df->fname[0] != '!') { if (!copy_and_close(open(df->fname, O_RDONLY))) { @@ -698,6 +773,9 @@ main(int argc, char *argv[]) angle_basis = ABtensorTree4; else UsageExit(argv[0]); + continue; + case 'c': /* correct solid angle */ + correct_solid_angle ^= 1; continue; case 't': /* transmission */ if (i >= argc-1)