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

Comparing ray/src/cv/bsdf2klems.c (file contents):
Revision 2.15 by greg, Thu Aug 21 10:33:48 2014 UTC vs.
Revision 2.21 by greg, Thu Feb 4 00:45:47 2016 UTC

# Line 14 | Line 14 | static const char RCSid[] = "$Id$";
14   #include <math.h>
15   #include "random.h"
16   #include "platform.h"
17 + #include "paths.h"
18 + #include "rtio.h"
19   #include "calcomp.h"
20   #include "bsdfrep.h"
21   #include "bsdf_m.h"
22 +                                /* tristimulus components */
23 + enum {CIE_X, CIE_Y, CIE_Z};
24                                  /* assumed maximum # Klems patches */
25   #define MAXPATCHES      145
26                                  /* global argv[0] */
27   char                    *progname;
28                                  /* selected basis function name */
29 < static const char       *kbasis = "LBNL/Klems Full";
29 > static const char       klems_full[] = "LBNL/Klems Full";
30 > static const char       klems_half[] = "LBNL/Klems Half";
31 > static const char       klems_quarter[] = "LBNL/Klems Quarter";
32 > static const char       *kbasis = klems_full;
33                                  /* number of BSDF samples per patch */
34   static int              npsamps = 256;
35                                  /* limit on number of RBF lobes */
# Line 30 | Line 37 | static int             lobe_lim = 15000;
37                                  /* progress bar length */
38   static int              do_prog = 79;
39  
40 + #define MAXCARG         512     /* wrapBSDF command */
41 + static char             *wrapBSDF[MAXCARG] = {"wrapBSDF", "-W", "-UU"};
42 + static int              wbsdfac = 3;
43  
44 + /* Add argument to wrapBSDF, allocating space if isstatic */
45 + static void
46 + add_wbsdf(const char *arg, int isstatic)
47 + {
48 +        if (arg == NULL)
49 +                return;
50 +        if (wbsdfac >= MAXCARG-1) {
51 +                fputs(progname, stderr);
52 +                fputs(": too many command arguments to wrapBSDF\n", stderr);
53 +                exit(1);
54 +        }
55 +        if (!*arg)
56 +                arg = "";
57 +        else if (!isstatic)
58 +                arg = savqstr((char *)arg);
59 +
60 +        wrapBSDF[wbsdfac++] = (char *)arg;
61 + }
62 +
63   /* Start new progress bar */
64   #define prog_start(s)   if (do_prog) fprintf(stderr, "%s: %s...\n", progname, s); else
65  
# Line 38 | Line 67 | static int             do_prog = 79;
67   static void
68   prog_show(double frac)
69   {
70 <        char    pbar[256];
71 <        int     nchars;
70 >        static unsigned call_cnt = 0;
71 >        static char     lastc[] = "-\\|/";
72 >        char            pbar[256];
73 >        int             nchars;
74  
75          if (do_prog <= 1) return;
76          if (do_prog > sizeof(pbar)-2)
77                  do_prog = sizeof(pbar)-2;
78          if (frac < 0) frac = 0;
79 <        else if (frac > 1) frac = 1;
80 <        nchars = do_prog*frac + .5;
79 >        else if (frac >= 1) frac = .9999;
80 >        nchars = do_prog*frac;
81          pbar[0] = '\r';
82          memset(pbar+1, '*', nchars);
83 <        memset(pbar+1+nchars, '-', do_prog-nchars);
83 >        pbar[nchars+1] = lastc[call_cnt++ & 3];
84 >        memset(pbar+2+nchars, '-', do_prog-nchars-1);
85          pbar[do_prog+1] = '\0';
86          fputs(pbar, stderr);
87   }
# Line 79 | Line 111 | get_basis(const char *bn)
111          return NULL;
112   }
113  
114 < /* Output XML header to stdout */
115 < static void
116 < xml_header(int ac, char *av[])
114 > /* Copy geometry string to file for wrapBSDF */
115 > static char *
116 > save_geom(const char *mgf)
117   {
118 <        puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
119 <        puts("<WindowElement xmlns=\"http://windows.lbl.gov\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://windows.lbl.gov/BSDF-v1.4.xsd\">");
120 <        fputs("<!-- File produced by:", stdout);
121 <        while (ac-- > 0) {
122 <                fputc(' ', stdout);
123 <                fputs(*av++, stdout);
124 <        }
125 <        puts(" -->");
118 >        char    *tfname = mktemp(savqstr(TEMPLATE));
119 >        int     fd = open(tfname, O_CREAT|O_WRONLY, 0600);
120 >
121 >        if (fd < 0)
122 >                return(NULL);
123 >        write(fd, mgf, strlen(mgf));
124 >        close(fd);
125 >        add_wbsdf("-g", 1);
126 >        add_wbsdf(tfname, 1);
127 >        return(tfname);
128   }
129  
130 < /* Output XML prologue to stdout */
131 < static void
132 < xml_prologue(const SDData *sd)
130 > /* Open XYZ component file for output and add appropriate arguments */
131 > static FILE *
132 > open_component_file(int c)
133   {
134 <        const char      *matn = (sd && sd->matn[0]) ? sd->matn :
135 <                                bsdf_name[0] ? bsdf_name : "Unknown";
136 <        const char      *makr = (sd && sd->makr[0]) ? sd->makr :
137 <                                bsdf_manuf[0] ? bsdf_manuf : "Unknown";
104 <        ANGLE_BASIS     *abp = get_basis(kbasis);
105 <        int             i;
134 >        static const char       sname[3][6] = {"CIE-X", "CIE-Y", "CIE-Z"};
135 >        static const char       cname[4][4] = {"-rf", "-tf", "-tb", "-rb"};
136 >        char                    *tfname = mktemp(savqstr(TEMPLATE));
137 >        FILE                    *fp = fopen(tfname, "w");
138  
139 <        if (abp == NULL) {
140 <                fprintf(stderr, "%s: unknown angle basis '%s'\n", progname, kbasis);
139 >        if (fp == NULL) {
140 >                fprintf(stderr, "%s: cannot open '%s' for writing\n",
141 >                                progname, tfname);
142                  exit(1);
143          }
144 <        puts("<WindowElementType>System</WindowElementType>");
145 <        puts("<FileType>BSDF</FileType>");
146 <        puts("<Optical>");
147 <        puts("<Layer>");
115 <        puts("\t<Material>");
116 <        printf("\t\t<Name>%s</Name>\n", matn);
117 <        printf("\t\t<Manufacturer>%s</Manufacturer>\n", makr);
118 <        if (sd && sd->dim[2] > .001) {
119 <                printf("\t\t<Thickness unit=\"meter\">%.3f</Thickness>\n", sd->dim[2]);
120 <                printf("\t\t<Width unit=\"meter\">%.3f</Width>\n", sd->dim[0]);
121 <                printf("\t\t<Height unit=\"meter\">%.3f</Height>\n", sd->dim[1]);
122 <        }
123 <        puts("\t\t<DeviceType>Other</DeviceType>");
124 <        puts("\t</Material>");
125 <        if (sd && sd->mgf != NULL) {
126 <                puts("\t<Geometry format=\"MGF\">");
127 <                puts("\t\t<MGFblock unit=\"meter\">");
128 <                fputs(sd->mgf, stdout);
129 <                puts("</MGFblock>");
130 <                puts("\t</Geometry>");
131 <        }
132 <        puts("\t<DataDefinition>");
133 <        puts("\t\t<IncidentDataStructure>Columns</IncidentDataStructure>");
134 <        puts("\t\t<AngleBasis>");
135 <        printf("\t\t\t<AngleBasisName>%s</AngleBasisName>\n", kbasis);
136 <        for (i = 0; abp->lat[i].nphis; i++) {
137 <                puts("\t\t\t<AngleBasisBlock>");
138 <                printf("\t\t\t<Theta>%g</Theta>\n", i ?
139 <                                .5*(abp->lat[i].tmin + abp->lat[i+1].tmin) :
140 <                                .0 );
141 <                printf("\t\t\t<nPhis>%d</nPhis>\n", abp->lat[i].nphis);
142 <                puts("\t\t\t<ThetaBounds>");
143 <                printf("\t\t\t\t<LowerTheta>%g</LowerTheta>\n", abp->lat[i].tmin);
144 <                printf("\t\t\t\t<UpperTheta>%g</UpperTheta>\n", abp->lat[i+1].tmin);
145 <                puts("\t\t\t</ThetaBounds>");
146 <                puts("\t\t\t</AngleBasisBlock>");
147 <        }
148 <        puts("\t\t</AngleBasis>");
149 <        puts("\t</DataDefinition>");
144 >        add_wbsdf("-s", 1); add_wbsdf(sname[c], 1);
145 >        add_wbsdf(cname[(input_orient>0)<<1 | (output_orient>0)], 1);
146 >        add_wbsdf(tfname, 1);
147 >        return(fp);
148   }
149  
152 /* Output XML data prologue to stdout */
153 static void
154 data_prologue()
155 {
156        static const char       *bsdf_type[4] = {
157                                        "Reflection Front",
158                                        "Transmission Front",
159                                        "Transmission Back",
160                                        "Reflection Back"
161                                };
162
163        puts("\t<WavelengthData>");
164        puts("\t\t<LayerNumber>System</LayerNumber>");
165        puts("\t\t<Wavelength unit=\"Integral\">Visible</Wavelength>");
166        puts("\t\t<SourceSpectrum>CIE Illuminant D65 1nm.ssp</SourceSpectrum>");
167        puts("\t\t<DetectorSpectrum>ASTM E308 1931 Y.dsp</DetectorSpectrum>");
168        puts("\t\t<WavelengthDataBlock>");
169        printf("\t\t\t<WavelengthDataDirection>%s</WavelengthDataDirection>\n",
170                        bsdf_type[(input_orient>0)<<1 | (output_orient>0)]);
171        printf("\t\t\t<ColumnAngleBasis>%s</ColumnAngleBasis>\n", kbasis);
172        printf("\t\t\t<RowAngleBasis>%s</RowAngleBasis>\n", kbasis);
173        puts("\t\t\t<ScatteringDataType>BTDF</ScatteringDataType>");
174        puts("\t\t\t<ScatteringData>");
175 }
176
177 /* Output XML data epilogue to stdout */
178 static void
179 data_epilogue(void)
180 {
181        puts("\t\t\t</ScatteringData>");
182        puts("\t\t</WavelengthDataBlock>");
183        puts("\t</WavelengthData>");
184 }
185
186 /* Output XML epilogue to stdout */
187 static void
188 xml_epilogue(void)
189 {
190        puts("</Layer>");
191        puts("</Optical>");
192        puts("</WindowElement>");
193 }
194
150   /* Load and resample XML BSDF description using Klems basis */
151   static void
152   eval_bsdf(const char *fname)
153   {
154          ANGLE_BASIS     *abp = get_basis(kbasis);
155 +        FILE            *cfp[3];
156          SDData          bsd;
157          SDError         ec;
158          FVECT           vin, vout;
159 <        SDValue         sv;
160 <        double          sum;
159 >        SDValue         sdv;
160 >        double          sum, xsum, ysum;
161          int             i, j, n;
162  
163 +        initurand(npsamps);
164          SDclearBSDF(&bsd, fname);               /* load BSDF file */
165          if ((ec = SDloadFile(&bsd, fname)) != SDEnone)
166                  goto err;
167 <        xml_prologue(&bsd);                     /* pass geometry */
167 >        if (bsd.mgf != NULL)                    /* save geometry */
168 >                save_geom(bsd.mgf);
169 >        if (bsd.matn[0])                        /* save identifier(s) */
170 >                strcpy(bsdf_name, bsd.matn);
171 >        if (bsd.makr[0])
172 >                strcpy(bsdf_manuf, bsd.makr);
173 >        if (bsd.dim[2] > 0) {                   /* save dimension(s) */
174 >                char    buf[64];
175 >                if ((bsd.dim[0] > 0) & (bsd.dim[1] > 0))
176 >                        sprintf(buf, "w=%g;h=%g;t=%g",
177 >                                        bsd.dim[0], bsd.dim[1], bsd.dim[2]);
178 >                else
179 >                        sprintf(buf, "t=%g", bsd.dim[2]);
180 >                add_wbsdf("-f", 1);
181 >                add_wbsdf(buf, 0);
182 >        }
183                                                  /* front reflection */
184          if (bsd.rf != NULL || bsd.rLambFront.cieY > .002) {
185              input_orient = 1; output_orient = 1;
186 <            data_prologue();
186 >            cfp[CIE_Y] = open_component_file(CIE_Y);
187 >            if (bsd.rf != NULL && bsd.rf->comp[0].cspec[2].flags) {
188 >                rbf_colorimetry = RBCtristimulus;
189 >                cfp[CIE_X] = open_component_file(CIE_X);
190 >                cfp[CIE_Z] = open_component_file(CIE_Z);
191 >            } else
192 >                rbf_colorimetry = RBCphotopic;
193              for (j = 0; j < abp->nangles; j++) {
194                  for (i = 0; i < abp->nangles; i++) {
195                      sum = 0;                    /* average over patches */
196 +                    xsum = ysum = 0;
197                      for (n = npsamps; n-- > 0; ) {
198                          fo_getvec(vout, j+(n+frandom())/npsamps, abp);
199                          fi_getvec(vin, i+urand(n), abp);
200 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
200 >                        ec = SDevalBSDF(&sdv, vout, vin, &bsd);
201                          if (ec != SDEnone)
202                                  goto err;
203 <                        sum += sv.cieY;
203 >                        sum += sdv.cieY;
204 >                        if (rbf_colorimetry == RBCtristimulus) {
205 >                                c_ccvt(&sdv.spec, C_CSXY);
206 >                                xsum += sdv.cieY * sdv.spec.cx;
207 >                                ysum += sdv.cieY * sdv.spec.cy;
208 >                        }
209                      }
210 <                    printf("\t%.3e\n", sum/npsamps);
210 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
211 >                    if (rbf_colorimetry == RBCtristimulus) {
212 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
213 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
214 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
215 >                    }
216                  }
217 <                putchar('\n');                  /* extra space between rows */
217 >                fputc('\n', cfp[CIE_Y]);        /* extra space between rows */
218 >                if (rbf_colorimetry == RBCtristimulus) {
219 >                        fputc('\n', cfp[CIE_X]);
220 >                        fputc('\n', cfp[CIE_Z]);
221 >                }
222              }
223 <            data_epilogue();
223 >            if (fclose(cfp[CIE_Y])) {
224 >                fprintf(stderr, "%s: error writing Y output\n", progname);
225 >                exit(1);
226 >            }
227 >            if (rbf_colorimetry == RBCtristimulus &&
228 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
229 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
230 >                exit(1);
231 >            }
232          }
233                                                  /* back reflection */
234          if (bsd.rb != NULL || bsd.rLambBack.cieY > .002) {
235              input_orient = -1; output_orient = -1;
236 <            data_prologue();
236 >            cfp[CIE_Y] = open_component_file(CIE_Y);
237 >            if (bsd.rb != NULL && bsd.rb->comp[0].cspec[2].flags) {
238 >                rbf_colorimetry = RBCtristimulus;
239 >                cfp[CIE_X] = open_component_file(CIE_X);
240 >                cfp[CIE_Z] = open_component_file(CIE_Z);
241 >            } else
242 >                rbf_colorimetry = RBCphotopic;
243              for (j = 0; j < abp->nangles; j++) {
244                  for (i = 0; i < abp->nangles; i++) {
245                      sum = 0;                    /* average over patches */
246 +                    xsum = ysum = 0;
247                      for (n = npsamps; n-- > 0; ) {
248                          bo_getvec(vout, j+(n+frandom())/npsamps, abp);
249                          bi_getvec(vin, i+urand(n), abp);
250 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
250 >                        ec = SDevalBSDF(&sdv, vout, vin, &bsd);
251                          if (ec != SDEnone)
252                                  goto err;
253 <                        sum += sv.cieY;
253 >                        sum += sdv.cieY;
254 >                        if (rbf_colorimetry == RBCtristimulus) {
255 >                                c_ccvt(&sdv.spec, C_CSXY);
256 >                                xsum += sdv.cieY * sdv.spec.cx;
257 >                                ysum += sdv.cieY * sdv.spec.cy;
258 >                        }
259                      }
260 <                    printf("\t%.3e\n", sum/npsamps);
260 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
261 >                    if (rbf_colorimetry == RBCtristimulus) {
262 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
263 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
264 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
265 >                    }
266                  }
267 <                putchar('\n');                  /* extra space between rows */
267 >                if (rbf_colorimetry == RBCtristimulus) {
268 >                        fputc('\n', cfp[CIE_X]);
269 >                        fputc('\n', cfp[CIE_Z]);
270 >                }
271              }
272 <            data_epilogue();
272 >            if (fclose(cfp[CIE_Y])) {
273 >                fprintf(stderr, "%s: error writing Y output\n", progname);
274 >                exit(1);
275 >            }
276 >            if (rbf_colorimetry == RBCtristimulus &&
277 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
278 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
279 >                exit(1);
280 >            }
281          }
282                                                  /* front transmission */
283          if (bsd.tf != NULL || bsd.tLamb.cieY > .002) {
284              input_orient = 1; output_orient = -1;
285 <            data_prologue();
285 >            cfp[CIE_Y] = open_component_file(CIE_Y);
286 >            if (bsd.tf != NULL && bsd.tf->comp[0].cspec[2].flags) {
287 >                rbf_colorimetry = RBCtristimulus;
288 >                cfp[CIE_X] = open_component_file(CIE_X);
289 >                cfp[CIE_Z] = open_component_file(CIE_Z);
290 >            } else
291 >                rbf_colorimetry = RBCphotopic;
292              for (j = 0; j < abp->nangles; j++) {
293                  for (i = 0; i < abp->nangles; i++) {
294                      sum = 0;                    /* average over patches */
295 +                    xsum = ysum = 0;
296                      for (n = npsamps; n-- > 0; ) {
297                          bo_getvec(vout, j+(n+frandom())/npsamps, abp);
298                          fi_getvec(vin, i+urand(n), abp);
299 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
299 >                        ec = SDevalBSDF(&sdv, vout, vin, &bsd);
300                          if (ec != SDEnone)
301                                  goto err;
302 <                        sum += sv.cieY;
302 >                        sum += sdv.cieY;
303 >                        if (rbf_colorimetry == RBCtristimulus) {
304 >                                c_ccvt(&sdv.spec, C_CSXY);
305 >                                xsum += sdv.cieY * sdv.spec.cx;
306 >                                ysum += sdv.cieY * sdv.spec.cy;
307 >                        }
308                      }
309 <                    printf("\t%.3e\n", sum/npsamps);
309 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
310 >                    if (rbf_colorimetry == RBCtristimulus) {
311 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
312 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
313 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
314 >                    }
315                  }
316 <                putchar('\n');                  /* extra space between rows */
316 >                if (rbf_colorimetry == RBCtristimulus) {
317 >                        fputc('\n', cfp[CIE_X]);
318 >                        fputc('\n', cfp[CIE_Z]);
319 >                }
320              }
321 <            data_epilogue();
321 >            if (fclose(cfp[CIE_Y])) {
322 >                fprintf(stderr, "%s: error writing Y output\n", progname);
323 >                exit(1);
324 >            }
325 >            if (rbf_colorimetry == RBCtristimulus &&
326 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
327 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
328 >                exit(1);
329 >            }
330          }
331                                                  /* back transmission */
332          if ((bsd.tb != NULL) | (bsd.tf != NULL)) {
333              input_orient = -1; output_orient = 1;
334 <            data_prologue();
334 >            cfp[CIE_Y] = open_component_file(CIE_Y);
335 >            if (bsd.tb != NULL)
336 >                rbf_colorimetry = bsd.tb->comp[0].cspec[2].flags
337 >                                        ? RBCtristimulus : RBCphotopic ;
338 >            if (rbf_colorimetry == RBCtristimulus) {
339 >                cfp[CIE_X] = open_component_file(CIE_X);
340 >                cfp[CIE_Z] = open_component_file(CIE_Z);
341 >            }
342              for (j = 0; j < abp->nangles; j++) {
343                  for (i = 0; i < abp->nangles; i++) {
344                      sum = 0;            /* average over patches */
345 +                    xsum = ysum = 0;
346                      for (n = npsamps; n-- > 0; ) {
347                          fo_getvec(vout, j+(n+frandom())/npsamps, abp);
348                          bi_getvec(vin, i+urand(n), abp);
349 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
349 >                        ec = SDevalBSDF(&sdv, vout, vin, &bsd);
350                          if (ec != SDEnone)
351                                  goto err;
352 <                        sum += sv.cieY;
352 >                        sum += sdv.cieY;
353 >                        if (rbf_colorimetry == RBCtristimulus) {
354 >                                c_ccvt(&sdv.spec, C_CSXY);
355 >                                xsum += sdv.cieY * sdv.spec.cx;
356 >                                ysum += sdv.cieY * sdv.spec.cy;
357 >                        }
358                      }
359 <                    printf("\t%.3e\n", sum/npsamps);
359 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
360 >                    if (rbf_colorimetry == RBCtristimulus) {
361 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
362 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
363 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
364 >                    }
365                  }
366 <                putchar('\n');                  /* extra space between rows */
366 >                if (rbf_colorimetry == RBCtristimulus) {
367 >                        fputc('\n', cfp[CIE_X]);
368 >                        fputc('\n', cfp[CIE_Z]);
369 >                }
370              }
371 <            data_epilogue();
371 >            if (fclose(cfp[CIE_Y])) {
372 >                fprintf(stderr, "%s: error writing Y output\n", progname);
373 >                exit(1);
374 >            }
375 >            if (rbf_colorimetry == RBCtristimulus &&
376 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
377 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
378 >                exit(1);
379 >            }
380          }
381          SDfreeBSDF(&bsd);                       /* all done */
382          return;
# Line 305 | Line 391 | eval_function(char *funame)
391   {
392          ANGLE_BASIS     *abp = get_basis(kbasis);
393          int             assignD = (fundefined(funame) < 6);
394 +        FILE            *ofp = open_component_file(CIE_Y);
395          double          iovec[6];
396          double          sum;
397          int             i, j, n;
398  
399          initurand(npsamps);
313        data_prologue();                        /* begin output */
400          for (j = 0; j < abp->nangles; j++) {    /* run through directions */
401              for (i = 0; i < abp->nangles; i++) {
402                  sum = 0;
# Line 333 | Line 419 | eval_function(char *funame)
419                      }
420                      sum += funvalue(funame, 6, iovec);
421                  }
422 <                printf("\t%.3e\n", sum/npsamps);
422 >                fprintf(ofp, "\t%.3e\n", sum/npsamps);
423              }
424 <            putchar('\n');
424 >            fputc('\n', ofp);
425              prog_show((j+1.)/abp->nangles);
426          }
341        data_epilogue();                        /* finish output */
427          prog_done();
428 +        if (fclose(ofp)) {
429 +                fprintf(stderr, "%s: error writing Y output\n", progname);
430 +                exit(1);
431 +        }
432   }
433  
434   /* Interpolate and output a radial basis function BSDF representation */
# Line 347 | Line 436 | static void
436   eval_rbf(void)
437   {
438          ANGLE_BASIS     *abp = get_basis(kbasis);
439 +        float           (*XZarr)[2] = NULL;
440          float           bsdfarr[MAXPATCHES*MAXPATCHES];
441 +        FILE            *cfp[3];
442          FVECT           vin, vout;
443 <        RBFNODE         *rbf;
353 <        double          sum;
443 >        double          sum, xsum, ysum;
444          int             i, j, n;
445                                                  /* sanity check */
446          if (abp->nangles > MAXPATCHES) {
447                  fprintf(stderr, "%s: too many patches!\n", progname);
448                  exit(1);
449          }
450 <        data_prologue();                        /* begin output */
450 >        if (rbf_colorimetry == RBCtristimulus)
451 >                XZarr = (float (*)[2])malloc(sizeof(float)*2*abp->nangles*abp->nangles);
452          for (i = 0; i < abp->nangles; i++) {
453 +            RBFNODE     *rbf;
454              if (input_orient > 0)               /* use incident patch center */
455                  fi_getvec(vin, i+.5*(i>0), abp);
456              else
# Line 368 | Line 460 | eval_rbf(void)
460  
461              for (j = 0; j < abp->nangles; j++) {
462                  sum = 0;                        /* sample over exiting patch */
463 +                xsum = ysum = 0;
464                  for (n = npsamps; n--; ) {
465 +                    SDValue     sdv;
466                      if (output_orient > 0)
467                          fo_getvec(vout, j+(n+frandom())/npsamps, abp);
468                      else
469                          bo_getvec(vout, j+(n+frandom())/npsamps, abp);
470  
471 <                    sum += eval_rbfrep(rbf, vout);
471 >                    eval_rbfcol(&sdv, rbf, vout);
472 >                    sum += sdv.cieY;
473 >                    if (XZarr != NULL) {
474 >                        c_ccvt(&sdv.spec, C_CSXY);
475 >                        xsum += sdv.cieY * sdv.spec.cx;
476 >                        ysum += sdv.cieY * sdv.spec.cy;
477 >                    }
478                  }
479 <                fo_getvec(vout, j+.5, abp);     /* use centered secant */
480 <                bsdfarr[j*abp->nangles + i] = sum / (double)npsamps;
479 >                n = j*abp->nangles + i;
480 >                bsdfarr[n] = sum / npsamps;
481 >                if (XZarr != NULL) {
482 >                    XZarr[n][0] = xsum*sum/(npsamps*ysum);
483 >                    XZarr[n][1] = (sum - xsum - ysum)*sum/(npsamps*ysum);
484 >                }
485              }
486              if (rbf != NULL)
487                  free(rbf);
488              prog_show((i+1.)/abp->nangles);
489          }
490 <        n = 0;                                  /* write out our matrix */
490 >                                                /* write out our matrix */
491 >        cfp[CIE_Y] = open_component_file(CIE_Y);
492 >        n = 0;
493          for (j = 0; j < abp->nangles; j++) {
494 <            for (i = 0; i < abp->nangles; i++)
495 <                printf("\t%.3e\n", bsdfarr[n++]);
496 <            putchar('\n');
494 >            for (i = 0; i < abp->nangles; i++, n++)
495 >                fprintf(cfp[CIE_Y], "\t%.3e\n", bsdfarr[n]);
496 >            fputc('\n', cfp[CIE_Y]);
497          }
392        data_epilogue();                        /* finish output */
498          prog_done();
499 +        if (fclose(cfp[CIE_Y])) {
500 +                fprintf(stderr, "%s: error writing Y output\n", progname);
501 +                exit(1);
502 +        }
503 +        if (XZarr == NULL)                      /* no color? */
504 +                return;
505 +        cfp[CIE_X] = open_component_file(CIE_X);
506 +        cfp[CIE_Z] = open_component_file(CIE_Z);
507 +        n = 0;
508 +        for (j = 0; j < abp->nangles; j++) {
509 +            for (i = 0; i < abp->nangles; i++, n++) {
510 +                fprintf(cfp[CIE_X], "\t%.3e\n", XZarr[n][0]);
511 +                fprintf(cfp[CIE_Z], "\t%.3e\n", XZarr[n][1]);
512 +            }
513 +            fputc('\n', cfp[CIE_X]);
514 +            fputc('\n', cfp[CIE_Z]);
515 +        }
516 +        free(XZarr);
517 +        if (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z])) {
518 +                fprintf(stderr, "%s: error writing X/Z output\n", progname);
519 +                exit(1);
520 +        }
521   }
522  
523 + #ifdef _WIN32
524 + /* Execute wrapBSDF command (may never return) */
525 + static int
526 + wrap_up(void)
527 + {
528 +        char    cmd[8192];
529 +
530 +        if (bsdf_manuf[0]) {
531 +                add_wbsdf("-f", 1);
532 +                strcpy(cmd, "m=");
533 +                strcpy(cmd+2, bsdf_manuf);
534 +                add_wbsdf(cmd, 0);
535 +        }
536 +        if (bsdf_name[0]) {
537 +                add_wbsdf("-f", 1);
538 +                strcpy(cmd, "n=");
539 +                strcpy(cmd+2, bsdf_name);
540 +                add_wbsdf(cmd, 0);
541 +        }
542 +        if (!convert_commandline(cmd, sizeof(cmd), wrapBSDF)) {
543 +                fputs(progname, stderr);
544 +                fputs(": command line too long in wrap_up()\n", stderr);
545 +                return(1);
546 +        }
547 +        return(system(cmd));
548 + }
549 + #else
550 + /* Execute wrapBSDF command (may never return) */
551 + static int
552 + wrap_up(void)
553 + {
554 +        char    buf[256];
555 +        char    *compath = getpath((char *)wrapBSDF[0], getenv("PATH"), X_OK);
556 +
557 +        if (compath == NULL) {
558 +                fprintf(stderr, "%s: cannot locate %s\n", progname, wrapBSDF[0]);
559 +                return(1);
560 +        }
561 +        if (bsdf_manuf[0]) {
562 +                add_wbsdf("-f", 1);
563 +                strcpy(buf, "m=");
564 +                strcpy(buf+2, bsdf_manuf);
565 +                add_wbsdf(buf, 0);
566 +        }
567 +        if (bsdf_name[0]) {
568 +                add_wbsdf("-f", 1);
569 +                strcpy(buf, "n=");
570 +                strcpy(buf+2, bsdf_name);
571 +                add_wbsdf(buf, 0);
572 +        }
573 +        execv(compath, wrapBSDF);       /* successful call never returns */
574 +        perror(compath);
575 +        return(1);
576 + }
577 + #endif
578 +
579   /* Read in BSDF and interpolate as Klems matrix representation */
580   int
581   main(int argc, char *argv[])
582   {
583          int     dofwd = 0, dobwd = 1;
584 +        char    buf[2048];
585          char    *cp;
586          int     i, na;
587  
# Line 419 | Line 603 | main(int argc, char *argv[])
603                          break;
604                  case 'f':
605                          if (!argv[i][2]) {
606 <                                fcompile(argv[++i]);
607 <                                single_plane_incident = 0;
606 >                                if (strchr(argv[++i], '=') != NULL) {
607 >                                        add_wbsdf("-f", 1);
608 >                                        add_wbsdf(argv[i], 1);
609 >                                } else {
610 >                                        fcompile(argv[i]);
611 >                                        single_plane_incident = 0;
612 >                                }
613                          } else
614                                  dofwd = (argv[i][0] == '+');
615                          break;
# Line 428 | Line 617 | main(int argc, char *argv[])
617                          dobwd = (argv[i][0] == '+');
618                          break;
619                  case 'h':
620 <                        kbasis = "LBNL/Klems Half";
620 >                        kbasis = klems_half;
621 >                        add_wbsdf("-a", 1);
622 >                        add_wbsdf("kh", 1);
623                          break;
624                  case 'q':
625 <                        kbasis = "LBNL/Klems Quarter";
625 >                        kbasis = klems_quarter;
626 >                        add_wbsdf("-a", 1);
627 >                        add_wbsdf("kq", 1);
628                          break;
629                  case 'l':
630                          lobe_lim = atoi(argv[++i]);
# Line 439 | Line 632 | main(int argc, char *argv[])
632                  case 'p':
633                          do_prog = atoi(argv[i]+2);
634                          break;
635 +                case 'C':
636 +                        add_wbsdf(argv[i], 1);
637 +                        add_wbsdf(argv[++i], 1);
638 +                        break;
639                  default:
640                          goto userr;
641                  }
642 +        if (kbasis == klems_full) {             /* default (full) basis? */
643 +                add_wbsdf("-a", 1);
644 +                add_wbsdf("kf", 1);
645 +        }
646 +        strcpy(buf, "File produced by: ");
647 +        if (convert_commandline(buf+18, sizeof(buf)-18, argv) != NULL) {
648 +                add_wbsdf("-C", 1); add_wbsdf(buf, 0);
649 +        }
650          if (single_plane_incident >= 0) {       /* function-based BSDF? */
651 <                if (i != argc-1 || fundefined(argv[i]) != 6) {
651 >                if (i != argc-1 || fundefined(argv[i]) < 3) {
652                          fprintf(stderr,
653          "%s: need single function with 6 arguments: bsdf(ix,iy,iz,ox,oy,oz)\n",
654                                          progname);
# Line 451 | Line 656 | main(int argc, char *argv[])
656                          goto userr;
657                  }
658                  ++eclock;
454                xml_header(argc, argv);                 /* start XML output */
455                xml_prologue(NULL);
659                  if (dofwd) {
660                          input_orient = -1;
661                          output_orient = -1;
# Line 471 | Line 674 | main(int argc, char *argv[])
674                          prog_start("Evaluating inside->outside transmission");
675                          eval_function(argv[i]);
676                  }
677 <                xml_epilogue();                 /* finish XML output & exit */
475 <                return(0);
677 >                return(wrap_up());
678          }
679                                                  /* XML input? */
680          if (i == argc-1 && (cp = argv[i]+strlen(argv[i])-4) > argv[i] &&
681                                  !strcasecmp(cp, ".xml")) {
480                xml_header(argc, argv);         /* start XML output */
682                  eval_bsdf(argv[i]);             /* load & resample BSDF */
683 <                xml_epilogue();                 /* finish XML output & exit */
483 <                return(0);
683 >                return(wrap_up());
684          }
685          if (i < argc) {                         /* open input files if given */
686                  int     nbsdf = 0;
# Line 495 | Line 695 | main(int argc, char *argv[])
695                          if (!load_bsdf_rep(fpin))
696                                  return(1);
697                          fclose(fpin);
498                        if (!nbsdf++) {         /* start XML on first dist. */
499                                xml_header(argc, argv);
500                                xml_prologue(NULL);
501                        }
698                          sprintf(pbuf, "Interpolating component '%s'", argv[i]);
699                          prog_start(pbuf);
700                          eval_rbf();
701                  }
702 <                xml_epilogue();                 /* finish XML output & exit */
507 <                return(0);
702 >                return(wrap_up());
703          }
704          SET_FILE_BINARY(stdin);                 /* load from stdin */
705          if (!load_bsdf_rep(stdin))
706                  return(1);
512        xml_header(argc, argv);                 /* start XML output */
513        xml_prologue(NULL);
707          prog_start("Interpolating from standard input");
708          eval_rbf();                             /* resample dist. */
709 <        xml_epilogue();                         /* finish XML output & exit */
517 <        return(0);
709 >        return(wrap_up());
710   userr:
711          fprintf(stderr,
712          "Usage: %s [-n spp][-h|-q][-l maxlobes] [bsdf.sir ..] > bsdf.xml\n", progname);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines