ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/cmbsdf.c
Revision: 2.2
Committed: Mon Jan 20 22:18:29 2014 UTC (10 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad4R2, rad4R2P1
Changes since 2.1: +27 -16 lines
Log Message:
Fixed improper handling of diffuse transmission matrix

File Contents

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