ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/cmbsdf.c
Revision: 2.10
Committed: Sat Mar 27 17:50:18 2021 UTC (3 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.9: +5 -2 lines
Log Message:
fix: Allow different front/back diffuse reflectance in BSDF library

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: cmbsdf.c,v 2.9 2021/01/19 23:32:00 greg Exp $";
3 #endif
4 /*
5 * Load and convert BSDF into color coefficient matrix representation.
6 *
7 * G. Ward
8 */
9
10 #include "standard.h"
11 #include "cmatrix.h"
12 #include "paths.h"
13 #include "bsdf.h"
14 #include "bsdf_m.h"
15
16 /* Convert a BSDF to our matrix representation */
17 static CMATRIX *
18 cm_bsdf(const COLOR diffBSDF, const SDMat *bsdf)
19 {
20 CMATRIX *cm = cm_alloc(bsdf->nout, bsdf->ninc);
21 int nbadohm = 0;
22 int nneg = 0;
23 int r, c;
24 /* loop over incident angles */
25 for (c = 0; c < cm->ncols; c++) {
26 const double dom = mBSDF_incohm(bsdf,c);
27 /* projected solid angle */
28 nbadohm += (dom <= 0);
29
30 for (r = 0; r < cm->nrows; r++) {
31 float f = mBSDF_value(bsdf,r,c);
32 COLORV *mp = cm_lval(cm,r,c);
33 /* check BSDF value */
34 if ((f <= 0) | (dom <= 0)) {
35 nneg += (f < -FTINY);
36 setcolor(mp, .0f, .0f, .0f);
37 } else if (bsdf->chroma != NULL) {
38 C_COLOR cxy;
39 c_decodeChroma(&cxy, mBSDF_chroma(bsdf,r,c));
40 ccy2rgb(&cxy, f, mp);
41 } else
42 setcolor(mp, f, f, f);
43 addcolor(mp, diffBSDF);
44 scalecolor(mp, dom);
45 }
46 }
47 if (nneg | nbadohm) {
48 sprintf(errmsg,
49 "BTDF has %d negatives and %d bad incoming solid angles",
50 nneg, nbadohm);
51 error(WARNING, errmsg);
52 }
53 return(cm);
54 }
55
56 /* Convert between input and output indices for reciprocity */
57 static int
58 recip_out_from_in(const SDMat *bsdf, int in_recip)
59 {
60 FVECT v;
61
62 if (!mBSDF_incvec(v, bsdf, in_recip+.5))
63 return(in_recip); /* XXX should be error! */
64 v[2] = -v[2];
65 return(mBSDF_outndx(bsdf, v));
66 }
67
68 /* Convert between output and input indices for reciprocity */
69 static int
70 recip_in_from_out(const SDMat *bsdf, int out_recip)
71 {
72 FVECT v;
73
74 if (!mBSDF_outvec(v, bsdf, out_recip+.5))
75 return(out_recip); /* XXX should be error! */
76 v[2] = -v[2];
77 return(mBSDF_incndx(bsdf, v));
78 }
79
80 /* Convert a BSDF to our matrix representation, applying reciprocity */
81 static CMATRIX *
82 cm_bsdf_recip(const COLOR diffBSDF, const SDMat *bsdf)
83 {
84 CMATRIX *cm = cm_alloc(bsdf->ninc, bsdf->nout);
85 int nbadohm = 0;
86 int nneg = 0;
87 int r, c;
88 /* loop over incident angles */
89 for (c = 0; c < cm->ncols; c++) {
90 const int ro = recip_out_from_in(bsdf,c);
91 const double dom = mBSDF_outohm(bsdf,ro);
92 /* projected solid angle */
93 nbadohm += (dom <= 0);
94
95 for (r = 0; r < cm->nrows; r++) {
96 const int ri = recip_in_from_out(bsdf,r);
97 float f = mBSDF_value(bsdf,ro,ri);
98 COLORV *mp = cm_lval(cm,r,c);
99 /* check BSDF value */
100 if ((f <= 0) | (dom <= 0)) {
101 nneg += (f < -FTINY);
102 setcolor(mp, .0f, .0f, .0f);
103 } else if (bsdf->chroma != NULL) {
104 C_COLOR cxy;
105 c_decodeChroma(&cxy, mBSDF_chroma(bsdf,ro,ri));
106 ccy2rgb(&cxy, f, mp);
107 } else
108 setcolor(mp, f, f, f);
109 addcolor(mp, diffBSDF);
110 scalecolor(mp, dom);
111 }
112 }
113 if (nneg | nbadohm) {
114 sprintf(errmsg,
115 "BTDF has %d negatives and %d bad incoming solid angles",
116 nneg, nbadohm);
117 error(WARNING, errmsg);
118 }
119 return(cm);
120 }
121
122 /* Return a Lambertian (diffuse) matrix */
123 static CMATRIX *
124 cm_bsdf_Lamb(const COLOR diffBSDF)
125 {
126 CMATRIX *cm = cm_alloc(145, 145); /* this is a hack */
127 ANGLE_BASIS *abase = abase_list;
128 int r, c;
129
130 while (abase->nangles != cm->nrows)
131 if (++abase >= abase_list+nabases)
132 error(INTERNAL, "Code error in cm_bsdf_Lamb()");
133
134 for (c = 0; c < cm->ncols; c++) {
135 const double dom = io_getohm(c,abase);
136 for (r = 0; r < cm->nrows; r++) {
137 COLORV *mp = cm_lval(cm,r,c);
138 copycolor(mp, diffBSDF);
139 scalecolor(mp, dom);
140 }
141 }
142 return(cm);
143 }
144
145 /* Load and convert a matrix BTDF from the given XML file */
146 CMATRIX *
147 cm_loadBTDF(const char *fname)
148 {
149 CMATRIX *Tmat;
150 int recip;
151 SDError ec;
152 SDData myBSDF;
153 SDSpectralDF *tdf;
154 COLOR diffBTDF;
155
156 SDclearBSDF(&myBSDF, fname); /* load XML and check type */
157 ec = SDloadFile(&myBSDF, fname);
158 if (ec)
159 error(USER, transSDError(ec));
160 recip = (myBSDF.tb == NULL);
161 if (recip)
162 ccy2rgb(&myBSDF.tLambFront.spec, myBSDF.tLambFront.cieY/PI, diffBTDF);
163 else
164 ccy2rgb(&myBSDF.tLambBack.spec, myBSDF.tLambBack.cieY/PI, diffBTDF);
165 tdf = recip ? myBSDF.tf : myBSDF.tb;
166 if (tdf == NULL) { /* no non-Lambertian transmission? */
167 SDfreeBSDF(&myBSDF);
168 return(cm_bsdf_Lamb(diffBTDF));
169 }
170 if (tdf->ncomp != 1 || tdf->comp[0].func != &SDhandleMtx) {
171 sprintf(errmsg, "unsupported BSDF '%s'", fname);
172 error(USER, errmsg);
173 }
174 /* convert BTDF to matrix */
175 Tmat = recip ? cm_bsdf_recip(diffBTDF, (SDMat *)tdf->comp[0].dist)
176 : cm_bsdf(diffBTDF, (SDMat *)tdf->comp[0].dist);
177 /* free BSDF and return */
178 SDfreeBSDF(&myBSDF);
179 return(Tmat);
180 }
181
182 /* Load and convert a matrix BRDF from the given XML file */
183 CMATRIX *
184 cm_loadBRDF(const char *fname, int backside)
185 {
186 CMATRIX *Rmat;
187 SDError ec;
188 SDData myBSDF;
189 SDSpectralDF *rdf;
190 COLOR diffBRDF;
191
192 SDclearBSDF(&myBSDF, fname); /* load XML and check type */
193 ec = SDloadFile(&myBSDF, fname);
194 if (ec)
195 error(USER, transSDError(ec));
196 if (backside) {
197 ccy2rgb(&myBSDF.rLambBack.spec, myBSDF.rLambBack.cieY/PI, diffBRDF);
198 rdf = myBSDF.rb;
199 } else {
200 ccy2rgb(&myBSDF.rLambFront.spec, myBSDF.rLambFront.cieY/PI, diffBRDF);
201 rdf = myBSDF.rf;
202 }
203 if (rdf == NULL) { /* no non-Lambertian reflection? */
204 SDfreeBSDF(&myBSDF);
205 return(cm_bsdf_Lamb(diffBRDF));
206 }
207 if (rdf->ncomp != 1 || rdf->comp[0].func != &SDhandleMtx) {
208 sprintf(errmsg, "unsupported BSDF '%s'", fname);
209 error(USER, errmsg);
210 }
211 /* convert BRDF to matrix */
212 Rmat = cm_bsdf(diffBRDF, (SDMat *)rdf->comp[0].dist);
213 /* free BSDF and return */
214 SDfreeBSDF(&myBSDF);
215 return(Rmat);
216 }