ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2klems.c
Revision: 2.33
Committed: Sat Mar 27 17:50:18 2021 UTC (3 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.32: +2 -2 lines
Log Message:
fix: Allow different front/back diffuse reflectance in BSDF library

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.33 static const char RCSid[] = "$Id: bsdf2klems.c,v 2.32 2020/11/13 19:21:11 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 greg 2.33 if (bsd.tf != NULL || bsd.tLambFront.cieY > .002) {
281 greg 2.1 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 greg 2.31 char cmd[32700];
529 greg 2.20
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.32 #define HEAD_BUFLEN 10240
580 greg 2.29 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 greg 2.30 #if defined(_WIN32) || defined(_WIN64)
596     if (head_buf[cur_headlen-1] == '\n')
597     head_buf[cur_headlen-1] = '\t';
598     #endif
599 greg 2.29 return(1);
600     }
601    
602     /* Finish off header for this file */
603     static void
604     done_header(void)
605     {
606     while (cur_headlen > 0 && isspace(head_buf[cur_headlen-1]))
607     --cur_headlen;
608     head_buf[cur_headlen] = '\0';
609     if (!cur_headlen)
610     return;
611     add_wbsdf("-C", 1);
612     add_wbsdf(head_buf, 0);
613     head_buf[cur_headlen=0] = '\0';
614     }
615    
616 greg 2.1 /* Read in BSDF and interpolate as Klems matrix representation */
617     int
618     main(int argc, char *argv[])
619     {
620     int dofwd = 0, dobwd = 1;
621 greg 2.32 char buf[1024];
622 greg 2.1 char *cp;
623     int i, na;
624    
625     progname = argv[0];
626     esupport |= E_VARIABLE|E_FUNCTION|E_RCONST;
627     esupport &= ~(E_INCHAN|E_OUTCHAN);
628     scompile("PI:3.14159265358979323846", NULL, 0);
629     biggerlib();
630 greg 2.2 for (i = 1; i < argc && (argv[i][0] == '-') | (argv[i][0] == '+'); i++)
631 greg 2.1 switch (argv[i][1]) { /* get options */
632     case 'n':
633     npsamps = atoi(argv[++i]);
634     if (npsamps <= 0)
635     goto userr;
636     break;
637     case 'e':
638     scompile(argv[++i], NULL, 0);
639     single_plane_incident = 0;
640     break;
641     case 'f':
642     if (!argv[i][2]) {
643 greg 2.20 if (strchr(argv[++i], '=') != NULL) {
644     add_wbsdf("-f", 1);
645     add_wbsdf(argv[i], 1);
646     } else {
647 greg 2.25 char *fpath = getpath(argv[i],
648     getrlibpath(), 0);
649     if (fpath == NULL) {
650     fprintf(stderr,
651     "%s: cannot find file '%s'\n",
652     argv[0], argv[i]);
653     return(1);
654     }
655     fcompile(fpath);
656 greg 2.20 single_plane_incident = 0;
657     }
658 greg 2.1 } else
659     dofwd = (argv[i][0] == '+');
660     break;
661     case 'b':
662     dobwd = (argv[i][0] == '+');
663     break;
664     case 'h':
665 greg 2.20 kbasis = klems_half;
666     add_wbsdf("-a", 1);
667     add_wbsdf("kh", 1);
668 greg 2.1 break;
669     case 'q':
670 greg 2.20 kbasis = klems_quarter;
671     add_wbsdf("-a", 1);
672     add_wbsdf("kq", 1);
673 greg 2.1 break;
674 greg 2.10 case 'l':
675     lobe_lim = atoi(argv[++i]);
676     break;
677 greg 2.13 case 'p':
678     do_prog = atoi(argv[i]+2);
679     break;
680 greg 2.20 case 'C':
681     add_wbsdf(argv[i], 1);
682     add_wbsdf(argv[++i], 1);
683     break;
684 greg 2.1 default:
685     goto userr;
686     }
687 greg 2.20 if (kbasis == klems_full) { /* default (full) basis? */
688     add_wbsdf("-a", 1);
689     add_wbsdf("kf", 1);
690     }
691     strcpy(buf, "File produced by: ");
692     if (convert_commandline(buf+18, sizeof(buf)-18, argv) != NULL) {
693     add_wbsdf("-C", 1); add_wbsdf(buf, 0);
694     }
695 greg 2.1 if (single_plane_incident >= 0) { /* function-based BSDF? */
696 greg 2.19 if (i != argc-1 || fundefined(argv[i]) < 3) {
697 greg 2.1 fprintf(stderr,
698     "%s: need single function with 6 arguments: bsdf(ix,iy,iz,ox,oy,oz)\n",
699     progname);
700 greg 2.13 fprintf(stderr, "\tor 3 arguments using Dx,Dy,Dz: bsdf(ix,iy,iz)\n");
701 greg 2.1 goto userr;
702     }
703 greg 2.8 ++eclock;
704 greg 2.1 if (dofwd) {
705     input_orient = -1;
706     output_orient = -1;
707 greg 2.13 prog_start("Evaluating outside reflectance");
708     eval_function(argv[i]);
709 greg 2.1 output_orient = 1;
710 greg 2.13 prog_start("Evaluating outside->inside transmission");
711     eval_function(argv[i]);
712 greg 2.1 }
713     if (dobwd) {
714     input_orient = 1;
715     output_orient = 1;
716 greg 2.13 prog_start("Evaluating inside reflectance");
717     eval_function(argv[i]);
718 greg 2.1 output_orient = -1;
719 greg 2.13 prog_start("Evaluating inside->outside transmission");
720     eval_function(argv[i]);
721 greg 2.1 }
722 greg 2.20 return(wrap_up());
723 greg 2.1 }
724 greg 2.2 /* XML input? */
725     if (i == argc-1 && (cp = argv[i]+strlen(argv[i])-4) > argv[i] &&
726     !strcasecmp(cp, ".xml")) {
727 greg 2.1 eval_bsdf(argv[i]); /* load & resample BSDF */
728 greg 2.20 return(wrap_up());
729 greg 2.1 }
730     if (i < argc) { /* open input files if given */
731     int nbsdf = 0;
732     for ( ; i < argc; i++) { /* interpolate each component */
733     FILE *fpin = fopen(argv[i], "rb");
734     if (fpin == NULL) {
735     fprintf(stderr, "%s: cannot open BSDF interpolant '%s'\n",
736     progname, argv[i]);
737     return(1);
738     }
739 greg 2.32 sprintf(buf, "%s:\n", argv[i]);
740     record2header(buf);
741 greg 2.29 sir_headshare = &record2header;
742 greg 2.1 if (!load_bsdf_rep(fpin))
743     return(1);
744     fclose(fpin);
745 greg 2.29 done_header();
746 greg 2.32 sprintf(buf, "Interpolating component '%s'", argv[i]);
747     prog_start(buf);
748 greg 2.1 eval_rbf();
749     }
750 greg 2.20 return(wrap_up());
751 greg 2.1 }
752     SET_FILE_BINARY(stdin); /* load from stdin */
753 greg 2.32 record2header("<stdin>:\n");
754     sir_headshare = &record2header;
755 greg 2.1 if (!load_bsdf_rep(stdin))
756     return(1);
757 greg 2.32 done_header();
758 greg 2.13 prog_start("Interpolating from standard input");
759 greg 2.1 eval_rbf(); /* resample dist. */
760 greg 2.20 return(wrap_up());
761 greg 2.1 userr:
762     fprintf(stderr,
763 greg 2.10 "Usage: %s [-n spp][-h|-q][-l maxlobes] [bsdf.sir ..] > bsdf.xml\n", progname);
764 greg 2.1 fprintf(stderr,
765 greg 2.3 " or: %s [-n spp][-h|-q] bsdf_in.xml > bsdf_out.xml\n", progname);
766 greg 2.1 fprintf(stderr,
767     " or: %s [-n spp][-h|-q][{+|-}for[ward]][{+|-}b[ackward]][-e expr][-f file] bsdf_func > bsdf.xml\n",
768     progname);
769     return(1);
770     }