ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glaresrc.c
Revision: 2.2
Committed: Tue Mar 10 10:00:33 1992 UTC (32 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +3 -1 lines
Log Message:
added flush to progress report

File Contents

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