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, 1 month 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.10 static const char RCSid[] = "$Id: cmbsdf.c,v 2.9 2021/01/19 23:32:00 greg Exp $";
3 greg 2.1 #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 greg 2.3 cm_bsdf(const COLOR diffBSDF, const SDMat *bsdf)
19 greg 2.1 {
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 greg 2.7 float f = mBSDF_value(bsdf,r,c);
32 greg 2.1 COLORV *mp = cm_lval(cm,r,c);
33     /* check BSDF value */
34     if ((f <= 0) | (dom <= 0)) {
35     nneg += (f < -FTINY);
36 greg 2.3 setcolor(mp, .0f, .0f, .0f);
37     } else if (bsdf->chroma != NULL) {
38     C_COLOR cxy;
39 greg 2.7 c_decodeChroma(&cxy, mBSDF_chroma(bsdf,r,c));
40 greg 2.3 ccy2rgb(&cxy, f, mp);
41     } else
42     setcolor(mp, f, f, f);
43 greg 2.2 addcolor(mp, diffBSDF);
44 greg 2.1 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 greg 2.3 cm_bsdf_recip(const COLOR diffBSDF, const SDMat *bsdf)
83 greg 2.1 {
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 greg 2.7 float f = mBSDF_value(bsdf,ro,ri);
98 greg 2.1 COLORV *mp = cm_lval(cm,r,c);
99     /* check BSDF value */
100     if ((f <= 0) | (dom <= 0)) {
101     nneg += (f < -FTINY);
102 greg 2.3 setcolor(mp, .0f, .0f, .0f);
103     } else if (bsdf->chroma != NULL) {
104     C_COLOR cxy;
105 greg 2.7 c_decodeChroma(&cxy, mBSDF_chroma(bsdf,ro,ri));
106 greg 2.3 ccy2rgb(&cxy, f, mp);
107     } else
108     setcolor(mp, f, f, f);
109 greg 2.2 addcolor(mp, diffBSDF);
110 greg 2.1 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 greg 2.2 /* Return a Lambertian (diffuse) matrix */
123     static CMATRIX *
124     cm_bsdf_Lamb(const COLOR diffBSDF)
125     {
126 greg 2.8 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 greg 2.2
134 greg 2.8 for (c = 0; c < cm->ncols; c++) {
135     const double dom = io_getohm(c,abase);
136 greg 2.2 for (r = 0; r < cm->nrows; r++) {
137     COLORV *mp = cm_lval(cm,r,c);
138     copycolor(mp, diffBSDF);
139 greg 2.8 scalecolor(mp, dom);
140 greg 2.2 }
141 greg 2.8 }
142 greg 2.2 return(cm);
143     }
144    
145     /* Load and convert a matrix BTDF from the given XML file */
146 greg 2.1 CMATRIX *
147 greg 2.9 cm_loadBTDF(const char *fname)
148 greg 2.1 {
149     CMATRIX *Tmat;
150     int recip;
151     SDError ec;
152     SDData myBSDF;
153     SDSpectralDF *tdf;
154 greg 2.9 COLOR diffBTDF;
155 greg 2.6
156 greg 2.1 SDclearBSDF(&myBSDF, fname); /* load XML and check type */
157 greg 2.6 ec = SDloadFile(&myBSDF, fname);
158 greg 2.1 if (ec)
159     error(USER, transSDError(ec));
160     recip = (myBSDF.tb == NULL);
161 greg 2.10 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 greg 2.1 tdf = recip ? myBSDF.tf : myBSDF.tb;
166     if (tdf == NULL) { /* no non-Lambertian transmission? */
167     SDfreeBSDF(&myBSDF);
168 greg 2.9 return(cm_bsdf_Lamb(diffBTDF));
169 greg 2.1 }
170     if (tdf->ncomp != 1 || tdf->comp[0].func != &SDhandleMtx) {
171 greg 2.6 sprintf(errmsg, "unsupported BSDF '%s'", fname);
172 greg 2.1 error(USER, errmsg);
173     }
174     /* convert BTDF to matrix */
175 greg 2.9 Tmat = recip ? cm_bsdf_recip(diffBTDF, (SDMat *)tdf->comp[0].dist)
176     : cm_bsdf(diffBTDF, (SDMat *)tdf->comp[0].dist);
177 greg 2.1 /* free BSDF and return */
178     SDfreeBSDF(&myBSDF);
179     return(Tmat);
180     }
181 greg 2.9
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     }