ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glaresrc.c
Revision: 2.4
Committed: Sat Feb 22 02:07:30 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.3: +6 -9 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Gather samples and compute glare sources.
6 */
7
8 #include "glare.h"
9 #include "linregr.h"
10
11 #define vcont(vd,vu) ((vu)-(vd)<=SEPS)
12 #define hcont(s1,s2) ((s1)->r-(s2)->l>=-SEPS&&(s2)->r-(s1)->l>=-SEPS)
13
14 struct source *curlist = NULL; /* current source list */
15 struct source *donelist = NULL; /* finished sources */
16
17
18 struct srcspan *
19 newspan(l, r, v, sb) /* allocate a new source span */
20 int l, r, v;
21 float *sb;
22 {
23 register struct srcspan *ss;
24 register int i;
25
26 ss = (struct srcspan *)malloc(sizeof(struct srcspan));
27 if (ss == NULL)
28 memerr("source spans");
29 ss->l = l;
30 ss->r = r;
31 ss->v = v;
32 ss->brsum = 0.0;
33 for (i = l; i < r; i++)
34 ss->brsum += sb[i+hsize];
35 return(ss);
36 }
37
38
39 analyze() /* analyze our scene */
40 {
41 int h, v;
42 int left;
43 float *spanbr;
44
45 spanbr = (float *)malloc((2*hsize+1)*sizeof(float));
46 if (spanbr == NULL)
47 memerr("view span brightness buffer");
48 for (v = vsize; v >= -vsize; v--) {
49 close_sources(v);
50 #ifndef DEBUG
51 if (verbose) {
52 fprintf(stderr, "%s: analyzing... %3ld%%\r",
53 progname, 100L*(vsize-v)/(2*vsize));
54 fflush(stderr);
55 }
56 #endif
57 getviewspan(v, spanbr);
58 left = hsize + 1;
59 for (h = -hsize; h <= hsize; h++) {
60 if (spanbr[h+hsize] < 0.0) { /* off view */
61 if (left < h) {
62 addsrcspan(newspan(left,h,v,spanbr));
63 left = hsize + 1;
64 }
65 continue;
66 }
67 if (spanbr[h+hsize] > threshold) { /* in source */
68 if (left > h)
69 left = h;
70 } else { /* out of source */
71 if (left < h) {
72 addsrcspan(newspan(left,h,v,spanbr));
73 left = hsize + 1;
74 }
75 addindirect(h, v, spanbr[h+hsize]);
76 }
77 }
78 if (left < h)
79 addsrcspan(newspan(left,h,v,spanbr));
80 }
81 free((void *)spanbr);
82 close_allsrcs();
83 }
84
85
86 addindirect(h, v, br) /* add brightness to indirect illuminances */
87 int h, v;
88 double br;
89 {
90 double tanb, d;
91 int hl;
92 register int i;
93
94 hl = hlim(v);
95 if (h <= -hl) { /* left region */
96 d = (double)(-h-hl)/sampdens;
97 if (d >= 1.0-FTINY)
98 return;
99 tanb = d/sqrt(1.0-d*d);
100 for (i = 0; i < nglardirs; i++) {
101 d = indirect[i].lcos - tanb*indirect[i].lsin;
102 if (d > 0.0) {
103 indirect[i].sum += d * br;
104 indirect[i].n += d;
105 }
106 }
107 return;
108 }
109 if (h >= hl) { /* right region */
110 d = (double)(-h+hl)/sampdens;
111 if (d <= -1.0+FTINY)
112 return;
113 tanb = d/sqrt(1.0-d*d);
114 for (i = 0; i < nglardirs; i++) {
115 d = indirect[i].rcos - tanb*indirect[i].rsin;
116 if (d > 0.0) {
117 indirect[i].sum += d * br;
118 indirect[i].n += d;
119 }
120 }
121 return;
122 }
123 /* central region */
124 for (i = 0; i < nglardirs; i++) {
125 d = cos(h_theta(h,v) - indirect[i].theta);
126 if (d > 0.0) {
127 indirect[i].sum += d * br;
128 indirect[i].n += d;
129 }
130 }
131 }
132
133
134 comp_thresh() /* compute glare threshold */
135 {
136 int h, v;
137 int nsamps;
138 double brsum, br;
139
140 if (verbose)
141 fprintf(stderr, "%s: computing glare threshold...\n",
142 progname);
143 brsum = 0.0;
144 nsamps = 0;
145 for (v = vsize; v >= -vsize; v -= TSAMPSTEP) {
146 for (h = -hsize; h <= hsize; h += TSAMPSTEP) {
147 if ((br = getviewpix(h, v)) < 0.0)
148 continue;
149 brsum += br;
150 nsamps++;
151 }
152 }
153 if (nsamps == 0) {
154 fprintf(stderr, "%s: no viewable scene!\n", progname);
155 exit(1);
156 }
157 threshold = GLAREBR * brsum / nsamps;
158 if (threshold <= FTINY) {
159 fprintf(stderr, "%s: threshold zero!\n", progname);
160 exit(1);
161 }
162 if (verbose) {
163 #ifdef DEBUG
164 pict_stats();
165 #endif
166 fprintf(stderr,
167 "%s: threshold set to %f cd/m2 from %d samples\n",
168 progname, threshold, nsamps);
169 }
170 }
171
172
173 addsrcspan(nss) /* add new source span to our list */
174 struct srcspan *nss;
175 {
176 struct source *last, *cs, *this;
177 register struct srcspan *ss;
178
179 cs = NULL;
180 for (this = curlist; this != NULL; this = this->next) {
181 for (ss = this->first; ss != NULL; ss = ss->next) {
182 if (!vcont(nss->v, ss->v))
183 break;
184 if (hcont(ss, nss)) {
185 if (cs == NULL)
186 cs = this;
187 else {
188 last->next = this->next;
189 mergesource(cs, this);
190 this = last;
191 }
192 break;
193 }
194 }
195 last = this;
196 }
197 if (cs == NULL) {
198 cs = (struct source *)malloc(sizeof(struct source));
199 if (cs == NULL)
200 memerr("source records");
201 cs->dom = 0.0;
202 cs->first = NULL;
203 cs->next = curlist;
204 curlist = cs;
205 }
206 nss->next = cs->first;
207 cs->first = nss;
208 }
209
210
211 mergesource(sp, ap) /* merge source ap into source sp */
212 struct source *sp, *ap;
213 {
214 struct srcspan head;
215 register struct srcspan *alp, *prev, *tp;
216
217 head.next = sp->first;
218 prev = &head;
219 alp = ap->first;
220 while (alp != NULL && prev->next != NULL) {
221 if (prev->next->v > alp->v) {
222 tp = alp->next;
223 alp->next = prev->next;
224 prev->next = alp;
225 alp = tp;
226 }
227 prev = prev->next;
228 }
229 if (prev->next == NULL)
230 prev->next = alp;
231 sp->first = head.next;
232 if (ap->dom > 0.0 && sp->dom > 0.0) { /* sources are done */
233 sp->dir[0] *= sp->dom;
234 sp->dir[1] *= sp->dom;
235 sp->dir[2] *= sp->dom;
236 fvsum(sp->dir, sp->dir, ap->dir, ap->dom);
237 normalize(sp->dir);
238 sp->brt = (sp->brt*sp->dom + ap->brt*ap->dom)
239 / (sp->dom + ap->dom);
240 }
241 free((void *)ap);
242 }
243
244
245 close_sources(v) /* close sources above v */
246 int v;
247 {
248 struct source head;
249 register struct source *last, *this;
250
251 head.next = curlist;
252 last = &head;
253 for (this = curlist; this != NULL; this = this->next)
254 if (!vcont(v, this->first->v)) {
255 last->next = this->next;
256 donesource(this);
257 this = last;
258 } else
259 last = this;
260 curlist = head.next;
261 }
262
263
264 close_allsrcs() /* done with everything */
265 {
266 register struct source *this, *next;
267
268 this = curlist;
269 while (this != NULL) {
270 next = this->next;
271 donesource(this);
272 this = next;
273 }
274 curlist = NULL;
275 }
276
277
278 struct srcspan *
279 splitspan(sso, h, v, m) /* divide source span at point */
280 register struct srcspan *sso;
281 double h, v, m;
282 {
283 register struct srcspan *ssn;
284 double d;
285 int hs;
286
287 d = h - m*(sso->v - v);
288 hs = d < 0. ? d-.5 : d+.5;
289 if (sso->l >= hs)
290 return(NULL);
291 if (sso->r <= hs)
292 return(sso);
293 /* need to split it */
294 ssn = (struct srcspan *)malloc(sizeof(struct srcspan));
295 if (ssn == NULL)
296 memerr("source spans in splitspan");
297 ssn->brsum = (double)(hs - sso->l)/(sso->r - sso->l) * sso->brsum;
298 sso->brsum -= ssn->brsum;
299 ssn->v = sso->v;
300 ssn->l = sso->l;
301 ssn->r = sso->l = hs;
302 return(ssn);
303 }
304
305
306 struct source *
307 splitsource(so) /* divide source in two if it's big and long */
308 struct source *so;
309 {
310 LRSUM lr;
311 LRLIN fit;
312 register struct srcspan *ss, *ssn;
313 struct srcspan *ssl, *ssnl, head;
314 int h;
315 double mh, mv;
316 struct source *sn;
317
318 lrclear(&lr);
319 for (ss = so->first; ss != NULL; ss = ss->next)
320 for (h = ss->l; h < ss->r; h++)
321 lrpoint(h, ss->v, &lr);
322 if ((double)lr.n/(sampdens*sampdens) < SABIG)
323 return(NULL); /* too small */
324 if (lrfit(&fit, &lr) < 0)
325 return(NULL); /* can't fit a line */
326 if (fit.correlation < LCORR && fit.correlation > -LCORR)
327 return(NULL);
328 if (verbose)
329 fprintf(stderr, "%s: splitting large source\n", progname);
330 mh = lrxavg(&lr);
331 mv = lryavg(&lr);
332 sn = (struct source *)malloc(sizeof(struct source));
333 if (sn == NULL)
334 memerr("source records in splitsource");
335 sn->dom = 0.0;
336 sn->first = NULL;
337 ssnl = NULL;
338 head.next = so->first;
339 ssl = &head;
340 for (ss = so->first; ss != NULL; ssl = ss, ss = ss->next)
341 if ((ssn = splitspan(ss, mh, mv, fit.slope)) != NULL) {
342 if (ssn == ss) { /* remove from old */
343 ssl->next = ss->next;
344 ss = ssl;
345 }
346 if (ssnl == NULL) /* add to new */
347 sn->first = ssn;
348 else
349 ssnl->next = ssn;
350 ssn->next = NULL;
351 ssnl = ssn;
352 }
353 so->first = head.next;
354 return(sn);
355 }
356
357
358 donesource(sp) /* finished with this source */
359 register struct source *sp;
360 {
361 struct source *newsrc;
362 register struct srcspan *ss;
363 int h, n;
364 double hsum, vsum, d;
365
366 while ((newsrc = splitsource(sp)) != NULL) /* split it? */
367 donesource(newsrc);
368 sp->dom = 0.0;
369 hsum = vsum = 0.0;
370 sp->brt = 0.0;
371 n = 0;
372 for (ss = sp->first; ss != NULL; ss = ss->next) {
373 sp->brt += ss->brsum;
374 n += ss->r - ss->l;
375 for (h = ss->l; h < ss->r; h++) {
376 d = pixsize(h, ss->v);
377 hsum += d*h;
378 vsum += d*ss->v;
379 sp->dom += d;
380 }
381 }
382 freespans(sp);
383 if (sp->dom <= FTINY) { /* must be right at edge of image */
384 free((void *)sp);
385 return;
386 }
387 sp->brt /= (double)n;
388 compdir(sp->dir, (int)(hsum/sp->dom), (int)(vsum/sp->dom));
389 sp->next = donelist;
390 donelist = sp;
391 if (verbose)
392 fprintf(stderr,
393 "%s: source at [%.3f,%.3f,%.3f], dw %.5f, br %.1f (%d samps)\n",
394 progname, sp->dir[0], sp->dir[1], sp->dir[2],
395 sp->dom, sp->brt, n);
396 }
397
398
399 struct source *
400 findbuddy(s, l) /* find close enough source to s in l*/
401 register struct source *s, *l;
402 {
403 struct source *bestbuddy = NULL;
404 double d, r, mindist = MAXBUDDY;
405
406 r = sqrt(s->dom/PI);
407 for ( ; l != NULL; l = l->next) {
408 d = sqrt(dist2(l->dir, s->dir)) - sqrt(l->dom/PI) - r;
409 if (d < mindist) {
410 bestbuddy = l;
411 mindist = d;
412 }
413 }
414 return(bestbuddy);
415 }
416
417
418 absorb_specks() /* eliminate too-small sources */
419 {
420 struct source head, *buddy;
421 register struct source *last, *this;
422
423 if (verbose)
424 fprintf(stderr, "%s: absorbing small sources...\n", progname);
425 head.next = donelist;
426 last = &head;
427 for (this = head.next; this != NULL; this = this->next)
428 if (TOOSMALL(this)) {
429 last->next = this->next;
430 buddy = findbuddy(this, head.next);
431 if (buddy != NULL)
432 mergesource(buddy, this);
433 else
434 absorb(this);
435 this = last;
436 } else
437 last = this;
438 donelist = head.next;
439 }
440
441
442 absorb(s) /* absorb a source into indirect */
443 register struct source *s;
444 {
445 FVECT dir;
446 double d;
447 register int i;
448
449 for (i = 0; i < nglardirs; i++) {
450 spinvector(dir, ourview.vdir, ourview.vup, indirect[i].theta);
451 d = DOT(dir,s->dir)*s->dom*(sampdens*sampdens);
452 if (d <= 0.0)
453 continue;
454 indirect[i].sum += d * s->brt;
455 indirect[i].n += d;
456 }
457 freespans(s);
458 free((void *)s);
459 }
460
461
462 freespans(sp) /* free spans associated with source */
463 struct source *sp;
464 {
465 register struct srcspan *ss;
466
467 while ((ss = sp->first) != NULL) {
468 sp->first = ss->next;
469 free((void *)ss);
470 }
471 }