ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2klems.c
Revision: 2.21
Committed: Thu Feb 4 00:45:47 2016 UTC (8 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.20: +25 -24 lines
Log Message:
Minor cleanup and fixes

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.21 static const char RCSid[] = "$Id: bsdf2klems.c,v 2.20 2016/02/03 01:57:06 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Load measured BSDF interpolant and write out as XML file with Klems matrix.
6     *
7     * G. Ward
8     */
9    
10     #define _USE_MATH_DEFINES
11     #include <stdio.h>
12     #include <stdlib.h>
13     #include <string.h>
14     #include <math.h>
15     #include "random.h"
16     #include "platform.h"
17 greg 2.20 #include "paths.h"
18     #include "rtio.h"
19 greg 2.1 #include "calcomp.h"
20     #include "bsdfrep.h"
21     #include "bsdf_m.h"
22 greg 2.20 /* tristimulus components */
23     enum {CIE_X, CIE_Y, CIE_Z};
24 greg 2.4 /* assumed maximum # Klems patches */
25     #define MAXPATCHES 145
26 greg 2.1 /* global argv[0] */
27     char *progname;
28     /* selected basis function name */
29 greg 2.20 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 greg 2.1 /* number of BSDF samples per patch */
34     static int npsamps = 256;
35 greg 2.10 /* limit on number of RBF lobes */
36     static int lobe_lim = 15000;
37 greg 2.13 /* progress bar length */
38     static int do_prog = 79;
39    
40 greg 2.20 #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 greg 2.13
63     /* Start new progress bar */
64     #define prog_start(s) if (do_prog) fprintf(stderr, "%s: %s...\n", progname, s); else
65    
66     /* Draw progress bar of the appropriate length */
67     static void
68     prog_show(double frac)
69     {
70 greg 2.17 static unsigned call_cnt = 0;
71     static char lastc[] = "-\\|/";
72     char pbar[256];
73     int nchars;
74 greg 2.13
75 greg 2.14 if (do_prog <= 1) return;
76 greg 2.13 if (do_prog > sizeof(pbar)-2)
77     do_prog = sizeof(pbar)-2;
78     if (frac < 0) frac = 0;
79 greg 2.17 else if (frac >= 1) frac = .9999;
80     nchars = do_prog*frac;
81 greg 2.13 pbar[0] = '\r';
82     memset(pbar+1, '*', nchars);
83 greg 2.17 pbar[nchars+1] = lastc[call_cnt++ & 3];
84     memset(pbar+2+nchars, '-', do_prog-nchars-1);
85 greg 2.13 pbar[do_prog+1] = '\0';
86     fputs(pbar, stderr);
87     }
88    
89     /* Finish progress bar */
90 greg 2.14 static void
91     prog_done(void)
92     {
93     int n = do_prog;
94    
95     if (n <= 1) return;
96     fputc('\r', stderr);
97     while (n--)
98     fputc(' ', stderr);
99     fputc('\r', stderr);
100     }
101 greg 2.1
102     /* Return angle basis corresponding to the given name */
103 greg 2.13 static ANGLE_BASIS *
104 greg 2.1 get_basis(const char *bn)
105     {
106     int n = nabases;
107    
108     while (n-- > 0)
109     if (!strcasecmp(bn, abase_list[n].name))
110     return &abase_list[n];
111     return NULL;
112     }
113    
114 greg 2.20 /* Copy geometry string to file for wrapBSDF */
115     static char *
116     save_geom(const char *mgf)
117     {
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     /* Open XYZ component file for output and add appropriate arguments */
131     static FILE *
132     open_component_file(int c)
133     {
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 (fp == NULL) {
140     fprintf(stderr, "%s: cannot open '%s' for writing\n",
141     progname, tfname);
142 greg 2.1 exit(1);
143     }
144 greg 2.20 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 greg 2.1 }
149    
150 greg 2.2 /* Load and resample XML BSDF description using Klems basis */
151 greg 2.1 static void
152     eval_bsdf(const char *fname)
153     {
154     ANGLE_BASIS *abp = get_basis(kbasis);
155 greg 2.20 FILE *cfp[3];
156 greg 2.1 SDData bsd;
157     SDError ec;
158     FVECT vin, vout;
159 greg 2.20 SDValue sdv;
160     double sum, xsum, ysum;
161 greg 2.1 int i, j, n;
162    
163 greg 2.18 initurand(npsamps);
164 greg 2.1 SDclearBSDF(&bsd, fname); /* load BSDF file */
165     if ((ec = SDloadFile(&bsd, fname)) != SDEnone)
166     goto err;
167 greg 2.20 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 greg 2.1 /* front reflection */
184     if (bsd.rf != NULL || bsd.rLambFront.cieY > .002) {
185     input_orient = 1; output_orient = 1;
186 greg 2.20 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 greg 2.1 for (j = 0; j < abp->nangles; j++) {
194     for (i = 0; i < abp->nangles; i++) {
195     sum = 0; /* average over patches */
196 greg 2.20 xsum = ysum = 0;
197 greg 2.1 for (n = npsamps; n-- > 0; ) {
198     fo_getvec(vout, j+(n+frandom())/npsamps, abp);
199 greg 2.5 fi_getvec(vin, i+urand(n), abp);
200 greg 2.20 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
201 greg 2.1 if (ec != SDEnone)
202     goto err;
203 greg 2.20 sum += sdv.cieY;
204     if (rbf_colorimetry == RBCtristimulus) {
205     c_ccvt(&sdv.spec, C_CSXY);
206 greg 2.21 xsum += sdv.cieY * sdv.spec.cx;
207     ysum += sdv.cieY * sdv.spec.cy;
208 greg 2.20 }
209     }
210     fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
211     if (rbf_colorimetry == RBCtristimulus) {
212 greg 2.21 fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
213     fprintf(cfp[CIE_Z], "\t%.3e\n",
214 greg 2.20 (sum - xsum - ysum)*sum/(npsamps*ysum));
215 greg 2.1 }
216     }
217 greg 2.20 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     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 greg 2.1 }
232     }
233     /* back reflection */
234     if (bsd.rb != NULL || bsd.rLambBack.cieY > .002) {
235     input_orient = -1; output_orient = -1;
236 greg 2.20 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 greg 2.1 for (j = 0; j < abp->nangles; j++) {
244     for (i = 0; i < abp->nangles; i++) {
245     sum = 0; /* average over patches */
246 greg 2.20 xsum = ysum = 0;
247 greg 2.1 for (n = npsamps; n-- > 0; ) {
248     bo_getvec(vout, j+(n+frandom())/npsamps, abp);
249 greg 2.5 bi_getvec(vin, i+urand(n), abp);
250 greg 2.20 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
251 greg 2.1 if (ec != SDEnone)
252     goto err;
253 greg 2.20 sum += sdv.cieY;
254     if (rbf_colorimetry == RBCtristimulus) {
255     c_ccvt(&sdv.spec, C_CSXY);
256 greg 2.21 xsum += sdv.cieY * sdv.spec.cx;
257     ysum += sdv.cieY * sdv.spec.cy;
258 greg 2.20 }
259     }
260     fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
261     if (rbf_colorimetry == RBCtristimulus) {
262 greg 2.21 fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
263     fprintf(cfp[CIE_Z], "\t%.3e\n",
264 greg 2.20 (sum - xsum - ysum)*sum/(npsamps*ysum));
265 greg 2.1 }
266     }
267 greg 2.20 if (rbf_colorimetry == RBCtristimulus) {
268     fputc('\n', cfp[CIE_X]);
269     fputc('\n', cfp[CIE_Z]);
270     }
271     }
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 greg 2.1 }
281     }
282     /* front transmission */
283     if (bsd.tf != NULL || bsd.tLamb.cieY > .002) {
284     input_orient = 1; output_orient = -1;
285 greg 2.20 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 greg 2.1 for (j = 0; j < abp->nangles; j++) {
293     for (i = 0; i < abp->nangles; i++) {
294     sum = 0; /* average over patches */
295 greg 2.20 xsum = ysum = 0;
296 greg 2.1 for (n = npsamps; n-- > 0; ) {
297     bo_getvec(vout, j+(n+frandom())/npsamps, abp);
298 greg 2.5 fi_getvec(vin, i+urand(n), abp);
299 greg 2.20 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
300 greg 2.1 if (ec != SDEnone)
301     goto err;
302 greg 2.20 sum += sdv.cieY;
303     if (rbf_colorimetry == RBCtristimulus) {
304     c_ccvt(&sdv.spec, C_CSXY);
305 greg 2.21 xsum += sdv.cieY * sdv.spec.cx;
306     ysum += sdv.cieY * sdv.spec.cy;
307 greg 2.20 }
308 greg 2.1 }
309 greg 2.20 fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
310     if (rbf_colorimetry == RBCtristimulus) {
311 greg 2.21 fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
312     fprintf(cfp[CIE_Z], "\t%.3e\n",
313 greg 2.20 (sum - xsum - ysum)*sum/(npsamps*ysum));
314     }
315     }
316     if (rbf_colorimetry == RBCtristimulus) {
317     fputc('\n', cfp[CIE_X]);
318     fputc('\n', cfp[CIE_Z]);
319 greg 2.1 }
320     }
321 greg 2.20 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 greg 2.1 }
331     /* back transmission */
332 greg 2.9 if ((bsd.tb != NULL) | (bsd.tf != NULL)) {
333 greg 2.1 input_orient = -1; output_orient = 1;
334 greg 2.20 cfp[CIE_Y] = open_component_file(CIE_Y);
335 greg 2.21 if (bsd.tb != NULL)
336     rbf_colorimetry = bsd.tb->comp[0].cspec[2].flags
337     ? RBCtristimulus : RBCphotopic ;
338     if (rbf_colorimetry == RBCtristimulus) {
339 greg 2.20 cfp[CIE_X] = open_component_file(CIE_X);
340     cfp[CIE_Z] = open_component_file(CIE_Z);
341 greg 2.21 }
342 greg 2.1 for (j = 0; j < abp->nangles; j++) {
343 greg 2.9 for (i = 0; i < abp->nangles; i++) {
344     sum = 0; /* average over patches */
345 greg 2.20 xsum = ysum = 0;
346 greg 2.9 for (n = npsamps; n-- > 0; ) {
347     fo_getvec(vout, j+(n+frandom())/npsamps, abp);
348     bi_getvec(vin, i+urand(n), abp);
349 greg 2.20 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
350 greg 2.9 if (ec != SDEnone)
351 greg 2.1 goto err;
352 greg 2.20 sum += sdv.cieY;
353     if (rbf_colorimetry == RBCtristimulus) {
354     c_ccvt(&sdv.spec, C_CSXY);
355 greg 2.21 xsum += sdv.cieY * sdv.spec.cx;
356     ysum += sdv.cieY * sdv.spec.cy;
357 greg 2.20 }
358     }
359     fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
360     if (rbf_colorimetry == RBCtristimulus) {
361 greg 2.21 fprintf(cfp[CIE_X], "\t%.3e\n", xsum*sum/(npsamps*ysum));
362     fprintf(cfp[CIE_Z], "\t%.3e\n",
363 greg 2.20 (sum - xsum - ysum)*sum/(npsamps*ysum));
364 greg 2.1 }
365 greg 2.9 }
366 greg 2.20 if (rbf_colorimetry == RBCtristimulus) {
367     fputc('\n', cfp[CIE_X]);
368     fputc('\n', cfp[CIE_Z]);
369     }
370     }
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 greg 2.1 }
380     }
381     SDfreeBSDF(&bsd); /* all done */
382     return;
383     err:
384     SDreportError(ec, stderr);
385     exit(1);
386     }
387    
388 greg 2.2 /* Interpolate and output a BSDF function using Klems basis */
389 greg 2.1 static void
390     eval_function(char *funame)
391     {
392     ANGLE_BASIS *abp = get_basis(kbasis);
393 greg 2.8 int assignD = (fundefined(funame) < 6);
394 greg 2.20 FILE *ofp = open_component_file(CIE_Y);
395 greg 2.1 double iovec[6];
396     double sum;
397     int i, j, n;
398    
399 greg 2.4 initurand(npsamps);
400 greg 2.1 for (j = 0; j < abp->nangles; j++) { /* run through directions */
401     for (i = 0; i < abp->nangles; i++) {
402     sum = 0;
403     for (n = npsamps; n--; ) { /* average over patches */
404     if (output_orient > 0)
405     fo_getvec(iovec+3, j+(n+frandom())/npsamps, abp);
406     else
407     bo_getvec(iovec+3, j+(n+frandom())/npsamps, abp);
408    
409     if (input_orient > 0)
410 greg 2.4 fi_getvec(iovec, i+urand(n), abp);
411 greg 2.1 else
412 greg 2.4 bi_getvec(iovec, i+urand(n), abp);
413 greg 2.1
414 greg 2.8 if (assignD) {
415     varset("Dx", '=', -iovec[3]);
416     varset("Dy", '=', -iovec[4]);
417     varset("Dz", '=', -iovec[5]);
418     ++eclock;
419     }
420 greg 2.1 sum += funvalue(funame, 6, iovec);
421     }
422 greg 2.20 fprintf(ofp, "\t%.3e\n", sum/npsamps);
423 greg 2.1 }
424 greg 2.20 fputc('\n', ofp);
425 greg 2.13 prog_show((j+1.)/abp->nangles);
426 greg 2.1 }
427 greg 2.13 prog_done();
428 greg 2.20 if (fclose(ofp)) {
429     fprintf(stderr, "%s: error writing Y output\n", progname);
430     exit(1);
431     }
432 greg 2.1 }
433    
434     /* Interpolate and output a radial basis function BSDF representation */
435     static void
436     eval_rbf(void)
437     {
438     ANGLE_BASIS *abp = get_basis(kbasis);
439 greg 2.20 float (*XZarr)[2] = NULL;
440 greg 2.2 float bsdfarr[MAXPATCHES*MAXPATCHES];
441 greg 2.20 FILE *cfp[3];
442 greg 2.2 FVECT vin, vout;
443 greg 2.20 double sum, xsum, ysum;
444 greg 2.1 int i, j, n;
445 greg 2.2 /* sanity check */
446     if (abp->nangles > MAXPATCHES) {
447     fprintf(stderr, "%s: too many patches!\n", progname);
448     exit(1);
449     }
450 greg 2.20 if (rbf_colorimetry == RBCtristimulus)
451     XZarr = (float (*)[2])malloc(sizeof(float)*2*abp->nangles*abp->nangles);
452 greg 2.2 for (i = 0; i < abp->nangles; i++) {
453 greg 2.20 RBFNODE *rbf;
454 greg 2.2 if (input_orient > 0) /* use incident patch center */
455     fi_getvec(vin, i+.5*(i>0), abp);
456     else
457     bi_getvec(vin, i+.5*(i>0), abp);
458    
459 greg 2.10 rbf = advect_rbf(vin, lobe_lim); /* compute radial basis func */
460 greg 2.2
461     for (j = 0; j < abp->nangles; j++) {
462     sum = 0; /* sample over exiting patch */
463 greg 2.20 xsum = ysum = 0;
464 greg 2.2 for (n = npsamps; n--; ) {
465 greg 2.20 SDValue sdv;
466 greg 2.2 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 greg 2.1
471 greg 2.20 eval_rbfcol(&sdv, rbf, vout);
472     sum += sdv.cieY;
473     if (XZarr != NULL) {
474     c_ccvt(&sdv.spec, C_CSXY);
475 greg 2.21 xsum += sdv.cieY * sdv.spec.cx;
476     ysum += sdv.cieY * sdv.spec.cy;
477 greg 2.20 }
478     }
479     n = j*abp->nangles + i;
480 greg 2.21 bsdfarr[n] = sum / npsamps;
481 greg 2.20 if (XZarr != NULL) {
482     XZarr[n][0] = xsum*sum/(npsamps*ysum);
483     XZarr[n][1] = (sum - xsum - ysum)*sum/(npsamps*ysum);
484 greg 2.2 }
485     }
486 greg 2.6 if (rbf != NULL)
487     free(rbf);
488 greg 2.13 prog_show((i+1.)/abp->nangles);
489 greg 2.2 }
490 greg 2.20 /* write out our matrix */
491     cfp[CIE_Y] = open_component_file(CIE_Y);
492     n = 0;
493 greg 2.2 for (j = 0; j < abp->nangles; j++) {
494 greg 2.20 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 greg 2.2 }
498 greg 2.13 prog_done();
499 greg 2.20 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 greg 2.1 }
522    
523 greg 2.20 #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 greg 2.1 /* 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 greg 2.20 char buf[2048];
585 greg 2.1 char *cp;
586     int i, na;
587    
588     progname = argv[0];
589     esupport |= E_VARIABLE|E_FUNCTION|E_RCONST;
590     esupport &= ~(E_INCHAN|E_OUTCHAN);
591     scompile("PI:3.14159265358979323846", NULL, 0);
592     biggerlib();
593 greg 2.2 for (i = 1; i < argc && (argv[i][0] == '-') | (argv[i][0] == '+'); i++)
594 greg 2.1 switch (argv[i][1]) { /* get options */
595     case 'n':
596     npsamps = atoi(argv[++i]);
597     if (npsamps <= 0)
598     goto userr;
599     break;
600     case 'e':
601     scompile(argv[++i], NULL, 0);
602     single_plane_incident = 0;
603     break;
604     case 'f':
605     if (!argv[i][2]) {
606 greg 2.20 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 greg 2.1 } else
614     dofwd = (argv[i][0] == '+');
615     break;
616     case 'b':
617     dobwd = (argv[i][0] == '+');
618     break;
619     case 'h':
620 greg 2.20 kbasis = klems_half;
621     add_wbsdf("-a", 1);
622     add_wbsdf("kh", 1);
623 greg 2.1 break;
624     case 'q':
625 greg 2.20 kbasis = klems_quarter;
626     add_wbsdf("-a", 1);
627     add_wbsdf("kq", 1);
628 greg 2.1 break;
629 greg 2.10 case 'l':
630     lobe_lim = atoi(argv[++i]);
631     break;
632 greg 2.13 case 'p':
633     do_prog = atoi(argv[i]+2);
634     break;
635 greg 2.20 case 'C':
636     add_wbsdf(argv[i], 1);
637     add_wbsdf(argv[++i], 1);
638     break;
639 greg 2.1 default:
640     goto userr;
641     }
642 greg 2.20 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 greg 2.1 if (single_plane_incident >= 0) { /* function-based BSDF? */
651 greg 2.19 if (i != argc-1 || fundefined(argv[i]) < 3) {
652 greg 2.1 fprintf(stderr,
653     "%s: need single function with 6 arguments: bsdf(ix,iy,iz,ox,oy,oz)\n",
654     progname);
655 greg 2.13 fprintf(stderr, "\tor 3 arguments using Dx,Dy,Dz: bsdf(ix,iy,iz)\n");
656 greg 2.1 goto userr;
657     }
658 greg 2.8 ++eclock;
659 greg 2.1 if (dofwd) {
660     input_orient = -1;
661     output_orient = -1;
662 greg 2.13 prog_start("Evaluating outside reflectance");
663     eval_function(argv[i]);
664 greg 2.1 output_orient = 1;
665 greg 2.13 prog_start("Evaluating outside->inside transmission");
666     eval_function(argv[i]);
667 greg 2.1 }
668     if (dobwd) {
669     input_orient = 1;
670     output_orient = 1;
671 greg 2.13 prog_start("Evaluating inside reflectance");
672     eval_function(argv[i]);
673 greg 2.1 output_orient = -1;
674 greg 2.13 prog_start("Evaluating inside->outside transmission");
675     eval_function(argv[i]);
676 greg 2.1 }
677 greg 2.20 return(wrap_up());
678 greg 2.1 }
679 greg 2.2 /* XML input? */
680     if (i == argc-1 && (cp = argv[i]+strlen(argv[i])-4) > argv[i] &&
681     !strcasecmp(cp, ".xml")) {
682 greg 2.1 eval_bsdf(argv[i]); /* load & resample BSDF */
683 greg 2.20 return(wrap_up());
684 greg 2.1 }
685     if (i < argc) { /* open input files if given */
686     int nbsdf = 0;
687     for ( ; i < argc; i++) { /* interpolate each component */
688 greg 2.13 char pbuf[256];
689 greg 2.1 FILE *fpin = fopen(argv[i], "rb");
690     if (fpin == NULL) {
691     fprintf(stderr, "%s: cannot open BSDF interpolant '%s'\n",
692     progname, argv[i]);
693     return(1);
694     }
695     if (!load_bsdf_rep(fpin))
696     return(1);
697     fclose(fpin);
698 greg 2.13 sprintf(pbuf, "Interpolating component '%s'", argv[i]);
699     prog_start(pbuf);
700 greg 2.1 eval_rbf();
701     }
702 greg 2.20 return(wrap_up());
703 greg 2.1 }
704     SET_FILE_BINARY(stdin); /* load from stdin */
705     if (!load_bsdf_rep(stdin))
706     return(1);
707 greg 2.13 prog_start("Interpolating from standard input");
708 greg 2.1 eval_rbf(); /* resample dist. */
709 greg 2.20 return(wrap_up());
710 greg 2.1 userr:
711     fprintf(stderr,
712 greg 2.10 "Usage: %s [-n spp][-h|-q][-l maxlobes] [bsdf.sir ..] > bsdf.xml\n", progname);
713 greg 2.1 fprintf(stderr,
714 greg 2.3 " or: %s [-n spp][-h|-q] bsdf_in.xml > bsdf_out.xml\n", progname);
715 greg 2.1 fprintf(stderr,
716     " or: %s [-n spp][-h|-q][{+|-}for[ward]][{+|-}b[ackward]][-e expr][-f file] bsdf_func > bsdf.xml\n",
717     progname);
718     return(1);
719     }