ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/checkBSDF.c
Revision: 2.1
Committed: Tue Dec 14 02:33:18 2021 UTC (2 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
feat(checkBSDF): created new checkBSDF tool to check XML data reciprocity

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * checkBSDF.c
6 *
7 * Load BSDF XML file and check Helmholtz reciprocity
8 */
9
10 #define _USE_MATH_DEFINES
11 #include <math.h>
12 #include "rtio.h"
13 #include "bsdf.h"
14 #include "bsdf_m.h"
15 #include "bsdf_t.h"
16
17 #define F_IN_COLOR 0x1
18 #define F_ISOTROPIC 0x2
19 #define F_MATRIX 0x4
20 #define F_TTREE 0x8
21
22 /* Figure out BSDF type (and optionally determine if in color) */
23 const char *
24 getBSDFtype(const SDData *bsdf, int *flags)
25 {
26 const SDSpectralDF *df = bsdf->tb;
27
28 if (flags) *flags = 0;
29 if (!df) df = bsdf->tf;
30 if (!df) df = bsdf->rf;
31 if (!df) df = bsdf->rb;
32 if (!df) return "Pure_Lambertian";
33 if (df->comp[0].func == &SDhandleMtx) {
34 const SDMat *m = (const SDMat *)df->comp[0].dist;
35 if (flags) {
36 *flags |= F_MATRIX;
37 *flags |= F_IN_COLOR*(m->chroma != NULL);
38 }
39 switch (m->ninc) {
40 case 145:
41 return "Klems_Full";
42 case 73:
43 return "Klems_Half";
44 case 41:
45 return "Klems_Quarter";
46 }
47 return "Unknown_Matrix";
48 }
49 if (df->comp[0].func == &SDhandleTre) {
50 const SDTre *t = (const SDTre *)df->comp[0].dist;
51 if (flags) {
52 *flags |= F_TTREE;
53 *flags |= F_IN_COLOR*(t->stc[1] != NULL);
54 }
55 switch (t->stc[0]->ndim) {
56 case 4:
57 return "Anisotropic_Tensor_Tree";
58 case 3:
59 if (flags) *flags |= F_ISOTROPIC;
60 return "Isotropic_Tensor_Tree";
61 }
62 return "Unknown_Tensor_Tree";
63 }
64 return "Unknown";
65 }
66
67 /* Report details related to one hemisphere distribution */
68 void
69 detailComponent(const char *nm, const SDValue *lamb, const SDSpectralDF *df)
70 {
71 printf("%s\t%4.1f %4.1f %4.1f\t\t", nm, 100.*lamb->cieY*lamb->spec.cx/lamb->spec.cy,
72 100.*lamb->cieY,
73 100.*lamb->cieY*(1.f - lamb->spec.cx - lamb->spec.cy)/lamb->spec.cy);
74 if (df)
75 printf("%5.1f%%\t\t%.2f deg\n", 100.*df->maxHemi,
76 sqrt(df->minProjSA/M_PI)*(360./M_PI));
77 else
78 puts("0%\t\t180");
79 }
80
81 /* Report reciprocity errors for the given directions */
82 void
83 checkReciprocity(const char *nm, const int side1, const int side2,
84 const SDData *bsdf, const int fl)
85 {
86 const SDSpectralDF *df = bsdf->tf;
87 double emin=FHUGE, emax=0, esum=0;
88 int ntested=0;
89 int ec;
90
91 if (side1 == side2) {
92 df = (side1 > 0) ? bsdf->rf : bsdf->rb;
93 if (!df) goto nothing2do;
94 } else if (!bsdf->tf | !bsdf->tb)
95 goto nothing2do;
96
97 if (fl & F_MATRIX) { /* special case for matrix BSDF */
98 const SDMat *m = (const SDMat *)df->comp[0].dist;
99 int i = m->ninc;
100 FVECT vin, vout;
101 double rerr;
102 SDValue vrev;
103 while (i--) {
104 int o = m->nout;
105 if (!mBSDF_incvec(vin, m, i+.5))
106 continue;
107 while (o--) {
108 if (!mBSDF_outvec(vout, m, o+.5))
109 continue;
110 rerr = mBSDF_value(m, o, i);
111 if (rerr <= FTINY)
112 continue;
113 if (SDreportError( SDevalBSDF(&vrev, vout, vin, bsdf), stderr))
114 return;
115 rerr = 100.*fabs(rerr - vrev.cieY)/rerr;
116 if (rerr < emin) emin = rerr;
117 if (rerr > emax) emax = rerr;
118 esum += rerr;
119 ++ntested;
120 }
121 }
122 } else {
123 }
124 if (ntested) {
125 printf("%s\t%.1f\t%.1f\t%.1f\n", nm, emin, esum/(double)ntested, emax);
126 return;
127 }
128 nothing2do:
129 printf("%s\t0\t0\t0\n", nm);
130 }
131
132 /* Report on the given BSDF XML file */
133 int
134 checkXML(char *fname)
135 {
136 int flags;
137 SDError ec;
138 SDData myBSDF;
139 char *pth;
140
141 printf("File: '%s'\n", fname);
142 SDclearBSDF(&myBSDF, fname);
143 pth = getpath(fname, getrlibpath(), R_OK);
144 if (!pth) {
145 fprintf(stderr, "Cannot find file '%s'\n", fname);
146 return 0;
147 }
148 ec = SDloadFile(&myBSDF, pth);
149 if (ec) goto err;
150 printf("Manufacturer: '%s'\n", myBSDF.makr);
151 printf("BSDF Name: '%s'\n", myBSDF.matn);
152 printf("Dimensions (W x H x Thickness): %g x %g x %g cm\n", 100.*myBSDF.dim[0],
153 100.*myBSDF.dim[1], 100.*myBSDF.dim[2]);
154 printf("Type: %s\n", getBSDFtype(&myBSDF, &flags));
155 printf("Color: %d\n", (flags & F_IN_COLOR) != 0);
156 printf("Has Geometry: %d\n", (myBSDF.mgf != NULL));
157 puts("Component\tLambertian XYZ %\tMax. Dir\tMin. Angle");
158 detailComponent("Internal Refl", &myBSDF.rLambFront, myBSDF.rf);
159 detailComponent("External Refl", &myBSDF.rLambBack, myBSDF.rb);
160 detailComponent("Int->Ext Trans", &myBSDF.tLambFront, myBSDF.tf);
161 detailComponent("Ext->Int Trans", &myBSDF.tLambBack, myBSDF.tb);
162 puts("Component\tReciprocity Error (min/avg/max %)");
163 checkReciprocity("Front Refl", 1, 1, &myBSDF, flags);
164 checkReciprocity("Back Refl", -1, -1, &myBSDF, flags);
165 checkReciprocity("Transmission", -1, 1, &myBSDF, flags);
166 SDfreeBSDF(&myBSDF);
167 return 1;
168 err:
169 SDreportError(ec, stderr);
170 SDfreeBSDF(&myBSDF);
171 return 0;
172 }
173
174 int
175 main(int argc, char *argv[])
176 {
177 int i;
178
179 if (argc < 2) {
180 fprintf(stderr, "Usage: %s bsdf.xml ..\n", argv[0]);
181 return 1;
182 }
183 for (i = 1; i < argc; i++) {
184 puts("=====================================================");
185 if (!checkXML(argv[i]))
186 return 1;
187 }
188 return 0;
189 }