ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/cmbsdf.c
Revision: 2.3
Committed: Fri Apr 17 01:47:03 2015 UTC (9 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +22 -15 lines
Log Message:
Add color BTDF support

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.3 static const char RCSid[] = "$Id: cmbsdf.c,v 2.2 2014/01/20 22:18:29 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     float f = mBSDF_value(bsdf,c,r);
32     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     c_decodeChroma(&cxy,
40     bsdf->chroma[r*bsdf->ninc + c]);
41     ccy2rgb(&cxy, f, mp);
42     } else
43     setcolor(mp, f, f, f);
44 greg 2.2 addcolor(mp, diffBSDF);
45 greg 2.1 scalecolor(mp, dom);
46     }
47     }
48     if (nneg | nbadohm) {
49     sprintf(errmsg,
50     "BTDF has %d negatives and %d bad incoming solid angles",
51     nneg, nbadohm);
52     error(WARNING, errmsg);
53     }
54     return(cm);
55     }
56    
57     /* Convert between input and output indices for reciprocity */
58     static int
59     recip_out_from_in(const SDMat *bsdf, int in_recip)
60     {
61     FVECT v;
62    
63     if (!mBSDF_incvec(v, bsdf, in_recip+.5))
64     return(in_recip); /* XXX should be error! */
65     v[2] = -v[2];
66     return(mBSDF_outndx(bsdf, v));
67     }
68    
69     /* Convert between output and input indices for reciprocity */
70     static int
71     recip_in_from_out(const SDMat *bsdf, int out_recip)
72     {
73     FVECT v;
74    
75     if (!mBSDF_outvec(v, bsdf, out_recip+.5))
76     return(out_recip); /* XXX should be error! */
77     v[2] = -v[2];
78     return(mBSDF_incndx(bsdf, v));
79     }
80    
81     /* Convert a BSDF to our matrix representation, applying reciprocity */
82     static CMATRIX *
83 greg 2.3 cm_bsdf_recip(const COLOR diffBSDF, const SDMat *bsdf)
84 greg 2.1 {
85     CMATRIX *cm = cm_alloc(bsdf->ninc, bsdf->nout);
86     int nbadohm = 0;
87     int nneg = 0;
88     int r, c;
89     /* loop over incident angles */
90     for (c = 0; c < cm->ncols; c++) {
91     const int ro = recip_out_from_in(bsdf,c);
92     const double dom = mBSDF_outohm(bsdf,ro);
93     /* projected solid angle */
94     nbadohm += (dom <= 0);
95    
96     for (r = 0; r < cm->nrows; r++) {
97     const int ri = recip_in_from_out(bsdf,r);
98     float f = mBSDF_value(bsdf,ri,ro);
99     COLORV *mp = cm_lval(cm,r,c);
100     /* check BSDF value */
101     if ((f <= 0) | (dom <= 0)) {
102     nneg += (f < -FTINY);
103 greg 2.3 setcolor(mp, .0f, .0f, .0f);
104     } else if (bsdf->chroma != NULL) {
105     C_COLOR cxy;
106     c_decodeChroma(&cxy,
107     bsdf->chroma[ro*bsdf->ninc + ri]);
108     ccy2rgb(&cxy, f, mp);
109     } else
110     setcolor(mp, f, f, f);
111 greg 2.2 addcolor(mp, diffBSDF);
112 greg 2.1 scalecolor(mp, dom);
113     }
114     }
115     if (nneg | nbadohm) {
116     sprintf(errmsg,
117     "BTDF has %d negatives and %d bad incoming solid angles",
118     nneg, nbadohm);
119     error(WARNING, errmsg);
120     }
121     return(cm);
122     }
123    
124 greg 2.2 /* Return a Lambertian (diffuse) matrix */
125     static CMATRIX *
126     cm_bsdf_Lamb(const COLOR diffBSDF)
127     {
128     CMATRIX *cm = cm_alloc(145, 145); /* this is a hack */
129     int r, c;
130    
131     for (c = 0; c < cm->ncols; c++)
132     for (r = 0; r < cm->nrows; r++) {
133     COLORV *mp = cm_lval(cm,r,c);
134     copycolor(mp, diffBSDF);
135     }
136     return(cm);
137     }
138    
139     /* Load and convert a matrix BTDF from the given XML file */
140 greg 2.1 CMATRIX *
141 greg 2.2 cm_loadBTDF(char *fname)
142 greg 2.1 {
143     CMATRIX *Tmat;
144     char *fpath;
145     int recip;
146     SDError ec;
147     SDData myBSDF;
148     SDSpectralDF *tdf;
149 greg 2.3 COLOR diffBSDF;
150 greg 2.1 /* find path to BSDF file */
151     fpath = getpath(fname, getrlibpath(), R_OK);
152     if (fpath == NULL) {
153     sprintf(errmsg, "cannot find BSDF file '%s'", fname);
154     error(USER, errmsg);
155     }
156     SDclearBSDF(&myBSDF, fname); /* load XML and check type */
157     ec = SDloadFile(&myBSDF, fpath);
158     if (ec)
159     error(USER, transSDError(ec));
160 greg 2.2 ccy2rgb(&myBSDF.tLamb.spec, myBSDF.tLamb.cieY/PI, diffBSDF);
161 greg 2.1 recip = (myBSDF.tb == NULL);
162     tdf = recip ? myBSDF.tf : myBSDF.tb;
163     if (tdf == NULL) { /* no non-Lambertian transmission? */
164     SDfreeBSDF(&myBSDF);
165 greg 2.2 return(cm_bsdf_Lamb(diffBSDF));
166 greg 2.1 }
167     if (tdf->ncomp != 1 || tdf->comp[0].func != &SDhandleMtx) {
168     sprintf(errmsg, "unsupported BSDF '%s'", fpath);
169     error(USER, errmsg);
170     }
171     /* convert BTDF to matrix */
172 greg 2.3 Tmat = recip ? cm_bsdf_recip(diffBSDF, (SDMat *)tdf->comp[0].dist)
173     : cm_bsdf(diffBSDF, (SDMat *)tdf->comp[0].dist);
174 greg 2.1 /* free BSDF and return */
175     SDfreeBSDF(&myBSDF);
176     return(Tmat);
177     }