ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/bsdf2rad.c
Revision: 2.16
Committed: Sun Apr 9 21:39:26 2017 UTC (7 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.15: +773 -139 lines
Log Message:
Completely rewrote bsdf2rad for visualizating BSDFs using lots of 3-D plots

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.16 static const char RCSid[] = "$Id: bsdf2rad.c,v 2.15 2016/03/06 01:13:17 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5 greg 2.4 * Plot 3-D BSDF output based on scattering interpolant or XML representation
6 greg 2.1 */
7    
8     #include <stdio.h>
9 greg 2.4 #include <string.h>
10 greg 2.1 #include <stdlib.h>
11 greg 2.16 #include "paths.h"
12     #include "rtmath.h"
13     #include "resolu.h"
14 greg 2.1 #include "bsdfrep.h"
15    
16 greg 2.16 #define NINCIDENT 25 /* number of samples/hemisphere */
17 greg 2.1
18 greg 2.16 #define GRIDSTEP 2 /* our grid step size */
19     #define SAMPRES (GRIDRES/GRIDSTEP)
20    
21     int front_comp = 0; /* front component flags (SDsamp*) */
22     int back_comp = 0; /* back component flags */
23     double overall_min = 1./PI; /* overall minimum BSDF value */
24     double min_log10; /* smallest log10 value for plotting */
25     double overall_max = .0; /* overall maximum BSDF value */
26    
27     char ourTempDir[TEMPLEN] = ""; /* our temporary directory */
28    
29     const FVECT Xaxis = {1., 0., 0.};
30     const FVECT Yaxis = {0., 1., 0.};
31     const FVECT Zaxis = {0., 0., 1.};
32    
33     const char frpref[] = "frefl";
34     const char ftpref[] = "ftrans";
35     const char brpref[] = "brefl";
36     const char btpref[] = "btrans";
37     const char dsuffix[] = ".txt";
38    
39     const char sph_mat[] = "BSDFmat";
40     const double sph_rad = 10.;
41     const double sph_xoffset = 15.;
42    
43     #define bsdf_rad (sph_rad*.25)
44     #define arrow_rad (bsdf_rad*.015)
45    
46     #define FEQ(a,b) ((a)-(b) <= 1e-7 && (b)-(a) <= 1e-7)
47    
48     #define set_minlog() (min_log10 = log10(overall_min + 1e-5) - .1)
49    
50     char *progname;
51    
52     /* Get Fibonacci sphere vector (0 to NINCIDENT-1) */
53     static void
54     get_ivector(FVECT iv, int i)
55     {
56     const double zstep = 1./(2*NINCIDENT-1);
57     const double phistep = PI*(3. - 2.236067978);
58     double r;
59    
60     iv[2] = 1. - (i+.5)*zstep;
61     r = sqrt(1. - iv[2]*iv[2]);
62     iv[0] = r * cos((i+1.)*phistep);
63     iv[1] = r * sin((i+1.)*phistep);
64     }
65    
66     /* Get temporary file name */
67     static char *
68     tfile_name(const char *prefix, const char *suffix, int i)
69     {
70     static char buf[128];
71    
72     if (!ourTempDir[0]) { /* create temporary directory */
73     mktemp(strcpy(ourTempDir,TEMPLATE));
74     if (mkdir(ourTempDir, 0777) < 0) {
75     perror("mkdir");
76     exit(1);
77     }
78     }
79     if (!prefix) prefix = "T";
80     if (!suffix) suffix = "";
81     sprintf(buf, "%s/%s%03d%s", ourTempDir, prefix, i, suffix);
82     return(buf);
83     }
84    
85     /* Remove temporary directory & contents */
86     static void
87     cleanup_tmp(void)
88     {
89     char buf[128];
90    
91     if (!ourTempDir[0])
92     return;
93 schorsch 2.15 #if defined(_WIN32) || defined(_WIN64)
94 greg 2.16 sprintf(buf, "RMDIR %s /S /Q", ourTempDir);
95 greg 2.11 #else
96 greg 2.16 sprintf(buf, "rm -rf %s", ourTempDir);
97 greg 2.11 #endif
98 greg 2.16 system(buf);
99     }
100    
101     /* Run the specified command, returning 1 if OK */
102     static int
103     run_cmd(const char *cmd)
104     {
105     fflush(stdout);
106     if (system(cmd)) {
107     fprintf(stderr, "%s: error running: %s\n", progname, cmd);
108     return(0);
109     }
110     return(1);
111     }
112    
113     /* Plot surface points for the given BSDF incident angle */
114     static int
115     plotBSDF(const char *fname, const FVECT ivec, int dfl, const SDData *sd)
116     {
117     FILE *fp = fopen(fname, "w");
118     int i, j;
119    
120     if (fp == NULL) {
121     fprintf(stderr, "%s: cannot open '%s' for writing\n",
122     progname, fname);
123     return(0);
124     }
125     if (ivec[2] > 0) {
126     input_orient = 1;
127     output_orient = dfl&SDsampR ? 1 : -1;
128     } else {
129     input_orient = -1;
130     output_orient = dfl&SDsampR ? -1 : 1;
131     }
132     for (i = SAMPRES; i--; )
133     for (j = 0; j < SAMPRES; j++) {
134     FVECT ovec;
135     SDValue sval;
136     double bsdf;
137     ovec_from_pos(ovec, i*GRIDSTEP, j*GRIDSTEP);
138     if (SDreportError(SDevalBSDF(&sval, ovec,
139     ivec, sd), stderr))
140     return(0);
141     if (sval.cieY > overall_max)
142     overall_max = sval.cieY;
143     bsdf = (sval.cieY < overall_min) ? overall_min : sval.cieY;
144     bsdf = log10(bsdf) - min_log10;
145     fprintf(fp, "%.5f %.5f %.5f\n",
146     ovec[0]*bsdf, ovec[1]*bsdf, ovec[2]*bsdf);
147     }
148     if (fclose(fp) == EOF) {
149     fprintf(stderr, "%s: error writing data to '%s'\n",
150     progname, fname);
151     return(0);
152     }
153     return(1);
154     }
155    
156     /* Build BSDF values from loaded XML file */
157     static int
158     build_wBSDF(const SDData *sd)
159     {
160     FVECT ivec;
161     int i;
162    
163     if (front_comp & SDsampR)
164     for (i = 0; i < NINCIDENT; i++) {
165     get_ivector(ivec, i);
166     if (!plotBSDF(tfile_name(frpref, dsuffix, i),
167     ivec, SDsampR, sd))
168     return(0);
169     }
170     if (front_comp & SDsampT)
171     for (i = 0; i < NINCIDENT; i++) {
172     get_ivector(ivec, i);
173     if (!plotBSDF(tfile_name(ftpref, dsuffix, i),
174     ivec, SDsampT, sd))
175     return(0);
176     }
177     if (back_comp & SDsampR)
178     for (i = 0; i < NINCIDENT; i++) {
179     get_ivector(ivec, i);
180     ivec[0] = -ivec[0]; ivec[2] = -ivec[2];
181     if (!plotBSDF(tfile_name(brpref, dsuffix, i),
182     ivec, SDsampR, sd))
183     return(0);
184     }
185     if (back_comp & SDsampT)
186     for (i = 0; i < NINCIDENT; i++) {
187     get_ivector(ivec, i);
188     ivec[0] = -ivec[0]; ivec[2] = -ivec[2];
189     if (!plotBSDF(tfile_name(btpref, dsuffix, i),
190     ivec, SDsampT, sd))
191     return(0);
192     }
193     return(1);
194     }
195    
196     /* Plot surface points using radial basis function */
197     static int
198     plotRBF(const char *fname, const RBFNODE *rbf)
199     {
200     FILE *fp = fopen(fname, "w");
201     int i, j;
202    
203     if (fp == NULL) {
204     fprintf(stderr, "%s: cannot open '%s' for writing\n",
205     progname, fname);
206     return(0);
207     }
208     for (i = SAMPRES; i--; )
209     for (j = 0; j < SAMPRES; j++) {
210     FVECT ovec;
211     double bsdf;
212     ovec_from_pos(ovec, i*GRIDSTEP, j*GRIDSTEP);
213     bsdf = eval_rbfrep(rbf, ovec);
214     if (bsdf > overall_max)
215     overall_max = bsdf;
216     else if (bsdf < overall_min)
217     bsdf = overall_min;
218     bsdf = log10(bsdf) - min_log10;
219     fprintf(fp, "%.5f %.5f %.5f\n",
220     ovec[0]*bsdf, ovec[1]*bsdf, ovec[2]*bsdf);
221     }
222     if (fclose(fp) == EOF) {
223     fprintf(stderr, "%s: error writing data to '%s'\n",
224     progname, fname);
225     return(0);
226     }
227     return(1);
228     }
229    
230     /* Build BSDF values from scattering interpolant representation */
231     static int
232     build_wRBF(void)
233     {
234     const char *pref;
235     int i;
236    
237     if (input_orient > 0) {
238     if (output_orient > 0)
239     pref = frpref;
240     else
241     pref = ftpref;
242     } else if (output_orient < 0)
243     pref = brpref;
244     else
245     pref = btpref;
246    
247     for (i = 0; i < NINCIDENT; i++) {
248     FVECT ivec;
249     RBFNODE *rbf;
250     get_ivector(ivec, i);
251     if (input_orient < 0) {
252     ivec[0] = -ivec[0]; ivec[1] = -ivec[1]; ivec[2] = -ivec[2];
253     }
254     rbf = advect_rbf(ivec, 15000);
255     if (!plotRBF(tfile_name(pref, dsuffix, i), rbf))
256     return(0);
257     if (rbf) free(rbf);
258     }
259     return(1); /* next call frees */
260     }
261    
262     /* Put out mirror arrow for the given incident vector */
263     static void
264     put_mirror_arrow(const FVECT ivec, int inc_side)
265     {
266     const double arrow_len = 1.2*bsdf_rad;
267     const double tip_len = 0.2*bsdf_rad;
268     FVECT origin, refl;
269     int i;
270    
271     for (i = 3; i--; ) origin[i] = ivec[i]*sph_rad;
272     origin[0] -= inc_side*sph_xoffset;
273    
274     refl[0] = 2.*ivec[2]*ivec[0];
275     refl[1] = 2.*ivec[2]*ivec[1];
276     refl[2] = 2.*ivec[2]*ivec[2] - 1.;
277    
278     printf("\n# Mirror arrow\n");
279     printf("\narrow_mat cylinder inc_dir\n0\n0\n7");
280     printf("\n\t%f %f %f\n\t%f %f %f\n\t%f\n",
281     origin[0], origin[1], origin[2]+arrow_len,
282     origin[0], origin[1], origin[2],
283     arrow_rad);
284     printf("\narrow_mat cylinder mir_dir\n0\n0\n7");
285     printf("\n\t%f %f %f\n\t%f %f %f\n\t%f\n",
286     origin[0], origin[1], origin[2],
287     origin[0] + arrow_len*refl[0],
288     origin[1] + arrow_len*refl[1],
289     origin[2] + arrow_len*refl[2],
290     arrow_rad);
291     printf("\narrow_mat cone mir_tip\n0\n0\n8");
292     printf("\n\t%f %f %f\n\t%f %f %f\n\t%f 0\n",
293     origin[0] + (arrow_len-.5*tip_len)*refl[0],
294     origin[1] + (arrow_len-.5*tip_len)*refl[1],
295     origin[2] + (arrow_len-.5*tip_len)*refl[2],
296     origin[0] + (arrow_len+.5*tip_len)*refl[0],
297     origin[1] + (arrow_len+.5*tip_len)*refl[1],
298     origin[2] + (arrow_len+.5*tip_len)*refl[2],
299     2.*arrow_rad);
300     }
301    
302     /* Put out transmitted direction arrow for the given incident vector */
303     static void
304     put_trans_arrow(const FVECT ivec, int inc_side)
305     {
306     const double arrow_len = 1.2*bsdf_rad;
307     const double tip_len = 0.2*bsdf_rad;
308     FVECT origin;
309     int i;
310    
311     for (i = 3; i--; ) origin[i] = ivec[i]*sph_rad;
312     origin[0] -= inc_side*sph_xoffset;
313    
314     printf("\n# Transmission arrow\n");
315     printf("\narrow_mat cylinder trans_dir\n0\n0\n7");
316     printf("\n\t%f %f %f\n\t%f %f %f\n\t%f\n",
317     origin[0], origin[1], origin[2],
318     origin[0], origin[1], origin[2]-arrow_len,
319     arrow_rad);
320     printf("\narrow_mat cone trans_tip\n0\n0\n8");
321     printf("\n\t%f %f %f\n\t%f %f %f\n\t%f 0\n",
322     origin[0], origin[1], origin[2]-arrow_len+.5*tip_len,
323     origin[0], origin[1], origin[2]-arrow_len-.5*tip_len,
324     2.*arrow_rad);
325     }
326    
327     /* Compute rotation (x,y,z) => (xp,yp,zp) */
328     static int
329     addrot(char *xf, const FVECT xp, const FVECT yp, const FVECT zp)
330     {
331     int n = 0;
332     double theta;
333 greg 2.10
334 greg 2.16 if (yp[2]*yp[2] + zp[2]*zp[2] < 2.*FTINY*FTINY) {
335     /* Special case for X' along Z-axis */
336     theta = -atan2(yp[0], yp[1]);
337     sprintf(xf, " -ry %f -rz %f",
338     xp[2] < 0.0 ? 90.0 : -90.0,
339     theta*(180./PI));
340     return(4);
341     }
342     theta = atan2(yp[2], zp[2]);
343     if (!FEQ(theta,0.0)) {
344     sprintf(xf, " -rx %f", theta*(180./PI));
345     while (*xf) ++xf;
346     n += 2;
347     }
348     theta = Asin(-xp[2]);
349     if (!FEQ(theta,0.0)) {
350     sprintf(xf, " -ry %f", theta*(180./PI));
351     while (*xf) ++xf;
352     n += 2;
353     }
354     theta = atan2(xp[1], xp[0]);
355     if (!FEQ(theta,0.0)) {
356     sprintf(xf, " -rz %f", theta*(180./PI));
357     /* while (*xf) ++xf; */
358     n += 2;
359     }
360     return(n);
361     }
362    
363     /* Put out BSDF surfaces */
364     static int
365     put_BSDFs(void)
366     {
367     const double scalef = bsdf_rad/(log10(overall_max) - min_log10);
368     FVECT ivec;
369     RREAL vMtx[3][3];
370     char *fname;
371     char cmdbuf[256];
372     char xfargs[128];
373     int nxfa;
374     int i;
375    
376     printf("\n# Gensurf output corresponding to %d incident directions\n",
377     NINCIDENT);
378    
379     printf("\nvoid glow arrow_glow\n0\n0\n4 1 0 1 0\n");
380     printf("\nvoid mixfunc arrow_mat\n4 arrow_glow void .5 .\n0\n0\n");
381    
382     if (front_comp & SDsampR)
383     for (i = 0; i < NINCIDENT; i++) {
384     get_ivector(ivec, i);
385     put_mirror_arrow(ivec, 1);
386     sprintf(xfargs, "-s %f -t %f %f %f", bsdf_rad,
387     ivec[0]*sph_rad - sph_xoffset,
388     ivec[1]*sph_rad, ivec[2]*sph_rad);
389     nxfa = 6;
390     printf("\nvoid colorfunc scale_pat\n");
391     printf("%d bsdf_red bsdf_grn bsdf_blu bsdf2rad.cal\n\t%s\n0\n0\n",
392     4+nxfa, xfargs);
393     printf("\nscale_pat glow scale_mat\n0\n0\n4 1 1 1 0\n");
394     SDcompXform(vMtx, ivec, Yaxis);
395     nxfa = addrot(xfargs, vMtx[0], vMtx[1], vMtx[2]);
396     sprintf(xfargs+strlen(xfargs), " -s %f -t %f %f %f",
397     scalef, ivec[0]*sph_rad - sph_xoffset,
398     ivec[1]*sph_rad, ivec[2]*sph_rad);
399     nxfa += 6;
400     fname = tfile_name(frpref, dsuffix, i);
401     sprintf(cmdbuf, "gensurf scale_mat %s%d %s %s %s %d %d | xform -mx -my %s",
402     frpref, i+1, fname, fname, fname, SAMPRES-1, SAMPRES-1,
403     xfargs);
404     if (!run_cmd(cmdbuf))
405     return(0);
406     }
407     if (front_comp & SDsampT)
408     for (i = 0; i < NINCIDENT; i++) {
409     get_ivector(ivec, i);
410     put_trans_arrow(ivec, 1);
411     sprintf(xfargs, "-s %f -t %f %f %f", bsdf_rad,
412     ivec[0]*sph_rad - sph_xoffset,
413     ivec[1]*sph_rad, ivec[2]*sph_rad);
414     nxfa = 6;
415     printf("\nvoid colorfunc scale_pat\n");
416     printf("%d bsdf_red bsdf_grn bsdf_blu bsdf2rad.cal\n\t%s\n0\n0\n",
417     4+nxfa, xfargs);
418     printf("\nscale_pat glow scale_mat\n0\n0\n4 1 1 1 0\n");
419     SDcompXform(vMtx, ivec, Yaxis);
420     nxfa = addrot(xfargs, vMtx[0], vMtx[1], vMtx[2]);
421     sprintf(xfargs+strlen(xfargs), " -s %f -t %f %f %f",
422     scalef, ivec[0]*sph_rad - sph_xoffset,
423     ivec[1]*sph_rad, ivec[2]*sph_rad);
424     nxfa += 6;
425     fname = tfile_name(ftpref, dsuffix, i);
426     sprintf(cmdbuf, "gensurf scale_mat %s%d %s %s %s %d %d | xform -I -mx -my %s",
427     ftpref, i+1, fname, fname, fname, SAMPRES-1, SAMPRES-1,
428     xfargs);
429     if (!run_cmd(cmdbuf))
430     return(0);
431     }
432     if (back_comp & SDsampR)
433     for (i = 0; i < NINCIDENT; i++) {
434     get_ivector(ivec, i);
435     put_mirror_arrow(ivec, -1);
436     fname = tfile_name(brpref, dsuffix, i);
437     sprintf(xfargs, "-s %f -t %f %f %f", bsdf_rad,
438     ivec[0]*sph_rad + sph_xoffset,
439     ivec[1]*sph_rad, ivec[2]*sph_rad);
440     nxfa = 6;
441     printf("\nvoid colorfunc scale_pat\n");
442     printf("%d bsdf_red bsdf_grn bsdf_blu bsdf2rad.cal\n\t%s\n0\n0\n",
443     4+nxfa, xfargs);
444     printf("\nscale_pat glow scale_mat\n0\n0\n4 1 1 1 0\n");
445     SDcompXform(vMtx, ivec, Yaxis);
446     nxfa = addrot(xfargs, vMtx[0], vMtx[1], vMtx[2]);
447     sprintf(xfargs+strlen(xfargs), " -s %f -t %f %f %f",
448     scalef, ivec[0]*sph_rad + sph_xoffset,
449     ivec[1]*sph_rad, ivec[2]*sph_rad);
450     nxfa += 6;
451     fname = tfile_name(brpref, dsuffix, i);
452     sprintf(cmdbuf, "gensurf scale_mat %s%d %s %s %s %d %d | xform -I -ry 180 -mx -my %s",
453     brpref, i+1, fname, fname, fname, SAMPRES-1, SAMPRES-1,
454     xfargs);
455     if (!run_cmd(cmdbuf))
456     return(0);
457     }
458     if (back_comp & SDsampT)
459     for (i = 0; i < NINCIDENT; i++) {
460     get_ivector(ivec, i);
461     put_trans_arrow(ivec, -1);
462     fname = tfile_name(btpref, dsuffix, i);
463     sprintf(xfargs, "-s %f -t %f %f %f", bsdf_rad,
464     ivec[0]*sph_rad + sph_xoffset,
465     ivec[1]*sph_rad, ivec[2]*sph_rad);
466     nxfa = 6;
467     printf("\nvoid colorfunc scale_pat\n");
468     printf("%d bsdf_red bsdf_grn bsdf_blu bsdf2rad.cal\n\t%s\n0\n0\n",
469     4+nxfa, xfargs);
470     printf("\nscale_pat glow scale_mat\n0\n0\n4 1 1 1 0\n");
471     SDcompXform(vMtx, ivec, Yaxis);
472     nxfa = addrot(xfargs, vMtx[0], vMtx[1], vMtx[2]);
473     sprintf(xfargs+strlen(xfargs), " -s %f -t %f %f %f",
474     scalef, ivec[0]*sph_rad + sph_xoffset,
475     ivec[1]*sph_rad, ivec[2]*sph_rad);
476     nxfa += 6;
477     fname = tfile_name(btpref, dsuffix, i);
478     sprintf(cmdbuf, "gensurf scale_mat %s%d %s %s %s %d %d | xform -ry 180 -mx -my %s",
479     btpref, i+1, fname, fname, fname, SAMPRES-1, SAMPRES-1,
480     xfargs);
481     if (!run_cmd(cmdbuf))
482     return(0);
483     }
484     return(1);
485     }
486    
487     /* Put our hemisphere material */
488     static void
489     put_matBSDF(const char *XMLfile)
490     {
491     const char *curdir = "./";
492    
493     if (!XMLfile) { /* simple material */
494     printf("\n# Simplified material because we have no XML input\n");
495     printf("\nvoid brightfunc latlong\n2 latlong bsdf2rad.cal\n0\n0\n");
496     if ((front_comp|back_comp) & SDsampT)
497     printf("\nlatlong trans %s\n0\n0\n7 .75 .75 .75 0 0 .5 .8\n",
498     sph_mat);
499     else
500     printf("\nlatlong plastic %s\n0\n0\n5 .5 .5 .5 0 0\n",
501     sph_mat);
502     return;
503     }
504     switch (XMLfile[0]) { /* avoid RAYPATH search */
505     case '.':
506     CASEDIRSEP:
507     curdir = "";
508     break;
509     case '\0':
510     fprintf(stderr, "%s: empty file name in put_matBSDF\n", progname);
511     exit(1);
512     break;
513     }
514     printf("\n# Actual BSDF material for rendering the hemispheres\n");
515     printf("\nvoid BSDF BSDFmat\n6 0 \"%s%s\" 0 1 0 .\n0\n0\n",
516     curdir, XMLfile);
517     printf("\nvoid plastic black\n0\n0\n5 0 0 0 0 0\n");
518     printf("\nvoid mixfunc %s\n4 BSDFmat black latlong bsdf2rad.cal\n0\n0\n",
519     sph_mat);
520     }
521    
522     /* Put out overhead parallel light source */
523     static void
524     put_source(void)
525     {
526     printf("\n# Overhead parallel light source\n");
527     printf("\nvoid light bright\n0\n0\n3 1000 1000 1000\n");
528     printf("\nbright source light\n0\n0\n4 0 0 1 2\n");
529     printf("\n# Material used for labels\n");
530     printf("\nvoid trans vellum\n0\n0\n7 1 1 1 0 0 .5 0\n");
531     }
532    
533     /* Put out hemisphere(s) */
534     static void
535     put_hemispheres(void)
536     {
537     printf("\n# Hemisphere(s) for showing BSDF appearance (if XML file)\n");
538     printf("\nvoid antimatter anti_sph\n2 void %s\n0\n0\n", sph_mat);
539     if (front_comp) {
540     printf("\n%s sphere Front\n0\n0\n4 %f 0 0 %f\n",
541     sph_mat, -sph_xoffset, sph_rad);
542     printf("\n!genbox anti_sph sph_eraser %f %f %f | xform -t %f %f %f\n",
543     2.02*sph_rad, 2.02*sph_rad, 1.02*sph_rad,
544     -1.01*sph_rad - sph_xoffset, -1.01*sph_rad, -1.01*sph_rad);
545     printf("\nvoid brighttext front_text\n3 helvet.fnt . FRONT\n0\n");
546     printf("12\n\t%f %f 0\n\t%f 0 0\n\t0 %f 0\n\t.01 1 -.1\n",
547     -.22*sph_rad - sph_xoffset, -1.2*sph_rad,
548     .35/5.*sph_rad, -1.6*.35/5.*sph_rad);
549     printf("\nfront_text alias front_label_mat vellum\n");
550     printf("\nfront_label_mat polygon front_label\n0\n0\n12");
551     printf("\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n",
552     -.25*sph_rad - sph_xoffset, -1.1*sph_rad,
553     -.25*sph_rad - sph_xoffset, (-1.2-1.6*.35/5.-.1)*sph_rad,
554     .25*sph_rad - sph_xoffset, (-1.2-1.6*.35/5.-.1)*sph_rad,
555     .25*sph_rad - sph_xoffset, -1.1*sph_rad );
556     }
557     if (back_comp) {
558     printf("\n%s bubble Back\n0\n0\n4 %f 0 0 %f\n",
559     sph_mat, sph_xoffset, sph_rad);
560     printf("\n!genbox anti_sph sph_eraser %f %f %f | xform -t %f %f %f\n",
561     2.02*sph_rad, 2.02*sph_rad, 1.02*sph_rad,
562     -1.01*sph_rad + sph_xoffset, -1.01*sph_rad, -1.01*sph_rad);
563     printf("\nvoid brighttext back_text\n3 helvet.fnt . BACK\n0\n");
564     printf("12\n\t%f %f 0\n\t%f 0 0\n\t0 %f 0\n\t.01 1 -.1\n",
565     -.22*sph_rad + sph_xoffset, -1.2*sph_rad,
566     .35/4.*sph_rad, -1.6*.35/4.*sph_rad);
567     printf("\nback_text alias back_label_mat vellum\n");
568     printf("\nback_label_mat polygon back_label\n0\n0\n12");
569     printf("\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n",
570     -.25*sph_rad + sph_xoffset, -1.1*sph_rad,
571     -.25*sph_rad + sph_xoffset, (-1.2-1.6*.35/4.-.1)*sph_rad,
572     .25*sph_rad + sph_xoffset, (-1.2-1.6*.35/4.-.1)*sph_rad,
573     .25*sph_rad + sph_xoffset, -1.1*sph_rad );
574     }
575     }
576    
577     /* Put out falsecolor scale and name label */
578     static void
579     put_scale(void)
580     {
581     const double max_log10 = log10(overall_max);
582     const double leg_width = 2.*.75*(sph_xoffset - sph_rad);
583     const double leg_height = 2.*sph_rad;
584     const int text_lines = 6;
585     const int text_digits = 7;
586     char fmt[16];
587     int i;
588    
589     printf("\n# BSDF legend with falsecolor scale\n");
590     printf("\nvoid colorfunc lscale\n10 sca_red(Py) sca_grn(Py) sca_blu(Py)");
591     printf("\n\tbsdf2rad.cal -s %f -t 0 %f 0\n0\n0\n", leg_height, -.5*leg_height);
592     sprintf(fmt, "%%%dg", text_digits-2);
593     for (i = 0; i < text_lines; i++) {
594     char vbuf[16];
595     sprintf(vbuf, fmt, pow(10., (i+.5)/text_lines*(max_log10-min_log10)+min_log10));
596     printf("\nlscale brighttext lscale\n");
597     printf("3 helvet.fnt . %s\n0\n12\n", vbuf);
598     printf("\t%f %f 0\n", -.45*leg_width, ((i+.9)/text_lines-.5)*leg_height);
599     printf("\t%f 0 0\n", .9*leg_width/strlen(vbuf));
600     printf("\t0 %f 0\n", -.9/text_lines*leg_height);
601     printf("\t.01 1 -.1\n");
602     }
603     printf("\nlscale alias legend_mat vellum\n");
604     printf("\nlegend_mat polygon legend\n0\n0\n12");
605     printf("\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n",
606     -.5*leg_width, .5*leg_height,
607     -.5*leg_width, -.5*leg_height,
608     .5*leg_width, -.5*leg_height,
609     .5*leg_width, .5*leg_height);
610     printf("\nvoid brighttext BSDFtitle\n3 helvet.fnt . BSDF\n0\n12\n");
611     printf("\t%f %f 0\n", -.25*leg_width, .7*leg_height);
612     printf("\t%f 0 0\n", .4/4.*leg_width);
613     printf("\t0 %f 0\n", -.1*leg_height);
614     printf("\t.01 1 -.1\n");
615     printf("\nBSDFtitle alias title_mat vellum\n");
616     printf("\ntitle_mat polygon title\n0\n0\n12");
617     printf("\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n",
618     -.3*leg_width, .75*leg_height,
619     -.3*leg_width, .55*leg_height,
620     .3*leg_width, .55*leg_height,
621     .3*leg_width, .75*leg_height);
622     if (!bsdf_name[0])
623     return;
624     printf("\nvoid brighttext BSDFname\n3 helvet.fnt . \"%s\"\n0\n12\n", bsdf_name);
625     printf("\t%f %f 0\n", -.95*leg_width, -.6*leg_height);
626     printf("\t%f 0 0\n", .4/strlen(bsdf_name)*leg_width);
627     printf("\t0 %f 0\n", -.1*leg_height);
628     printf("\t.01 1 -.1\n");
629     printf("\nBSDFname alias name_mat vellum\n");
630     printf("\nname_mat polygon name\n0\n0\n12");
631     printf("\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n\t%f %f 0\n",
632     -leg_width, -.55*leg_height,
633     -leg_width, -.75*leg_height,
634     leg_width, -.75*leg_height,
635     leg_width, -.55*leg_height);
636     }
637    
638     /* Convert MGF to Radiance in output */
639     static void
640     convert_mgf(const char *mgfdata)
641     {
642     int len = strlen(mgfdata);
643     char mgfn[128];
644     char radfn[128];
645     char cmdbuf[256];
646     float xmin, xmax, ymin, ymax, zmin, zmax;
647     double max_dim;
648     int fd;
649     FILE *fp;
650    
651     if (!len) return;
652     strcpy(mgfn, tfile_name("geom", ".mgf", 0));
653     fd = open(mgfn, O_WRONLY|O_CREAT, 0666);
654     if (fd < 0 || write(fd, mgfdata, len) != len) {
655     fprintf(stderr, "%s: cannot write file '%s'\n",
656     progname, mgfn);
657     return;
658     }
659     close(fd);
660     strcpy(radfn, tfile_name("geom", ".rad", 0));
661     sprintf(cmdbuf, "mgf2rad %s > %s", mgfn, radfn);
662     if (!run_cmd(cmdbuf))
663     return;
664     sprintf(cmdbuf, "getbbox -w -h %s", radfn);
665     if ((fp = popen(cmdbuf, "r")) == NULL ||
666     fscanf(fp, "%f %f %f %f %f %f",
667     &xmin, &xmax, &ymin, &ymax, &zmin, &zmax) != 6
668     || pclose(fp) < 0) {
669     fprintf(stderr, "%s: error reading from command: %s\n",
670     progname, cmdbuf);
671     return;
672     }
673     max_dim = ymax - ymin;
674     if (xmax - xmin > max_dim)
675     max_dim = xmax - xmin;
676     if (front_comp) {
677     printf("\n# BSDF system geometry (front view)\n");
678     sprintf(cmdbuf, "xform -t %f %f %f -s %f -t %f %f 0 %s",
679     -.5*(xmin+xmax), -.5*(ymin+ymax), -zmax,
680     1.5*sph_rad/max_dim,
681     -sph_xoffset, -2.5*sph_rad,
682     radfn);
683     if (!run_cmd(cmdbuf))
684     return;
685     }
686     if (back_comp) {
687     printf("\n# BSDF system geometry (back view)\n");
688     sprintf(cmdbuf, "xform -t %f %f %f -s %f -ry 180 -t %f %f 0 %s",
689     -.5*(xmin+xmax), -.5*(ymin+ymax), -zmin,
690     1.5*sph_rad/max_dim,
691     sph_xoffset, -2.5*sph_rad,
692     radfn);
693     if (!run_cmd(cmdbuf))
694     return;
695     }
696     }
697    
698     /* Check RBF input header line & get minimum BSDF value */
699     static int
700     rbf_headline(char *s, void *p)
701     {
702     char fmt[64];
703    
704     if (formatval(fmt, s)) {
705     if (strcmp(fmt, BSDFREP_FMT))
706     return(-1);
707     return(0);
708     }
709     if (!strncmp(s, "IO_SIDES=", 9)) {
710     sscanf(s+9, "%d %d", &input_orient, &output_orient);
711     if (input_orient == output_orient) {
712     if (input_orient > 0)
713     front_comp |= SDsampR;
714     else
715     back_comp |= SDsampR;
716     } else if (input_orient > 0)
717     front_comp |= SDsampT;
718     else
719     back_comp |= SDsampT;
720     return(0);
721     }
722     if (!strncmp(s, "BSDFMIN=", 8)) {
723     sscanf(s+8, "%lf", &bsdf_min);
724     if (bsdf_min < overall_min)
725     overall_min = bsdf_min;
726     return(0);
727     }
728     return(0);
729     }
730 greg 2.1
731 greg 2.16 /* Produce a Radiance model plotting the given BSDF representation */
732 greg 2.1 int
733     main(int argc, char *argv[])
734     {
735 greg 2.4 int inpXML = -1;
736     SDData myBSDF;
737 greg 2.16 int n;
738 greg 2.4 /* check arguments */
739 greg 2.1 progname = argv[0];
740 greg 2.16 if (argc > 1 && (n = strlen(argv[1])-4) > 0) {
741 greg 2.4 if (!strcasecmp(argv[1]+n, ".xml"))
742     inpXML = 1;
743     else if (!strcasecmp(argv[1]+n, ".sir"))
744     inpXML = 0;
745     }
746 greg 2.16 if (inpXML < 0 || inpXML & (argc > 2)) {
747     fprintf(stderr, "Usage: %s bsdf.xml > output.rad\n", progname);
748     fprintf(stderr, " Or: %s hemi1.sir hemi2.sir .. > output.rad\n", progname);
749 greg 2.1 return(1);
750     }
751 greg 2.16 fputs("# ", stdout); /* copy our command */
752     printargs(argc, argv, stdout);
753     /* evaluate BSDF */
754 greg 2.4 if (inpXML) {
755     SDclearBSDF(&myBSDF, argv[1]);
756     if (SDreportError(SDloadFile(&myBSDF, argv[1]), stderr))
757     return(1);
758 greg 2.16 if (myBSDF.rf != NULL) front_comp |= SDsampR;
759     if (myBSDF.tf != NULL) front_comp |= SDsampT;
760     if (myBSDF.rb != NULL) back_comp |= SDsampR;
761     if (myBSDF.tb != NULL) back_comp |= SDsampT;
762     if (!front_comp & !back_comp) {
763     fprintf(stderr, "%s: nothing to plot in '%s'\n",
764 greg 2.4 progname, argv[1]);
765     return(1);
766     }
767 greg 2.16 if (front_comp & SDsampR && myBSDF.rLambFront.cieY < overall_min*PI)
768     overall_min = myBSDF.rLambFront.cieY/PI;
769     if (back_comp & SDsampR && myBSDF.rLambBack.cieY < overall_min*PI)
770     overall_min = myBSDF.rLambBack.cieY/PI;
771     if ((front_comp|back_comp) & SDsampT &&
772     myBSDF.tLamb.cieY < overall_min*PI)
773     overall_min = myBSDF.tLamb.cieY/PI;
774     set_minlog();
775     if (!build_wBSDF(&myBSDF))
776 greg 2.9 return(1);
777 greg 2.16 if (myBSDF.matn[0])
778     strcpy(bsdf_name, myBSDF.matn);
779 greg 2.1 else
780 greg 2.16 strcpy(bsdf_name, myBSDF.name);
781     strcpy(bsdf_manuf, myBSDF.makr);
782     put_matBSDF(argv[1]);
783     } else {
784     FILE *fp;
785     for (n = 1; n < argc; n++) {
786     fp = fopen(argv[n], "rb");
787     if (fp == NULL) {
788     fprintf(stderr, "%s: cannot open BSDF interpolant '%s'\n",
789     progname, argv[n]);
790     return(1);
791     }
792     if (getheader(fp, rbf_headline, NULL) < 0) {
793     fprintf(stderr, "%s: bad BSDF interpolant '%s'\n",
794     progname, argv[n]);
795     return(1);
796 greg 2.2 }
797 greg 2.16 fclose(fp);
798 greg 2.2 }
799 greg 2.16 set_minlog();
800     for (n = 1; n < argc; n++) {
801     fp = fopen(argv[n], "rb");
802     if (!load_bsdf_rep(fp))
803     return(1);
804     fclose(fp);
805     if (!build_wRBF())
806     return(1);
807 greg 2.2 }
808 greg 2.16 put_matBSDF(NULL);
809 greg 2.1 }
810 greg 2.16 put_source(); /* before hemispheres & labels */
811     put_hemispheres();
812     put_scale();
813     if (inpXML && myBSDF.mgf)
814     convert_mgf(myBSDF.mgf);
815     if (!put_BSDFs())
816     return(1);
817     cleanup_tmp();
818 greg 2.1 return(0);
819     }