ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2klems.c
Revision: 2.29
Committed: Mon Oct 26 21:12:20 2020 UTC (3 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.28: +39 -1 lines
Log Message:
feat(bsdf2klems, bsdf2ttree): added XML header comments copying useful information from SIR inputs

File Contents

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