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, 2 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: cmbsdf.c,v 2.1 2014/01/20 21:29:04 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 COLOR specCol, 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,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 addcolor(mp, diffBSDF);
41 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 cm_bsdf_recip(const COLOR diffBSDF, const COLOR specCol, const SDMat *bsdf)
80 {
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 addcolor(mp, diffBSDF);
104 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 /* 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 CMATRIX *
133 cm_loadBTDF(char *fname)
134 {
135 CMATRIX *Tmat;
136 char *fpath;
137 int recip;
138 SDError ec;
139 SDData myBSDF;
140 SDSpectralDF *tdf;
141 COLOR diffBSDF, specCol;
142 /* 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 ccy2rgb(&myBSDF.tLamb.spec, myBSDF.tLamb.cieY/PI, diffBSDF);
153 recip = (myBSDF.tb == NULL);
154 tdf = recip ? myBSDF.tf : myBSDF.tb;
155 if (tdf == NULL) { /* no non-Lambertian transmission? */
156 SDfreeBSDF(&myBSDF);
157 return(cm_bsdf_Lamb(diffBSDF));
158 }
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 Tmat = recip ? cm_bsdf_recip(diffBSDF, specCol, (SDMat *)tdf->comp[0].dist)
166 : cm_bsdf(diffBSDF, specCol, (SDMat *)tdf->comp[0].dist);
167 /* free BSDF and return */
168 SDfreeBSDF(&myBSDF);
169 return(Tmat);
170 }