ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2ttree.c
Revision: 2.32
Committed: Tue Feb 2 18:02:32 2016 UTC (8 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.31: +2 -71 lines
Log Message:
Moved declaration of popen to paths.h and put convert_command() into module

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: bsdf2ttree.c,v 2.31 2016/01/29 16:21:55 greg Exp $";
3 #endif
4 /*
5 * Load measured BSDF interpolant and write out as XML file with tensor tree.
6 *
7 * G. Ward
8 */
9
10 #define _USE_MATH_DEFINES
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include "random.h"
15 #include "platform.h"
16 #include "rtprocess.h"
17 #include "calcomp.h"
18 #include "bsdfrep.h"
19 /* global argv[0] */
20 char *progname;
21 /* percentage to cull (<0 to turn off) */
22 static double pctcull = 90.;
23 /* sampling order */
24 static int samp_order = 6;
25 /* super-sampling threshold */
26 const double ssamp_thresh = 0.35;
27 /* number of super-samples */
28 #ifndef NSSAMP
29 #define NSSAMP 100
30 #endif
31 /* limit on number of RBF lobes */
32 static int lobe_lim = 15000;
33 /* progress bar length */
34 static int do_prog = 79;
35
36
37
38 /* Start new progress bar */
39 #define prog_start(s) if (do_prog) fprintf(stderr, "%s: %s...\n", progname, s); else
40
41 /* Draw progress bar of the appropriate length */
42 static void
43 prog_show(double frac)
44 {
45 static unsigned call_cnt = 0;
46 static char lastc[] = "-\\|/";
47 char pbar[256];
48 int nchars;
49
50 if (do_prog <= 1) return;
51 if (do_prog > sizeof(pbar)-2)
52 do_prog = sizeof(pbar)-2;
53 if (frac < 0) frac = 0;
54 else if (frac >= 1) frac = .9999;
55 nchars = do_prog*frac;
56 pbar[0] = '\r';
57 memset(pbar+1, '*', nchars);
58 pbar[nchars+1] = lastc[call_cnt++ & 3];
59 memset(pbar+2+nchars, '-', do_prog-nchars-1);
60 pbar[do_prog+1] = '\0';
61 fputs(pbar, stderr);
62 }
63
64 /* Finish progress bar */
65 static void
66 prog_done(void)
67 {
68 int n = do_prog;
69
70 if (n <= 1) return;
71 fputc('\r', stderr);
72 while (n--)
73 fputc(' ', stderr);
74 fputc('\r', stderr);
75 }
76
77 /* Compute absolute relative difference */
78 static double
79 abs_diff(double v1, double v0)
80 {
81 if ((v0 < 0) | (v1 < 0))
82 return(.0);
83 v1 = (v1-v0)*2./(v0+v1+.0001);
84 if (v1 < 0)
85 return(-v1);
86 return(v1);
87 }
88
89 /* Interpolate and output isotropic BSDF data */
90 static void
91 eval_isotropic(char *funame)
92 {
93 const int sqres = 1<<samp_order;
94 FILE *ofp = NULL;
95 int assignD = 0;
96 char cmd[128];
97 int ix, ox, oy;
98 double iovec[6];
99 float bsdf;
100
101 data_prologue(); /* begin output */
102 if (pctcull >= 0) {
103 sprintf(cmd, "rttree_reduce -a -h -ff -r 3 -t %f -g %d",
104 pctcull, samp_order);
105 fflush(stdout);
106 ofp = popen(cmd, "w");
107 if (ofp == NULL) {
108 fprintf(stderr, "%s: cannot create pipe to rttree_reduce\n",
109 progname);
110 exit(1);
111 }
112 SET_FILE_BINARY(ofp);
113 #ifdef getc_unlocked /* avoid lock/unlock overhead */
114 flockfile(ofp);
115 #endif
116 } else
117 fputs("{\n", stdout);
118 /* need to assign Dx, Dy, Dz? */
119 if (funame != NULL)
120 assignD = (fundefined(funame) < 6);
121 /* run through directions */
122 for (ix = 0; ix < sqres/2; ix++) {
123 RBFNODE *rbf = NULL;
124 iovec[0] = 2.*(ix+.5)/sqres - 1.;
125 iovec[1] = .0;
126 iovec[2] = input_orient * sqrt(1. - iovec[0]*iovec[0]);
127 if (funame == NULL)
128 rbf = advect_rbf(iovec, lobe_lim);
129 for (ox = 0; ox < sqres; ox++) {
130 float last_bsdf = -1;
131 for (oy = 0; oy < sqres; oy++) {
132 SDsquare2disk(iovec+3, (ox+.5)/sqres, (oy+.5)/sqres);
133 iovec[5] = output_orient *
134 sqrt(1. - iovec[3]*iovec[3] - iovec[4]*iovec[4]);
135 if (funame == NULL)
136 bsdf = eval_rbfrep(rbf, iovec+3);
137 else {
138 if (assignD) {
139 varset("Dx", '=', -iovec[3]);
140 varset("Dy", '=', -iovec[4]);
141 varset("Dz", '=', -iovec[5]);
142 ++eclock;
143 }
144 bsdf = funvalue(funame, 6, iovec);
145 #if (NSSAMP > 0)
146 if (abs_diff(bsdf, last_bsdf) > ssamp_thresh) {
147 int ssi;
148 double ssa[3], ssvec[6], sum = 0;
149 /* super-sample voxel */
150 for (ssi = NSSAMP; ssi--; ) {
151 SDmultiSamp(ssa, 3, (ssi+frandom()) *
152 (1./NSSAMP));
153 ssvec[0] = 2.*(ix+ssa[0])/sqres - 1.;
154 ssvec[1] = .0;
155 ssvec[2] = input_orient *
156 sqrt(1. - ssvec[0]*ssvec[0]);
157 SDsquare2disk(ssvec+3, (ox+ssa[1])/sqres,
158 (oy+ssa[2])/sqres);
159 ssvec[5] = output_orient *
160 sqrt(1. - ssvec[3]*ssvec[3] -
161 ssvec[4]*ssvec[4]);
162 if (assignD) {
163 varset("Dx", '=', -ssvec[3]);
164 varset("Dy", '=', -ssvec[4]);
165 varset("Dz", '=', -ssvec[5]);
166 ++eclock;
167 }
168 sum += funvalue(funame, 6, ssvec);
169 }
170 bsdf = sum/NSSAMP;
171 }
172 #endif
173 }
174 if (pctcull >= 0)
175 fwrite(&bsdf, sizeof(bsdf), 1, ofp);
176 else
177 printf("\t%.3e\n", bsdf);
178 last_bsdf = bsdf;
179 }
180 }
181 if (rbf != NULL)
182 free(rbf);
183 prog_show((ix+1.)*(2./sqres));
184 }
185 if (pctcull >= 0) { /* finish output */
186 if (pclose(ofp)) {
187 fprintf(stderr, "%s: error running '%s'\n",
188 progname, cmd);
189 exit(1);
190 }
191 } else {
192 for (ix = sqres*sqres*sqres/2; ix--; )
193 fputs("\t0\n", stdout);
194 fputs("}\n", stdout);
195 }
196 data_epilogue();
197 prog_done();
198 }
199
200 /* Interpolate and output anisotropic BSDF data */
201 static void
202 eval_anisotropic(char *funame)
203 {
204 const int sqres = 1<<samp_order;
205 FILE *ofp = NULL;
206 int assignD = 0;
207 char cmd[128];
208 int ix, iy, ox, oy;
209 double iovec[6];
210 float bsdf;
211
212 data_prologue(); /* begin output */
213 if (pctcull >= 0) {
214 sprintf(cmd, "rttree_reduce%s -h -ff -r 4 -t %f -g %d",
215 (input_orient>0 ^ output_orient>0) ? "" : " -a",
216 pctcull, samp_order);
217 fflush(stdout);
218 ofp = popen(cmd, "w");
219 if (ofp == NULL) {
220 fprintf(stderr, "%s: cannot create pipe to rttree_reduce\n",
221 progname);
222 exit(1);
223 }
224 SET_FILE_BINARY(ofp);
225 #ifdef getc_unlocked /* avoid lock/unlock overhead */
226 flockfile(ofp);
227 #endif
228 } else
229 fputs("{\n", stdout);
230 /* need to assign Dx, Dy, Dz? */
231 if (funame != NULL)
232 assignD = (fundefined(funame) < 6);
233 /* run through directions */
234 for (ix = 0; ix < sqres; ix++)
235 for (iy = 0; iy < sqres; iy++) {
236 RBFNODE *rbf = NULL; /* Klems reversal */
237 SDsquare2disk(iovec, 1.-(ix+.5)/sqres, 1.-(iy+.5)/sqres);
238 iovec[2] = input_orient *
239 sqrt(1. - iovec[0]*iovec[0] - iovec[1]*iovec[1]);
240 if (funame == NULL)
241 rbf = advect_rbf(iovec, lobe_lim);
242 for (ox = 0; ox < sqres; ox++) {
243 float last_bsdf = -1;
244 for (oy = 0; oy < sqres; oy++) {
245 SDsquare2disk(iovec+3, (ox+.5)/sqres, (oy+.5)/sqres);
246 iovec[5] = output_orient *
247 sqrt(1. - iovec[3]*iovec[3] - iovec[4]*iovec[4]);
248 if (funame == NULL)
249 bsdf = eval_rbfrep(rbf, iovec+3);
250 else {
251 if (assignD) {
252 varset("Dx", '=', -iovec[3]);
253 varset("Dy", '=', -iovec[4]);
254 varset("Dz", '=', -iovec[5]);
255 ++eclock;
256 }
257 bsdf = funvalue(funame, 6, iovec);
258 #if (NSSAMP > 0)
259 if (abs_diff(bsdf, last_bsdf) > ssamp_thresh) {
260 int ssi;
261 double ssa[4], ssvec[6], sum = 0;
262 /* super-sample voxel */
263 for (ssi = NSSAMP; ssi--; ) {
264 SDmultiSamp(ssa, 4, (ssi+frandom()) *
265 (1./NSSAMP));
266 SDsquare2disk(ssvec, 1.-(ix+ssa[0])/sqres,
267 1.-(iy+ssa[1])/sqres);
268 ssvec[2] = input_orient *
269 sqrt(1. - ssvec[0]*ssvec[0] -
270 ssvec[1]*ssvec[1]);
271 SDsquare2disk(ssvec+3, (ox+ssa[2])/sqres,
272 (oy+ssa[3])/sqres);
273 ssvec[5] = output_orient *
274 sqrt(1. - ssvec[3]*ssvec[3] -
275 ssvec[4]*ssvec[4]);
276 if (assignD) {
277 varset("Dx", '=', -ssvec[3]);
278 varset("Dy", '=', -ssvec[4]);
279 varset("Dz", '=', -ssvec[5]);
280 ++eclock;
281 }
282 sum += funvalue(funame, 6, ssvec);
283 }
284 bsdf = sum/NSSAMP;
285 }
286 #endif
287 }
288 if (pctcull >= 0)
289 fwrite(&bsdf, sizeof(bsdf), 1, ofp);
290 else
291 printf("\t%.3e\n", bsdf);
292 last_bsdf = bsdf;
293 }
294 }
295 if (rbf != NULL)
296 free(rbf);
297 prog_show((ix*sqres+iy+1.)/(sqres*sqres));
298 }
299 if (pctcull >= 0) { /* finish output */
300 if (pclose(ofp)) {
301 fprintf(stderr, "%s: error running '%s'\n",
302 progname, cmd);
303 exit(1);
304 }
305 } else
306 fputs("}\n", stdout);
307 data_epilogue();
308 prog_done();
309 }
310
311 /* Read in BSDF and interpolate as tensor tree representation */
312 int
313 main(int argc, char *argv[])
314 {
315 int dofwd = 0, dobwd = 1;
316 int i, na;
317
318 progname = argv[0];
319 esupport |= E_VARIABLE|E_FUNCTION|E_RCONST;
320 esupport &= ~(E_INCHAN|E_OUTCHAN);
321 scompile("PI:3.14159265358979323846", NULL, 0);
322 biggerlib();
323 for (i = 1; i < argc-1 && (argv[i][0] == '-') | (argv[i][0] == '+'); i++)
324 switch (argv[i][1]) { /* get options */
325 case 'e':
326 scompile(argv[++i], NULL, 0);
327 break;
328 case 'f':
329 if (!argv[i][2])
330 fcompile(argv[++i]);
331 else
332 dofwd = (argv[i][0] == '+');
333 break;
334 case 'b':
335 dobwd = (argv[i][0] == '+');
336 break;
337 case 't':
338 switch (argv[i][2]) {
339 case '3':
340 single_plane_incident = 1;
341 break;
342 case '4':
343 single_plane_incident = 0;
344 break;
345 case '\0':
346 pctcull = atof(argv[++i]);
347 break;
348 default:
349 goto userr;
350 }
351 break;
352 case 'g':
353 samp_order = atoi(argv[++i]);
354 break;
355 case 'l':
356 lobe_lim = atoi(argv[++i]);
357 break;
358 case 'p':
359 do_prog = atoi(argv[i]+2);
360 break;
361 default:
362 goto userr;
363 }
364 if (single_plane_incident >= 0) { /* function-based BSDF? */
365 void (*evf)(char *s) = single_plane_incident ?
366 &eval_isotropic : &eval_anisotropic;
367 if (i != argc-1 || fundefined(argv[i]) < 3) {
368 fprintf(stderr,
369 "%s: need single function with 6 arguments: bsdf(ix,iy,iz,ox,oy,oz)\n",
370 progname);
371 fprintf(stderr, "\tor 3 arguments using Dx,Dy,Dz: bsdf(ix,iy,iz)\n");
372 goto userr;
373 }
374 ++eclock;
375 xml_prologue(argc, argv); /* start XML output */
376 if (dofwd) {
377 input_orient = -1;
378 output_orient = -1;
379 prog_start("Evaluating outside reflectance");
380 (*evf)(argv[i]);
381 output_orient = 1;
382 prog_start("Evaluating outside->inside transmission");
383 (*evf)(argv[i]);
384 }
385 if (dobwd) {
386 input_orient = 1;
387 output_orient = 1;
388 prog_start("Evaluating inside reflectance");
389 (*evf)(argv[i]);
390 output_orient = -1;
391 prog_start("Evaluating inside->outside transmission");
392 (*evf)(argv[i]);
393 }
394 xml_epilogue(); /* finish XML output & exit */
395 return(0);
396 }
397 if (i < argc) { /* open input files if given */
398 int nbsdf = 0;
399 for ( ; i < argc; i++) { /* interpolate each component */
400 char pbuf[256];
401 FILE *fpin = fopen(argv[i], "rb");
402 if (fpin == NULL) {
403 fprintf(stderr, "%s: cannot open BSDF interpolant '%s'\n",
404 progname, argv[i]);
405 return(1);
406 }
407 if (!load_bsdf_rep(fpin))
408 return(1);
409 fclose(fpin);
410 if (!nbsdf++) /* start XML on first dist. */
411 xml_prologue(argc, argv);
412 sprintf(pbuf, "Interpolating component '%s'", argv[i]);
413 prog_start(pbuf);
414 if (single_plane_incident)
415 eval_isotropic(NULL);
416 else
417 eval_anisotropic(NULL);
418 }
419 xml_epilogue(); /* finish XML output & exit */
420 return(0);
421 }
422 SET_FILE_BINARY(stdin); /* load from stdin */
423 if (!load_bsdf_rep(stdin))
424 return(1);
425 xml_prologue(argc, argv); /* start XML output */
426 prog_start("Interpolating from standard input");
427 if (single_plane_incident) /* resample dist. */
428 eval_isotropic(NULL);
429 else
430 eval_anisotropic(NULL);
431 xml_epilogue(); /* finish XML output & exit */
432 return(0);
433 userr:
434 fprintf(stderr,
435 "Usage: %s [-g Nlog2][-t pctcull][-l maxlobes] [bsdf.sir ..] > bsdf.xml\n",
436 progname);
437 fprintf(stderr,
438 " or: %s -t{3|4} [-g Nlog2][-t pctcull][{+|-}for[ward]][{+|-}b[ackward]][-e expr][-f file] bsdf_func > bsdf.xml\n",
439 progname);
440 return(1);
441 }