ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2ttree.c
Revision: 2.17
Committed: Fri Aug 2 20:56:19 2013 UTC (10 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.16: +37 -2 lines
Log Message:
Added ability to use Dx, Dy and Dz instead of last 3 function parameters

File Contents

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