ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2klems.c
Revision: 2.28
Committed: Sat Dec 28 18:05:14 2019 UTC (4 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.27: +1 -3 lines
Log Message:
Removed redundant include files

File Contents

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