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.16 by greg, Wed Oct 1 23:32:42 2014 UTC vs.
Revision 2.37 by greg, Tue Jun 3 21:31:51 2025 UTC

# Line 8 | Line 8 | static const char RCSid[] = "$Id$";
8   */
9  
10   #define _USE_MATH_DEFINES
11 #include <stdio.h>
11   #include <stdlib.h>
13 #include <string.h>
12   #include <math.h>
13 + #include <ctype.h>
14   #include "random.h"
15   #include "platform.h"
16 + #include "paths.h"
17 + #include "rtio.h"
18   #include "calcomp.h"
19   #include "bsdfrep.h"
20   #include "bsdf_m.h"
21 +                                /* tristimulus components */
22 + enum {CIE_X, CIE_Y, CIE_Z};
23                                  /* assumed maximum # Klems patches */
24   #define MAXPATCHES      145
22                                /* global argv[0] */
23 char                    *progname;
25                                  /* selected basis function name */
26 < static const char       *kbasis = "LBNL/Klems Full";
26 > static const char       klems_full[] = "LBNL/Klems Full";
27 > static const char       klems_half[] = "LBNL/Klems Half";
28 > static const char       klems_quarter[] = "LBNL/Klems Quarter";
29 > static const char       *kbasis = klems_full;
30                                  /* number of BSDF samples per patch */
31 < static int              npsamps = 256;
31 > static int              npsamps = 1024;
32                                  /* limit on number of RBF lobes */
33   static int              lobe_lim = 15000;
34                                  /* progress bar length */
35   static int              do_prog = 79;
36  
37 + #define MAXCARG         512     /* wrapBSDF command */
38 + static char             *wrapBSDF[MAXCARG] = {"wrapBSDF", "-W", "-UU"};
39 + static int              wbsdfac = 3;
40  
41 + /* Add argument to wrapBSDF, allocating space if !isstatic */
42 + static void
43 + add_wbsdf(const char *arg, int isstatic)
44 + {
45 +        if (arg == NULL)
46 +                return;
47 +        if (wbsdfac >= MAXCARG-1) {
48 +                fputs(progname, stderr);
49 +                fputs(": too many command arguments to wrapBSDF\n", stderr);
50 +                exit(1);
51 +        }
52 +        if (!*arg)
53 +                arg = "";
54 +        else if (!isstatic)
55 +                arg = savqstr((char *)arg);
56 +
57 +        wrapBSDF[wbsdfac++] = (char *)arg;
58 + }
59 +
60   /* Start new progress bar */
61   #define prog_start(s)   if (do_prog) fprintf(stderr, "%s: %s...\n", progname, s); else
62  
# Line 38 | Line 64 | static int             do_prog = 79;
64   static void
65   prog_show(double frac)
66   {
67 <        char    pbar[256];
68 <        int     nchars;
67 >        static unsigned call_cnt = 0;
68 >        static char     lastc[] = "-\\|/";
69 >        char            pbar[256];
70 >        int             nchars;
71  
72          if (do_prog <= 1) return;
73          if (do_prog > sizeof(pbar)-2)
74                  do_prog = sizeof(pbar)-2;
75          if (frac < 0) frac = 0;
76 <        else if (frac > 1) frac = 1;
77 <        nchars = do_prog*frac + .5;
76 >        else if (frac >= 1) frac = .9999;
77 >        nchars = do_prog*frac;
78          pbar[0] = '\r';
79          memset(pbar+1, '*', nchars);
80 <        memset(pbar+1+nchars, '-', do_prog-nchars);
80 >        pbar[nchars+1] = lastc[call_cnt++ & 3];
81 >        memset(pbar+2+nchars, '-', do_prog-nchars-1);
82          pbar[do_prog+1] = '\0';
83          fputs(pbar, stderr);
84   }
# Line 79 | Line 108 | get_basis(const char *bn)
108          return NULL;
109   }
110  
111 < /* Output XML header to stdout */
112 < static void
113 < xml_header(int ac, char *av[])
111 > /* Copy geometry string to file for wrapBSDF */
112 > static char *
113 > save_geom(const char *mgf)
114   {
115 <        puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
116 <        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\">");
117 <        fputs("<!-- File produced by:", stdout);
118 <        while (ac-- > 0) {
119 <                fputc(' ', stdout);
120 <                fputs(*av++, stdout);
121 <        }
122 <        puts(" -->");
115 >        char    *tfname = mktemp(savqstr(TEMPLATE));
116 >        int     fd = open(tfname, O_CREAT|O_WRONLY, 0600);
117 >
118 >        if (fd < 0)
119 >                return(NULL);
120 >        write(fd, mgf, strlen(mgf));
121 >        close(fd);
122 >        add_wbsdf("-g", 1);
123 >        add_wbsdf(tfname, 1);
124 >        return(tfname);
125   }
126  
127 < /* Output XML prologue to stdout */
128 < static void
129 < xml_prologue(const SDData *sd)
127 > /* Open XYZ component file for output and add appropriate arguments */
128 > static FILE *
129 > open_component_file(int c)
130   {
131 <        const char      *matn = (sd && sd->matn[0]) ? sd->matn :
132 <                                bsdf_name[0] ? bsdf_name : "Unknown";
133 <        const char      *makr = (sd && sd->makr[0]) ? sd->makr :
134 <                                bsdf_manuf[0] ? bsdf_manuf : "Unknown";
104 <        ANGLE_BASIS     *abp = get_basis(kbasis);
105 <        int             i;
131 >        static const char       sname[3][6] = {"CIE-X", "CIE-Y", "CIE-Z"};
132 >        static const char       cname[4][4] = {"-rf", "-tf", "-tb", "-rb"};
133 >        char                    *tfname = mktemp(savqstr(TEMPLATE));
134 >        FILE                    *fp = fopen(tfname, "w");
135  
136 <        if (abp == NULL) {
137 <                fprintf(stderr, "%s: unknown angle basis '%s'\n", progname, kbasis);
136 >        if (fp == NULL) {
137 >                fprintf(stderr, "%s: cannot open '%s' for writing\n",
138 >                                progname, tfname);
139                  exit(1);
140          }
141 <        puts("<WindowElementType>System</WindowElementType>");
142 <        puts("<FileType>BSDF</FileType>");
143 <        puts("<Optical>");
144 <        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>");
141 >        add_wbsdf("-s", 1); add_wbsdf(sname[c], 1);
142 >        add_wbsdf(cname[(input_orient>0)<<1 | (output_orient>0)], 1);
143 >        add_wbsdf(tfname, 1);
144 >        return(fp);
145   }
146  
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
147   /* Load and resample XML BSDF description using Klems basis */
148   static void
149   eval_bsdf(const char *fname)
150   {
151          ANGLE_BASIS     *abp = get_basis(kbasis);
152 +        FILE            *cfp[3];
153          SDData          bsd;
154          SDError         ec;
155          FVECT           vin, vout;
156 <        SDValue         sv;
157 <        double          sum;
156 >        SDValue         sdv;
157 >        double          sum, xsum, ysum;
158          int             i, j, n;
159  
160 +        initurand(npsamps);
161          SDclearBSDF(&bsd, fname);               /* load BSDF file */
162          if ((ec = SDloadFile(&bsd, fname)) != SDEnone)
163                  goto err;
164 <        xml_prologue(&bsd);                     /* pass geometry */
164 >        if (bsd.mgf != NULL)                    /* save geometry */
165 >                save_geom(bsd.mgf);
166 >        if (bsd.matn[0])                        /* save identifier(s) */
167 >                strcpy(bsdf_name, bsd.matn);
168 >        if (bsd.makr[0])
169 >                strcpy(bsdf_manuf, bsd.makr);
170 >        if (bsd.dim[2] > 0) {                   /* save dimension(s) */
171 >                char    buf[64];
172 >                if ((bsd.dim[0] > 0) & (bsd.dim[1] > 0))
173 >                        sprintf(buf, "w=%g;h=%g;t=%g",
174 >                                        bsd.dim[0], bsd.dim[1], bsd.dim[2]);
175 >                else
176 >                        sprintf(buf, "t=%g", bsd.dim[2]);
177 >                add_wbsdf("-f", 1);
178 >                add_wbsdf(buf, 0);
179 >        }
180                                                  /* front reflection */
181          if (bsd.rf != NULL || bsd.rLambFront.cieY > .002) {
182              input_orient = 1; output_orient = 1;
183 <            data_prologue();
183 >            cfp[CIE_Y] = open_component_file(CIE_Y);
184 >            if (bsd.rf != NULL && bsd.rf->comp[0].cspec[2].flags) {
185 >                rbf_colorimetry = RBCtristimulus;
186 >                cfp[CIE_X] = open_component_file(CIE_X);
187 >                cfp[CIE_Z] = open_component_file(CIE_Z);
188 >            } else
189 >                rbf_colorimetry = RBCphotopic;
190              for (j = 0; j < abp->nangles; j++) {
191                  for (i = 0; i < abp->nangles; i++) {
192                      sum = 0;                    /* average over patches */
193 +                    xsum = ysum = 0;
194                      for (n = npsamps; n-- > 0; ) {
195                          fo_getvec(vout, j+(n+frandom())/npsamps, abp);
196                          fi_getvec(vin, i+urand(n), abp);
197 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
197 >                        ec = SDevalBSDF(&sdv, vin, vout, &bsd);
198                          if (ec != SDEnone)
199                                  goto err;
200 <                        sum += sv.cieY;
200 >                        sum += sdv.cieY;
201 >                        if (rbf_colorimetry == RBCtristimulus) {
202 >                                xsum += sdv.cieY * sdv.spec.cx;
203 >                                ysum += sdv.cieY * sdv.spec.cy;
204 >                        }
205                      }
206 <                    printf("\t%.3e\n", sum/npsamps);
206 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
207 >                    if (rbf_colorimetry == RBCtristimulus) {
208 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
209 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
210 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
211 >                    }
212                  }
213 <                putchar('\n');                  /* extra space between rows */
213 >                fputc('\n', cfp[CIE_Y]);        /* extra space between rows */
214 >                if (rbf_colorimetry == RBCtristimulus) {
215 >                        fputc('\n', cfp[CIE_X]);
216 >                        fputc('\n', cfp[CIE_Z]);
217 >                }
218              }
219 <            data_epilogue();
219 >            if (fclose(cfp[CIE_Y])) {
220 >                fprintf(stderr, "%s: error writing Y output\n", progname);
221 >                exit(1);
222 >            }
223 >            if (rbf_colorimetry == RBCtristimulus &&
224 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
225 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
226 >                exit(1);
227 >            }
228          }
229                                                  /* back reflection */
230          if (bsd.rb != NULL || bsd.rLambBack.cieY > .002) {
231              input_orient = -1; output_orient = -1;
232 <            data_prologue();
232 >            cfp[CIE_Y] = open_component_file(CIE_Y);
233 >            if (bsd.rb != NULL && bsd.rb->comp[0].cspec[2].flags) {
234 >                rbf_colorimetry = RBCtristimulus;
235 >                cfp[CIE_X] = open_component_file(CIE_X);
236 >                cfp[CIE_Z] = open_component_file(CIE_Z);
237 >            } else
238 >                rbf_colorimetry = RBCphotopic;
239              for (j = 0; j < abp->nangles; j++) {
240                  for (i = 0; i < abp->nangles; i++) {
241                      sum = 0;                    /* average over patches */
242 +                    xsum = ysum = 0;
243                      for (n = npsamps; n-- > 0; ) {
244                          bo_getvec(vout, j+(n+frandom())/npsamps, abp);
245                          bi_getvec(vin, i+urand(n), abp);
246 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
246 >                        ec = SDevalBSDF(&sdv, vin, vout, &bsd);
247                          if (ec != SDEnone)
248                                  goto err;
249 <                        sum += sv.cieY;
249 >                        sum += sdv.cieY;
250 >                        if (rbf_colorimetry == RBCtristimulus) {
251 >                                xsum += sdv.cieY * sdv.spec.cx;
252 >                                ysum += sdv.cieY * sdv.spec.cy;
253 >                        }
254                      }
255 <                    printf("\t%.3e\n", sum/npsamps);
255 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
256 >                    if (rbf_colorimetry == RBCtristimulus) {
257 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
258 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
259 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
260 >                    }
261                  }
262 <                putchar('\n');                  /* extra space between rows */
262 >                if (rbf_colorimetry == RBCtristimulus) {
263 >                        fputc('\n', cfp[CIE_X]);
264 >                        fputc('\n', cfp[CIE_Z]);
265 >                }
266              }
267 <            data_epilogue();
267 >            if (fclose(cfp[CIE_Y])) {
268 >                fprintf(stderr, "%s: error writing Y output\n", progname);
269 >                exit(1);
270 >            }
271 >            if (rbf_colorimetry == RBCtristimulus &&
272 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
273 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
274 >                exit(1);
275 >            }
276          }
277                                                  /* front transmission */
278 <        if (bsd.tf != NULL || bsd.tLamb.cieY > .002) {
278 >        if (bsd.tf != NULL || bsd.tLambFront.cieY > .002) {
279              input_orient = 1; output_orient = -1;
280 <            data_prologue();
280 >            cfp[CIE_Y] = open_component_file(CIE_Y);
281 >            if (bsd.tf != NULL && bsd.tf->comp[0].cspec[2].flags) {
282 >                rbf_colorimetry = RBCtristimulus;
283 >                cfp[CIE_X] = open_component_file(CIE_X);
284 >                cfp[CIE_Z] = open_component_file(CIE_Z);
285 >            } else
286 >                rbf_colorimetry = RBCphotopic;
287              for (j = 0; j < abp->nangles; j++) {
288                  for (i = 0; i < abp->nangles; i++) {
289                      sum = 0;                    /* average over patches */
290 +                    xsum = ysum = 0;
291                      for (n = npsamps; n-- > 0; ) {
292                          bo_getvec(vout, j+(n+frandom())/npsamps, abp);
293                          fi_getvec(vin, i+urand(n), abp);
294 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
294 >                        ec = SDevalBSDF(&sdv, vin, vout, &bsd);
295                          if (ec != SDEnone)
296                                  goto err;
297 <                        sum += sv.cieY;
297 >                        sum += sdv.cieY;
298 >                        if (rbf_colorimetry == RBCtristimulus) {
299 >                                xsum += sdv.cieY * sdv.spec.cx;
300 >                                ysum += sdv.cieY * sdv.spec.cy;
301 >                        }
302                      }
303 <                    printf("\t%.3e\n", sum/npsamps);
303 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
304 >                    if (rbf_colorimetry == RBCtristimulus) {
305 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
306 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
307 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
308 >                    }
309                  }
310 <                putchar('\n');                  /* extra space between rows */
310 >                if (rbf_colorimetry == RBCtristimulus) {
311 >                        fputc('\n', cfp[CIE_X]);
312 >                        fputc('\n', cfp[CIE_Z]);
313 >                }
314              }
315 <            data_epilogue();
315 >            if (fclose(cfp[CIE_Y])) {
316 >                fprintf(stderr, "%s: error writing Y output\n", progname);
317 >                exit(1);
318 >            }
319 >            if (rbf_colorimetry == RBCtristimulus &&
320 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
321 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
322 >                exit(1);
323 >            }
324          }
325                                                  /* back transmission */
326          if ((bsd.tb != NULL) | (bsd.tf != NULL)) {
327              input_orient = -1; output_orient = 1;
328 <            data_prologue();
328 >            cfp[CIE_Y] = open_component_file(CIE_Y);
329 >            if (bsd.tb != NULL)
330 >                rbf_colorimetry = bsd.tb->comp[0].cspec[2].flags
331 >                                        ? RBCtristimulus : RBCphotopic ;
332 >            if (rbf_colorimetry == RBCtristimulus) {
333 >                cfp[CIE_X] = open_component_file(CIE_X);
334 >                cfp[CIE_Z] = open_component_file(CIE_Z);
335 >            }
336              for (j = 0; j < abp->nangles; j++) {
337                  for (i = 0; i < abp->nangles; i++) {
338                      sum = 0;            /* average over patches */
339 +                    xsum = ysum = 0;
340                      for (n = npsamps; n-- > 0; ) {
341                          fo_getvec(vout, j+(n+frandom())/npsamps, abp);
342                          bi_getvec(vin, i+urand(n), abp);
343 <                        ec = SDevalBSDF(&sv, vout, vin, &bsd);
343 >                        ec = SDevalBSDF(&sdv, vin, vout, &bsd);
344                          if (ec != SDEnone)
345                                  goto err;
346 <                        sum += sv.cieY;
346 >                        sum += sdv.cieY;
347 >                        if (rbf_colorimetry == RBCtristimulus) {
348 >                                xsum += sdv.cieY * sdv.spec.cx;
349 >                                ysum += sdv.cieY * sdv.spec.cy;
350 >                        }
351                      }
352 <                    printf("\t%.3e\n", sum/npsamps);
352 >                    fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
353 >                    if (rbf_colorimetry == RBCtristimulus) {
354 >                        fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
355 >                        fprintf(cfp[CIE_Z], "\t%.3e\n",
356 >                                (sum - xsum - ysum)*sum/(npsamps*ysum));
357 >                    }
358                  }
359 <                putchar('\n');                  /* extra space between rows */
359 >                if (rbf_colorimetry == RBCtristimulus) {
360 >                        fputc('\n', cfp[CIE_X]);
361 >                        fputc('\n', cfp[CIE_Z]);
362 >                }
363              }
364 <            data_epilogue();
364 >            if (fclose(cfp[CIE_Y])) {
365 >                fprintf(stderr, "%s: error writing Y output\n", progname);
366 >                exit(1);
367 >            }
368 >            if (rbf_colorimetry == RBCtristimulus &&
369 >                        (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
370 >                fprintf(stderr, "%s: error writing X/Z output\n", progname);
371 >                exit(1);
372 >            }
373          }
374          SDfreeBSDF(&bsd);                       /* all done */
375          return;
# Line 305 | Line 384 | eval_function(char *funame)
384   {
385          ANGLE_BASIS     *abp = get_basis(kbasis);
386          int             assignD = (fundefined(funame) < 6);
387 +        FILE            *ofp = open_component_file(CIE_Y);
388          double          iovec[6];
389          double          sum;
390          int             i, j, n;
391  
392          initurand(npsamps);
313        data_prologue();                        /* begin output */
393          for (j = 0; j < abp->nangles; j++) {    /* run through directions */
394              for (i = 0; i < abp->nangles; i++) {
395                  sum = 0;
# Line 333 | Line 412 | eval_function(char *funame)
412                      }
413                      sum += funvalue(funame, 6, iovec);
414                  }
415 <                printf("\t%.3e\n", sum/npsamps);
415 >                fprintf(ofp, "\t%.3e\n", sum/npsamps);
416              }
417 <            putchar('\n');
417 >            fputc('\n', ofp);
418              prog_show((j+1.)/abp->nangles);
419          }
341        data_epilogue();                        /* finish output */
420          prog_done();
421 +        if (fclose(ofp)) {
422 +                fprintf(stderr, "%s: error writing Y output\n", progname);
423 +                exit(1);
424 +        }
425   }
426  
427   /* Interpolate and output a radial basis function BSDF representation */
428   static void
429   eval_rbf(void)
430   {
431 <        ANGLE_BASIS     *abp = get_basis(kbasis);
432 <        float           bsdfarr[MAXPATCHES*MAXPATCHES];
433 <        FVECT           vin, vout;
434 <        RBFNODE         *rbf;
435 <        double          sum;
436 <        int             i, j, n;
437 <                                                /* sanity check */
438 <        if (abp->nangles > MAXPATCHES) {
439 <                fprintf(stderr, "%s: too many patches!\n", progname);
440 <                exit(1);
441 <        }
442 <        data_prologue();                        /* begin output */
443 <        for (i = 0; i < abp->nangles; i++) {
444 <            if (input_orient > 0)               /* use incident patch center */
445 <                fi_getvec(vin, i+.5*(i>0), abp);
446 <            else
447 <                bi_getvec(vin, i+.5*(i>0), abp);
431 >    ANGLE_BASIS *abp = get_basis(kbasis);
432 >    float       (*XZarr)[2] = NULL;
433 >    float       bsdfarr[MAXPATCHES*MAXPATCHES];
434 >    FILE        *cfp[3];
435 >    FVECT       vin, vout;
436 >    double      sum, xsum, ysum, normf;
437 >    int         i, j, ni, no, nisamps, nosamps;
438 >                                        /* sanity check */
439 >    if (abp->nangles > MAXPATCHES) {
440 >        fprintf(stderr, "%s: too many patches!\n", progname);
441 >        exit(1);
442 >    }
443 >    memset(bsdfarr, 0, sizeof(bsdfarr));
444 >    if (rbf_colorimetry == RBCtristimulus)
445 >        XZarr = (float (*)[2])calloc(abp->nangles*abp->nangles, 2*sizeof(float));
446 >    nosamps = (int)(pow((double)npsamps, 0.67) + .5);
447 >    nisamps = (npsamps + (nosamps>>1)) / nosamps;
448 >    normf = 1./(double)(nisamps*nosamps);
449 >    for (i = 0; i < abp->nangles; i++) {
450 >        for (ni = nisamps; ni--; ) {            /* sample over incident patch */
451 >            RBFNODE     *rbf;
452 >            if (input_orient > 0)               /* vary incident patch loc. */
453 >                fi_getvec(vin, i+urand(ni), abp);
454 >            else
455 >                bi_getvec(vin, i+urand(ni), abp);
456  
457 <            rbf = advect_rbf(vin, lobe_lim);    /* compute radial basis func */
457 >            rbf = advect_rbf(vin, lobe_lim);    /* compute radial basis func */
458  
459 <            for (j = 0; j < abp->nangles; j++) {
460 <                sum = 0;                        /* sample over exiting patch */
461 <                for (n = npsamps; n--; ) {
459 >            for (j = 0; j < abp->nangles; j++) {
460 >                sum = 0;                        /* sample over exiting patch */
461 >                xsum = ysum = 0;
462 >                for (no = nosamps; no--; ) {
463 >                    SDValue     sdv;
464                      if (output_orient > 0)
465 <                        fo_getvec(vout, j+(n+frandom())/npsamps, abp);
465 >                        fo_getvec(vout, j+(no+frandom())/nosamps, abp);
466                      else
467 <                        bo_getvec(vout, j+(n+frandom())/npsamps, abp);
467 >                        bo_getvec(vout, j+(no+frandom())/nosamps, abp);
468  
469 <                    sum += eval_rbfrep(rbf, vout);
469 >                    eval_rbfcol(&sdv, rbf, vout);
470 >                    sum += sdv.cieY;
471 >                    if (rbf_colorimetry == RBCtristimulus) {
472 >                        xsum += sdv.cieY * sdv.spec.cx;
473 >                        ysum += sdv.cieY * sdv.spec.cy;
474 >                    }
475                  }
476 <                bsdfarr[j*abp->nangles + i] = sum / (double)npsamps;
476 >                no = j*abp->nangles + i;
477 >                bsdfarr[no] += sum * normf;
478 >                if (rbf_colorimetry == RBCtristimulus) {
479 >                    XZarr[no][0] += xsum*sum*normf/ysum;
480 >                    XZarr[no][1] += (sum - xsum - ysum)*sum*normf/ysum;
481 >                }
482              }
483 <            if (rbf != NULL)
483 >            if (rbf != NULL)
484                  free(rbf);
383            prog_show((i+1.)/abp->nangles);
485          }
486 <        n = 0;                                  /* write out our matrix */
487 <        for (j = 0; j < abp->nangles; j++) {
488 <            for (i = 0; i < abp->nangles; i++)
489 <                printf("\t%.3e\n", bsdfarr[n++]);
490 <            putchar('\n');
486 >        prog_show((i+1.)/abp->nangles);
487 >    }
488 >                                        /* write out our matrix */
489 >    cfp[CIE_Y] = open_component_file(CIE_Y);
490 >    no = 0;
491 >    for (j = 0; j < abp->nangles; j++) {
492 >        for (i = 0; i < abp->nangles; i++, no++)
493 >        fprintf(cfp[CIE_Y], "\t%.3e\n", bsdfarr[no]);
494 >        fputc('\n', cfp[CIE_Y]);
495 >    }
496 >    prog_done();
497 >    if (fclose(cfp[CIE_Y])) {
498 >        fprintf(stderr, "%s: error writing Y output\n", progname);
499 >        exit(1);
500 >    }
501 >    if (XZarr == NULL)                  /* no color? */
502 >        return;
503 >    cfp[CIE_X] = open_component_file(CIE_X);
504 >    cfp[CIE_Z] = open_component_file(CIE_Z);
505 >    no = 0;
506 >    for (j = 0; j < abp->nangles; j++) {
507 >        for (i = 0; i < abp->nangles; i++, no++) {
508 >        fprintf(cfp[CIE_X], "\t%.3e\n", XZarr[no][0]);
509 >        fprintf(cfp[CIE_Z], "\t%.3e\n", XZarr[no][1]);
510 >        }
511 >        fputc('\n', cfp[CIE_X]);
512 >        fputc('\n', cfp[CIE_Z]);
513 >    }
514 >    free(XZarr);
515 >    if (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z])) {
516 >        fprintf(stderr, "%s: error writing X/Z output\n", progname);
517 >        exit(1);
518 >    }
519 > }
520 >
521 > #if defined(_WIN32) || defined(_WIN64)
522 > /* Execute wrapBSDF command (may never return) */
523 > static int
524 > wrap_up(void)
525 > {
526 >        char    cmd[32700];
527 >
528 >        if (bsdf_manuf[0]) {
529 >                add_wbsdf("-f", 1);
530 >                strcpy(cmd, "m=");
531 >                strcpy(cmd+2, bsdf_manuf);
532 >                add_wbsdf(cmd, 0);
533          }
534 <        data_epilogue();                        /* finish output */
535 <        prog_done();
534 >        if (bsdf_name[0]) {
535 >                add_wbsdf("-f", 1);
536 >                strcpy(cmd, "n=");
537 >                strcpy(cmd+2, bsdf_name);
538 >                add_wbsdf(cmd, 0);
539 >        }
540 >        if (!convert_commandline(cmd, sizeof(cmd), wrapBSDF)) {
541 >                fputs(progname, stderr);
542 >                fputs(": command line too long in wrap_up()\n", stderr);
543 >                return(1);
544 >        }
545 >        return(system(cmd));
546   }
547 + #else
548 + /* Execute wrapBSDF command (may never return) */
549 + static int
550 + wrap_up(void)
551 + {
552 +        char    buf[256];
553 +        char    *compath = getpath((char *)wrapBSDF[0], getenv("PATH"), X_OK);
554  
555 +        if (compath == NULL) {
556 +                fprintf(stderr, "%s: cannot locate %s\n", progname, wrapBSDF[0]);
557 +                return(1);
558 +        }
559 +        if (bsdf_manuf[0]) {
560 +                add_wbsdf("-f", 1);
561 +                strcpy(buf, "m=");
562 +                strcpy(buf+2, bsdf_manuf);
563 +                add_wbsdf(buf, 0);
564 +        }
565 +        if (bsdf_name[0]) {
566 +                add_wbsdf("-f", 1);
567 +                strcpy(buf, "n=");
568 +                strcpy(buf+2, bsdf_name);
569 +                add_wbsdf(buf, 0);
570 +        }
571 +        execv(compath, wrapBSDF);       /* successful call never returns */
572 +        perror(compath);
573 +        return(1);
574 + }
575 + #endif
576 +
577 + #define HEAD_BUFLEN     10240
578 + static char     head_buf[HEAD_BUFLEN];
579 + static int      cur_headlen = 0;
580 +
581 + /* Record header line as comment associated with this SIR input */
582 + static int
583 + record2header(char *s)
584 + {
585 +        int     len = strlen(s);
586 +
587 +        if (cur_headlen+len >= HEAD_BUFLEN-6)
588 +                return(0);
589 +                                        /* includes EOL */
590 +        strcpy(head_buf+cur_headlen, s);
591 +        cur_headlen += len;
592 +
593 + #if defined(_WIN32) || defined(_WIN64)
594 +        if (head_buf[cur_headlen-1] == '\n')
595 +                head_buf[cur_headlen-1] = '\t';
596 + #endif
597 +        return(1);
598 + }
599 +
600 + /* Finish off header for this file */
601 + static void
602 + done_header(void)
603 + {
604 +        while (cur_headlen > 0 && isspace(head_buf[cur_headlen-1]))
605 +                --cur_headlen;
606 +        head_buf[cur_headlen] = '\0';
607 +        if (!cur_headlen)
608 +                return;
609 +        add_wbsdf("-C", 1);
610 +        add_wbsdf(head_buf, 0);
611 +        head_buf[cur_headlen=0] = '\0';
612 + }
613 +
614   /* Read in BSDF and interpolate as Klems matrix representation */
615   int
616   main(int argc, char *argv[])
617   {
618          int     dofwd = 0, dobwd = 1;
619 +        char    buf[1024];
620          char    *cp;
621          int     i, na;
622 <
623 <        progname = argv[0];
622 >                                                /* set global progname */
623 >        fixargv0(argv[0]);
624          esupport |= E_VARIABLE|E_FUNCTION|E_RCONST;
625          esupport &= ~(E_INCHAN|E_OUTCHAN);
626          scompile("PI:3.14159265358979323846", NULL, 0);
# Line 417 | Line 637 | main(int argc, char *argv[])
637                          single_plane_incident = 0;
638                          break;
639                  case 'f':
640 <                        if (!argv[i][2]) {
641 <                                fcompile(argv[++i]);
642 <                                single_plane_incident = 0;
640 >                        if ((argv[i][0] == '-') & !argv[i][2]) {
641 >                                if (strchr(argv[++i], '=') != NULL) {
642 >                                        add_wbsdf("-f", 1);
643 >                                        add_wbsdf(argv[i], 1);
644 >                                } else {
645 >                                        char    *fpath = getpath(argv[i],
646 >                                                            getrlibpath(), 0);
647 >                                        if (fpath == NULL) {
648 >                                                fprintf(stderr,
649 >                                                "%s: cannot find file '%s'\n",
650 >                                                        argv[0], argv[i]);
651 >                                                return(1);
652 >                                        }
653 >                                        fcompile(fpath);
654 >                                        single_plane_incident = 0;
655 >                                }
656                          } else
657                                  dofwd = (argv[i][0] == '+');
658                          break;
# Line 427 | Line 660 | main(int argc, char *argv[])
660                          dobwd = (argv[i][0] == '+');
661                          break;
662                  case 'h':
663 <                        kbasis = "LBNL/Klems Half";
663 >                        kbasis = klems_half;
664 >                        add_wbsdf("-a", 1);
665 >                        add_wbsdf("kh", 1);
666                          break;
667                  case 'q':
668 <                        kbasis = "LBNL/Klems Quarter";
668 >                        kbasis = klems_quarter;
669 >                        add_wbsdf("-a", 1);
670 >                        add_wbsdf("kq", 1);
671                          break;
672                  case 'l':
673                          lobe_lim = atoi(argv[++i]);
# Line 438 | Line 675 | main(int argc, char *argv[])
675                  case 'p':
676                          do_prog = atoi(argv[i]+2);
677                          break;
678 +                case 'C':
679 +                        add_wbsdf(argv[i], 1);
680 +                        add_wbsdf(argv[++i], 1);
681 +                        break;
682                  default:
683                          goto userr;
684                  }
685 +        if (kbasis == klems_full) {             /* default (full) basis? */
686 +                add_wbsdf("-a", 1);
687 +                add_wbsdf("kf", 1);
688 +        }
689 +        strcpy(buf, "File produced by: ");
690 +        if (convert_commandline(buf+18, sizeof(buf)-18, argv) != NULL) {
691 +                add_wbsdf("-C", 1); add_wbsdf(buf, 0);
692 +        }
693          if (single_plane_incident >= 0) {       /* function-based BSDF? */
694 <                if (i != argc-1 || fundefined(argv[i]) != 6) {
694 >                if (i != argc-1 || fundefined(argv[i]) < 3) {
695                          fprintf(stderr,
696          "%s: need single function with 6 arguments: bsdf(ix,iy,iz,ox,oy,oz)\n",
697                                          progname);
698                          fprintf(stderr, "\tor 3 arguments using Dx,Dy,Dz: bsdf(ix,iy,iz)\n");
699                          goto userr;
700                  }
701 +                doptimize(1);                   /* optimize definitions */
702                  ++eclock;
453                xml_header(argc, argv);                 /* start XML output */
454                xml_prologue(NULL);
703                  if (dofwd) {
704                          input_orient = -1;
705                          output_orient = -1;
# Line 470 | Line 718 | main(int argc, char *argv[])
718                          prog_start("Evaluating inside->outside transmission");
719                          eval_function(argv[i]);
720                  }
721 <                xml_epilogue();                 /* finish XML output & exit */
474 <                return(0);
721 >                return(wrap_up());
722          }
723                                                  /* XML input? */
724          if (i == argc-1 && (cp = argv[i]+strlen(argv[i])-4) > argv[i] &&
725                                  !strcasecmp(cp, ".xml")) {
479                xml_header(argc, argv);         /* start XML output */
726                  eval_bsdf(argv[i]);             /* load & resample BSDF */
727 <                xml_epilogue();                 /* finish XML output & exit */
482 <                return(0);
727 >                return(wrap_up());
728          }
729          if (i < argc) {                         /* open input files if given */
730                  int     nbsdf = 0;
731                  for ( ; i < argc; i++) {        /* interpolate each component */
487                        char    pbuf[256];
732                          FILE    *fpin = fopen(argv[i], "rb");
733                          if (fpin == NULL) {
734                                  fprintf(stderr, "%s: cannot open BSDF interpolant '%s'\n",
735                                                  progname, argv[i]);
736                                  return(1);
737                          }
738 +                        sprintf(buf, "%s:\n", argv[i]);
739 +                        record2header(buf);
740 +                        sir_headshare = &record2header;
741                          if (!load_bsdf_rep(fpin))
742                                  return(1);
743                          fclose(fpin);
744 <                        if (!nbsdf++) {         /* start XML on first dist. */
745 <                                xml_header(argc, argv);
746 <                                xml_prologue(NULL);
500 <                        }
501 <                        sprintf(pbuf, "Interpolating component '%s'", argv[i]);
502 <                        prog_start(pbuf);
744 >                        done_header();
745 >                        sprintf(buf, "Interpolating component '%s'", argv[i]);
746 >                        prog_start(buf);
747                          eval_rbf();
748                  }
749 <                xml_epilogue();                 /* finish XML output & exit */
506 <                return(0);
749 >                return(wrap_up());
750          }
751          SET_FILE_BINARY(stdin);                 /* load from stdin */
752 +        record2header("<stdin>:\n");
753 +        sir_headshare = &record2header;
754          if (!load_bsdf_rep(stdin))
755                  return(1);
756 <        xml_header(argc, argv);                 /* start XML output */
512 <        xml_prologue(NULL);
756 >        done_header();
757          prog_start("Interpolating from standard input");
758          eval_rbf();                             /* resample dist. */
759 <        xml_epilogue();                         /* finish XML output & exit */
516 <        return(0);
759 >        return(wrap_up());
760   userr:
761          fprintf(stderr,
762          "Usage: %s [-n spp][-h|-q][-l maxlobes] [bsdf.sir ..] > bsdf.xml\n", progname);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines