ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum4.c
Revision: 2.4
Committed: Wed Dec 5 05:02:58 2007 UTC (17 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +17 -27 lines
Log Message:
Fixed resampling coefficients

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mkillum4.c,v 2.3 2007/11/21 18:51:05 greg Exp $";
3 #endif
4 /*
5 * Routines for handling BSDF data within mkillum
6 */
7
8 #include "mkillum.h"
9 #include "paths.h"
10 #include "random.h"
11 #include "ezxml.h"
12
13
14 struct BSDF_data *
15 load_BSDF( /* load BSDF data from file */
16 char *fname
17 )
18 {
19 char *path;
20 ezxml_t fl, wld, wdb;
21 struct BSDF_data *dp;
22
23 path = getpath(fname, getrlibpath(), R_OK);
24 if (path == NULL) {
25 sprintf(errmsg, "cannot find BSDF file \"%s\"", fname);
26 error(WARNING, errmsg);
27 return(NULL);
28 }
29 fl = ezxml_parse_file(path);
30 if (fl == NULL) {
31 sprintf(errmsg, "cannot open BSDF \"%s\"", path);
32 error(WARNING, errmsg);
33 return(NULL);
34 }
35 dp = (struct BSDF_data *)malloc(sizeof(struct BSDF_data));
36 if (dp == NULL)
37 goto memerr;
38 for (wld = ezxml_child(fl, "WavelengthData");
39 fl != NULL; fl = fl->next) {
40 if (strcmp(ezxml_child(wld, "Wavelength")->txt, "Visible"))
41 continue;
42 wdb = ezxml_child(wld, "WavelengthDataBlock");
43 if (wdb == NULL) continue;
44 if (strcmp(ezxml_child(wdb, "WavelengthDataDirection")->txt,
45 "Transmission Front"))
46 continue;
47 }
48 /* etc... */
49 ezxml_free(fl);
50 return(dp);
51 memerr:
52 error(SYSTEM, "out of memory in load_BSDF");
53 return NULL; /* pro forma return */
54 }
55
56
57 void
58 free_BSDF( /* free BSDF data structure */
59 struct BSDF_data *b
60 )
61 {
62 if (b == NULL)
63 return;
64 free(b->inc_dir);
65 free(b->inc_rad);
66 free(b->out_dir);
67 free(b->out_rad);
68 free(b->bsdf);
69 free(b);
70 }
71
72
73 void
74 r_BSDF_incvec( /* compute random input vector at given location */
75 FVECT v,
76 struct BSDF_data *b,
77 int i,
78 double rv,
79 MAT4 xm
80 )
81 {
82 FVECT pert;
83 double rad;
84 int j;
85
86 getBSDF_incvec(v, b, i);
87 rad = getBSDF_incrad(b, i);
88 multisamp(pert, 3, rv);
89 for (j = 0; j < 3; j++)
90 v[j] += rad*(2.*pert[j] - 1.);
91 if (xm != NULL)
92 multv3(v, v, xm);
93 normalize(v);
94 }
95
96
97 void
98 r_BSDF_outvec( /* compute random output vector at given location */
99 FVECT v,
100 struct BSDF_data *b,
101 int o,
102 double rv,
103 MAT4 xm
104 )
105 {
106 FVECT pert;
107 double rad;
108 int j;
109
110 getBSDF_outvec(v, b, o);
111 rad = getBSDF_outrad(b, o);
112 multisamp(pert, 3, rv);
113 for (j = 0; j < 3; j++)
114 v[j] += rad*(2.*pert[j] - 1.);
115 if (xm != NULL)
116 multv3(v, v, xm);
117 normalize(v);
118 }
119
120
121 #define FEQ(a,b) ((a)-(b) <= 1e-7 && (b)-(a) <= 1e-7)
122
123 static int
124 addrot( /* compute rotation (x,y,z) => (xp,yp,zp) */
125 char *xfarg[],
126 FVECT xp,
127 FVECT yp,
128 FVECT zp
129 )
130 {
131 static char bufs[3][16];
132 int bn = 0;
133 char **xfp = xfarg;
134 double theta;
135
136 theta = atan2(yp[2], zp[2]);
137 if (!FEQ(theta,0.0)) {
138 *xfp++ = "-rx";
139 sprintf(bufs[bn], "%f", theta*(180./PI));
140 *xfp++ = bufs[bn++];
141 }
142 theta = asin(-xp[2]);
143 if (!FEQ(theta,0.0)) {
144 *xfp++ = "-ry";
145 sprintf(bufs[bn], " %f", theta*(180./PI));
146 *xfp++ = bufs[bn++];
147 }
148 theta = atan2(xp[1], xp[0]);
149 if (!FEQ(theta,0.0)) {
150 *xfp++ = "-rz";
151 sprintf(bufs[bn], "%f", theta*(180./PI));
152 *xfp++ = bufs[bn++];
153 }
154 *xfp = NULL;
155 return(xfp - xfarg);
156 }
157
158
159 int
160 getBSDF_xfm( /* compute transform for the given surface */
161 MAT4 xm,
162 FVECT nrm,
163 UpDir ud
164 )
165 {
166 char *xfargs[7];
167 XF myxf;
168 FVECT updir, xdest, ydest;
169
170 updir[0] = updir[1] = updir[2] = 0.;
171 switch (ud) {
172 case UDzneg:
173 updir[2] = -1.;
174 break;
175 case UDyneg:
176 updir[1] = -1.;
177 break;
178 case UDxneg:
179 updir[0] = -1.;
180 break;
181 case UDxpos:
182 updir[0] = 1.;
183 break;
184 case UDypos:
185 updir[1] = 1.;
186 break;
187 case UDzpos:
188 updir[2] = 1.;
189 break;
190 case UDunknown:
191 error(WARNING, "unspecified up direction");
192 return(0);
193 }
194 fcross(xdest, updir, nrm);
195 if (normalize(xdest) == 0.0)
196 return(0);
197 fcross(ydest, nrm, xdest);
198 xf(&myxf, addrot(xfargs, xdest, ydest, nrm), xfargs);
199 copymat4(xm, myxf.xfm);
200 return(1);
201 }
202
203
204 void
205 redistribute( /* pass distarr ray sums through BSDF */
206 struct BSDF_data *b,
207 int nalt,
208 int nazi,
209 FVECT u,
210 FVECT v,
211 FVECT w,
212 MAT4 xm
213 )
214 {
215 MAT4 mymat;
216 COLORV *outarr;
217 COLORV *cp, *csum;
218 uint16 *distcnt;
219 FVECT dv;
220 double wt0, wt1;
221 int i, j, o;
222 int cnt;
223 COLOR col;
224 /* allocate temporary memory */
225 outarr = (COLORV *)calloc(b->nout, sizeof(COLOR));
226 distcnt = (uint16 *)calloc(nalt*nazi, sizeof(uint16));
227 if ((outarr == NULL) | (distcnt == NULL))
228 error(SYSTEM, "out of memory in redistribute");
229 /* compose matrix */
230 for (i = 3; i--; ) {
231 mymat[i][0] = u[i];
232 mymat[i][1] = v[i];
233 mymat[i][2] = w[i];
234 mymat[i][3] = 0.;
235 }
236 mymat[3][0] = mymat[3][1] = mymat[3][2] = 0.;
237 mymat[3][3] = 1.;
238 if (xm != NULL)
239 multmat4(mymat, xm, mymat);
240 for (i = 3; i--; ) { /* make sure it's normalized */
241 wt0 = 1./sqrt( mymat[0][i]*mymat[0][i] +
242 mymat[1][i]*mymat[1][i] +
243 mymat[2][i]*mymat[2][i] );
244 for (j = 3; j--; )
245 mymat[j][i] *= wt0;
246 }
247 /* pass through BSDF */
248 for (i = b->ninc; i--; ) {
249 getBSDF_incvec(dv, b, i);
250 multv3(dv, dv, mymat);
251 wt0 = getBSDF_incrad(b, i);
252 wt0 *= PI*wt0 * dv[2]; /* solid_angle*cosine(theta) */
253 for (o = b->nout; o--; ) {
254 cp = &distarr[3*i];
255 csum = &outarr[3*o];
256 wt1 = wt0 * BSDF_data(b,i,o);
257 copycolor(col, cp);
258 scalecolor(col, wt1);
259 addcolor(csum, col);
260 }
261 }
262 newdist(nalt*nazi); /* resample distribution */
263 for (o = b->nout; o--; ) {
264 getBSDF_outvec(dv, b, o);
265 multv3(dv, dv, mymat);
266 j = (.5 + atan2(dv[1],dv[0])*(.5/PI))*nazi + .5;
267 if (j >= nazi) j = 0;
268 i = (0.9999 - dv[2]*dv[2])*nalt;
269 csum = &distarr[3*(i*nazi + j)];
270 cp = &outarr[3*o];
271 addcolor(csum, cp);
272 ++distcnt[i*nazi + j];
273 }
274 free(outarr);
275 /* fill in missing bits */
276 for (i = nalt; i--; )
277 for (j = nazi; j--; ) {
278 int ii, jj, alt, azi;
279 if (distcnt[i*nazi + j])
280 continue;
281 csum = &distarr[3*(i*nazi + j)];
282 setcolor(csum, 0., 0., 0.);
283 cnt = 0;
284 for (o = 0; !cnt; o++)
285 for (ii = -o; ii <= o; ii++) {
286 alt = i + ii;
287 if (alt < 0) continue;
288 if (alt >= nalt) break;
289 for (jj = -o; jj <= o; jj++) {
290 if (ii*ii + jj*jj != o*o)
291 continue;
292 azi = j + jj;
293 if (azi >= nazi) azi -= nazi;
294 else if (azi < 0) azi += nazi;
295 if (!distcnt[alt*nazi + azi])
296 continue;
297 cp = &distarr[3*(alt*nazi + azi)];
298 addcolor(csum, cp);
299 cnt += distcnt[alt*nazi + azi];
300 }
301 }
302 wt0 = 1./cnt;
303 scalecolor(csum, wt0);
304 }
305 /* finish averages */
306 for (i = nalt; i--; )
307 for (j = nazi; j--; ) {
308 if ((cnt = distcnt[i*nazi + j]) <= 1)
309 continue;
310 csum = &distarr[3*(i*nazi + j)];
311 wt0 = 1./cnt;
312 scalecolor(csum, wt0);
313 }
314 free(distcnt);
315 }