ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2klems.c
Revision: 2.20
Committed: Wed Feb 3 01:57:06 2016 UTC (8 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.19: +361 -173 lines
Log Message:
Added tristimulus color support for RBF and XML input

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: bsdf2klems.c,v 2.19 2016/01/24 14:28:51 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 = 256;
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 c_ccvt(&sdv.spec, C_CSXY);
206 xsum += sdv.cieY*sdv.spec.cx;
207 ysum += sdv.cieY*sdv.spec.cy;
208 }
209 }
210 fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
211 if (rbf_colorimetry == RBCtristimulus) {
212 fprintf(cfp[CIE_X], "\t%3e\n", xsum*sum/(npsamps*ysum));
213 fprintf(cfp[CIE_Z], "\t%3e\n",
214 (sum - xsum - ysum)*sum/(npsamps*ysum));
215 }
216 }
217 fputc('\n', cfp[CIE_Y]); /* extra space between rows */
218 if (rbf_colorimetry == RBCtristimulus) {
219 fputc('\n', cfp[CIE_X]);
220 fputc('\n', cfp[CIE_Z]);
221 }
222 }
223 if (fclose(cfp[CIE_Y])) {
224 fprintf(stderr, "%s: error writing Y output\n", progname);
225 exit(1);
226 }
227 if (rbf_colorimetry == RBCtristimulus &&
228 (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
229 fprintf(stderr, "%s: error writing X/Z output\n", progname);
230 exit(1);
231 }
232 }
233 /* back reflection */
234 if (bsd.rb != NULL || bsd.rLambBack.cieY > .002) {
235 input_orient = -1; output_orient = -1;
236 cfp[CIE_Y] = open_component_file(CIE_Y);
237 if (bsd.rb != NULL && bsd.rb->comp[0].cspec[2].flags) {
238 rbf_colorimetry = RBCtristimulus;
239 cfp[CIE_X] = open_component_file(CIE_X);
240 cfp[CIE_Z] = open_component_file(CIE_Z);
241 } else
242 rbf_colorimetry = RBCphotopic;
243 for (j = 0; j < abp->nangles; j++) {
244 for (i = 0; i < abp->nangles; i++) {
245 sum = 0; /* average over patches */
246 xsum = ysum = 0;
247 for (n = npsamps; n-- > 0; ) {
248 bo_getvec(vout, j+(n+frandom())/npsamps, abp);
249 bi_getvec(vin, i+urand(n), abp);
250 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
251 if (ec != SDEnone)
252 goto err;
253 sum += sdv.cieY;
254 if (rbf_colorimetry == RBCtristimulus) {
255 c_ccvt(&sdv.spec, C_CSXY);
256 xsum += sdv.cieY*sdv.spec.cx;
257 ysum += sdv.cieY*sdv.spec.cy;
258 }
259 }
260 fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
261 if (rbf_colorimetry == RBCtristimulus) {
262 fprintf(cfp[CIE_X], "\t%3e\n", xsum*sum/(npsamps*ysum));
263 fprintf(cfp[CIE_Z], "\t%3e\n",
264 (sum - xsum - ysum)*sum/(npsamps*ysum));
265 }
266 }
267 if (rbf_colorimetry == RBCtristimulus) {
268 fputc('\n', cfp[CIE_X]);
269 fputc('\n', cfp[CIE_Z]);
270 }
271 }
272 if (fclose(cfp[CIE_Y])) {
273 fprintf(stderr, "%s: error writing Y output\n", progname);
274 exit(1);
275 }
276 if (rbf_colorimetry == RBCtristimulus &&
277 (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
278 fprintf(stderr, "%s: error writing X/Z output\n", progname);
279 exit(1);
280 }
281 }
282 /* front transmission */
283 if (bsd.tf != NULL || bsd.tLamb.cieY > .002) {
284 input_orient = 1; output_orient = -1;
285 cfp[CIE_Y] = open_component_file(CIE_Y);
286 if (bsd.tf != NULL && bsd.tf->comp[0].cspec[2].flags) {
287 rbf_colorimetry = RBCtristimulus;
288 cfp[CIE_X] = open_component_file(CIE_X);
289 cfp[CIE_Z] = open_component_file(CIE_Z);
290 } else
291 rbf_colorimetry = RBCphotopic;
292 for (j = 0; j < abp->nangles; j++) {
293 for (i = 0; i < abp->nangles; i++) {
294 sum = 0; /* average over patches */
295 xsum = ysum = 0;
296 for (n = npsamps; n-- > 0; ) {
297 bo_getvec(vout, j+(n+frandom())/npsamps, abp);
298 fi_getvec(vin, i+urand(n), abp);
299 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
300 if (ec != SDEnone)
301 goto err;
302 sum += sdv.cieY;
303 if (rbf_colorimetry == RBCtristimulus) {
304 c_ccvt(&sdv.spec, C_CSXY);
305 xsum += sdv.cieY*sdv.spec.cx;
306 ysum += sdv.cieY*sdv.spec.cy;
307 }
308 }
309 fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
310 if (rbf_colorimetry == RBCtristimulus) {
311 fprintf(cfp[CIE_X], "\t%3e\n", xsum*sum/(npsamps*ysum));
312 fprintf(cfp[CIE_Z], "\t%3e\n",
313 (sum - xsum - ysum)*sum/(npsamps*ysum));
314 }
315 }
316 if (rbf_colorimetry == RBCtristimulus) {
317 fputc('\n', cfp[CIE_X]);
318 fputc('\n', cfp[CIE_Z]);
319 }
320 }
321 if (fclose(cfp[CIE_Y])) {
322 fprintf(stderr, "%s: error writing Y output\n", progname);
323 exit(1);
324 }
325 if (rbf_colorimetry == RBCtristimulus &&
326 (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
327 fprintf(stderr, "%s: error writing X/Z output\n", progname);
328 exit(1);
329 }
330 }
331 /* back transmission */
332 if ((bsd.tb != NULL) | (bsd.tf != NULL)) {
333 input_orient = -1; output_orient = 1;
334 cfp[CIE_Y] = open_component_file(CIE_Y);
335 if (bsd.tb != NULL && bsd.tb->comp[0].cspec[2].flags) {
336 rbf_colorimetry = RBCtristimulus;
337 cfp[CIE_X] = open_component_file(CIE_X);
338 cfp[CIE_Z] = open_component_file(CIE_Z);
339 } else
340 rbf_colorimetry = RBCphotopic;
341 for (j = 0; j < abp->nangles; j++) {
342 for (i = 0; i < abp->nangles; i++) {
343 sum = 0; /* average over patches */
344 xsum = ysum = 0;
345 for (n = npsamps; n-- > 0; ) {
346 fo_getvec(vout, j+(n+frandom())/npsamps, abp);
347 bi_getvec(vin, i+urand(n), abp);
348 ec = SDevalBSDF(&sdv, vout, vin, &bsd);
349 if (ec != SDEnone)
350 goto err;
351 sum += sdv.cieY;
352 if (rbf_colorimetry == RBCtristimulus) {
353 c_ccvt(&sdv.spec, C_CSXY);
354 xsum += sdv.cieY*sdv.spec.cx;
355 ysum += sdv.cieY*sdv.spec.cy;
356 }
357 }
358 fprintf(cfp[CIE_Y], "\t%.3e\n", sum/npsamps);
359 if (rbf_colorimetry == RBCtristimulus) {
360 fprintf(cfp[CIE_X], "\t%3e\n", xsum*sum/(npsamps*ysum));
361 fprintf(cfp[CIE_Z], "\t%3e\n",
362 (sum - xsum - ysum)*sum/(npsamps*ysum));
363 }
364 }
365 if (rbf_colorimetry == RBCtristimulus) {
366 fputc('\n', cfp[CIE_X]);
367 fputc('\n', cfp[CIE_Z]);
368 }
369 }
370 if (fclose(cfp[CIE_Y])) {
371 fprintf(stderr, "%s: error writing Y output\n", progname);
372 exit(1);
373 }
374 if (rbf_colorimetry == RBCtristimulus &&
375 (fclose(cfp[CIE_X]) || fclose(cfp[CIE_Z]))) {
376 fprintf(stderr, "%s: error writing X/Z output\n", progname);
377 exit(1);
378 }
379 }
380 SDfreeBSDF(&bsd); /* all done */
381 return;
382 err:
383 SDreportError(ec, stderr);
384 exit(1);
385 }
386
387 /* Interpolate and output a BSDF function using Klems basis */
388 static void
389 eval_function(char *funame)
390 {
391 ANGLE_BASIS *abp = get_basis(kbasis);
392 int assignD = (fundefined(funame) < 6);
393 FILE *ofp = open_component_file(CIE_Y);
394 double iovec[6];
395 double sum;
396 int i, j, n;
397
398 initurand(npsamps);
399 for (j = 0; j < abp->nangles; j++) { /* run through directions */
400 for (i = 0; i < abp->nangles; i++) {
401 sum = 0;
402 for (n = npsamps; n--; ) { /* average over patches */
403 if (output_orient > 0)
404 fo_getvec(iovec+3, j+(n+frandom())/npsamps, abp);
405 else
406 bo_getvec(iovec+3, j+(n+frandom())/npsamps, abp);
407
408 if (input_orient > 0)
409 fi_getvec(iovec, i+urand(n), abp);
410 else
411 bi_getvec(iovec, i+urand(n), abp);
412
413 if (assignD) {
414 varset("Dx", '=', -iovec[3]);
415 varset("Dy", '=', -iovec[4]);
416 varset("Dz", '=', -iovec[5]);
417 ++eclock;
418 }
419 sum += funvalue(funame, 6, iovec);
420 }
421 fprintf(ofp, "\t%.3e\n", sum/npsamps);
422 }
423 fputc('\n', ofp);
424 prog_show((j+1.)/abp->nangles);
425 }
426 prog_done();
427 if (fclose(ofp)) {
428 fprintf(stderr, "%s: error writing Y output\n", progname);
429 exit(1);
430 }
431 }
432
433 /* Interpolate and output a radial basis function BSDF representation */
434 static void
435 eval_rbf(void)
436 {
437 ANGLE_BASIS *abp = get_basis(kbasis);
438 float (*XZarr)[2] = NULL;
439 float bsdfarr[MAXPATCHES*MAXPATCHES];
440 FILE *cfp[3];
441 FVECT vin, vout;
442 double sum, xsum, ysum;
443 int i, j, n;
444 /* sanity check */
445 if (abp->nangles > MAXPATCHES) {
446 fprintf(stderr, "%s: too many patches!\n", progname);
447 exit(1);
448 }
449 if (rbf_colorimetry == RBCtristimulus)
450 XZarr = (float (*)[2])malloc(sizeof(float)*2*abp->nangles*abp->nangles);
451 for (i = 0; i < abp->nangles; i++) {
452 RBFNODE *rbf;
453 if (input_orient > 0) /* use incident patch center */
454 fi_getvec(vin, i+.5*(i>0), abp);
455 else
456 bi_getvec(vin, i+.5*(i>0), abp);
457
458 rbf = advect_rbf(vin, lobe_lim); /* compute radial basis func */
459
460 for (j = 0; j < abp->nangles; j++) {
461 sum = 0; /* sample over exiting patch */
462 xsum = ysum = 0;
463 for (n = npsamps; n--; ) {
464 SDValue sdv;
465 if (output_orient > 0)
466 fo_getvec(vout, j+(n+frandom())/npsamps, abp);
467 else
468 bo_getvec(vout, j+(n+frandom())/npsamps, abp);
469
470 eval_rbfcol(&sdv, rbf, vout);
471 sum += sdv.cieY;
472 if (XZarr != NULL) {
473 c_ccvt(&sdv.spec, C_CSXY);
474 xsum += sdv.cieY*sdv.spec.cx;
475 ysum += sdv.cieY*sdv.spec.cy;
476 }
477 }
478 n = j*abp->nangles + i;
479 bsdfarr[n] = sum / (double)npsamps;
480 if (XZarr != NULL) {
481 XZarr[n][0] = xsum*sum/(npsamps*ysum);
482 XZarr[n][1] = (sum - xsum - ysum)*sum/(npsamps*ysum);
483 }
484 }
485 if (rbf != NULL)
486 free(rbf);
487 prog_show((i+1.)/abp->nangles);
488 }
489 /* write out our matrix */
490 cfp[CIE_Y] = open_component_file(CIE_Y);
491 n = 0;
492 for (j = 0; j < abp->nangles; j++) {
493 for (i = 0; i < abp->nangles; i++, n++)
494 fprintf(cfp[CIE_Y], "\t%.3e\n", bsdfarr[n]);
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 n = 0;
507 for (j = 0; j < abp->nangles; j++) {
508 for (i = 0; i < abp->nangles; i++, n++) {
509 fprintf(cfp[CIE_X], "\t%.3e\n", XZarr[n][0]);
510 fprintf(cfp[CIE_Z], "\t%.3e\n", XZarr[n][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 }
521
522 #ifdef _WIN32
523 /* 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 /* 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 char buf[2048];
584 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 for (i = 1; i < argc && (argv[i][0] == '-') | (argv[i][0] == '+'); i++)
593 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 if (strchr(argv[++i], '=') != NULL) {
606 add_wbsdf("-f", 1);
607 add_wbsdf(argv[i], 1);
608 } else {
609 fcompile(argv[i]);
610 single_plane_incident = 0;
611 }
612 } else
613 dofwd = (argv[i][0] == '+');
614 break;
615 case 'b':
616 dobwd = (argv[i][0] == '+');
617 break;
618 case 'h':
619 kbasis = klems_half;
620 add_wbsdf("-a", 1);
621 add_wbsdf("kh", 1);
622 break;
623 case 'q':
624 kbasis = klems_quarter;
625 add_wbsdf("-a", 1);
626 add_wbsdf("kq", 1);
627 break;
628 case 'l':
629 lobe_lim = atoi(argv[++i]);
630 break;
631 case 'p':
632 do_prog = atoi(argv[i]+2);
633 break;
634 case 'C':
635 add_wbsdf(argv[i], 1);
636 add_wbsdf(argv[++i], 1);
637 break;
638 default:
639 goto userr;
640 }
641 if (kbasis == klems_full) { /* default (full) basis? */
642 add_wbsdf("-a", 1);
643 add_wbsdf("kf", 1);
644 }
645 strcpy(buf, "File produced by: ");
646 if (convert_commandline(buf+18, sizeof(buf)-18, argv) != NULL) {
647 add_wbsdf("-C", 1); add_wbsdf(buf, 0);
648 }
649 if (single_plane_incident >= 0) { /* function-based BSDF? */
650 if (i != argc-1 || fundefined(argv[i]) < 3) {
651 fprintf(stderr,
652 "%s: need single function with 6 arguments: bsdf(ix,iy,iz,ox,oy,oz)\n",
653 progname);
654 fprintf(stderr, "\tor 3 arguments using Dx,Dy,Dz: bsdf(ix,iy,iz)\n");
655 goto userr;
656 }
657 ++eclock;
658 if (dofwd) {
659 input_orient = -1;
660 output_orient = -1;
661 prog_start("Evaluating outside reflectance");
662 eval_function(argv[i]);
663 output_orient = 1;
664 prog_start("Evaluating outside->inside transmission");
665 eval_function(argv[i]);
666 }
667 if (dobwd) {
668 input_orient = 1;
669 output_orient = 1;
670 prog_start("Evaluating inside reflectance");
671 eval_function(argv[i]);
672 output_orient = -1;
673 prog_start("Evaluating inside->outside transmission");
674 eval_function(argv[i]);
675 }
676 return(wrap_up());
677 }
678 /* XML input? */
679 if (i == argc-1 && (cp = argv[i]+strlen(argv[i])-4) > argv[i] &&
680 !strcasecmp(cp, ".xml")) {
681 eval_bsdf(argv[i]); /* load & resample BSDF */
682 return(wrap_up());
683 }
684 if (i < argc) { /* open input files if given */
685 int nbsdf = 0;
686 for ( ; i < argc; i++) { /* interpolate each component */
687 char pbuf[256];
688 FILE *fpin = fopen(argv[i], "rb");
689 if (fpin == NULL) {
690 fprintf(stderr, "%s: cannot open BSDF interpolant '%s'\n",
691 progname, argv[i]);
692 return(1);
693 }
694 if (!load_bsdf_rep(fpin))
695 return(1);
696 fclose(fpin);
697 sprintf(pbuf, "Interpolating component '%s'", argv[i]);
698 prog_start(pbuf);
699 eval_rbf();
700 }
701 return(wrap_up());
702 }
703 SET_FILE_BINARY(stdin); /* load from stdin */
704 if (!load_bsdf_rep(stdin))
705 return(1);
706 prog_start("Interpolating from standard input");
707 eval_rbf(); /* resample dist. */
708 return(wrap_up());
709 userr:
710 fprintf(stderr,
711 "Usage: %s [-n spp][-h|-q][-l maxlobes] [bsdf.sir ..] > bsdf.xml\n", progname);
712 fprintf(stderr,
713 " or: %s [-n spp][-h|-q] bsdf_in.xml > bsdf_out.xml\n", progname);
714 fprintf(stderr,
715 " or: %s [-n spp][-h|-q][{+|-}for[ward]][{+|-}b[ackward]][-e expr][-f file] bsdf_func > bsdf.xml\n",
716 progname);
717 return(1);
718 }