ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2klems.c
Revision: 2.27
Committed: Mon Jun 17 23:58:32 2019 UTC (4 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.26: +71 -65 lines
Log Message:
Added incident patch sampling for more accurate result

File Contents

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