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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: cmbsdf.c,v 2.2 2014/01/20 22:18:29 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,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 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 addcolor(mp, diffBSDF);
45 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 cm_bsdf_recip(const COLOR diffBSDF, const SDMat *bsdf)
84 {
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 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 addcolor(mp, diffBSDF);
112 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 /* 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 CMATRIX *
141 cm_loadBTDF(char *fname)
142 {
143 CMATRIX *Tmat;
144 char *fpath;
145 int recip;
146 SDError ec;
147 SDData myBSDF;
148 SDSpectralDF *tdf;
149 COLOR diffBSDF;
150 /* 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 ccy2rgb(&myBSDF.tLamb.spec, myBSDF.tLamb.cieY/PI, diffBSDF);
161 recip = (myBSDF.tb == NULL);
162 tdf = recip ? myBSDF.tf : myBSDF.tb;
163 if (tdf == NULL) { /* no non-Lambertian transmission? */
164 SDfreeBSDF(&myBSDF);
165 return(cm_bsdf_Lamb(diffBSDF));
166 }
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 Tmat = recip ? cm_bsdf_recip(diffBSDF, (SDMat *)tdf->comp[0].dist)
173 : cm_bsdf(diffBSDF, (SDMat *)tdf->comp[0].dist);
174 /* free BSDF and return */
175 SDfreeBSDF(&myBSDF);
176 return(Tmat);
177 }