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, 1 month 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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.4 static const char RCSid[] = "$Id$";
3 greg 1.1 #endif
4     /*
5     * Gather samples and compute glare sources.
6     */
7    
8     #include "glare.h"
9 greg 1.15 #include "linregr.h"
10 greg 1.1
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 greg 1.5 close_sources(v);
50 greg 1.8 #ifndef DEBUG
51 greg 2.2 if (verbose) {
52 greg 1.8 fprintf(stderr, "%s: analyzing... %3ld%%\r",
53     progname, 100L*(vsize-v)/(2*vsize));
54 greg 2.2 fflush(stderr);
55     }
56 greg 1.8 #endif
57 greg 1.1 getviewspan(v, spanbr);
58     left = hsize + 1;
59 greg 1.2 for (h = -hsize; h <= hsize; h++) {
60 greg 1.1 if (spanbr[h+hsize] < 0.0) { /* off view */
61     if (left < h) {
62 greg 1.2 addsrcspan(newspan(left,h,v,spanbr));
63 greg 1.1 left = hsize + 1;
64     }
65     continue;
66     }
67     if (spanbr[h+hsize] > threshold) { /* in source */
68 greg 1.2 if (left > h)
69 greg 1.1 left = h;
70     } else { /* out of source */
71     if (left < h) {
72 greg 1.2 addsrcspan(newspan(left,h,v,spanbr));
73 greg 1.1 left = hsize + 1;
74     }
75 greg 1.13 addindirect(h, v, spanbr[h+hsize]);
76 greg 1.1 }
77 greg 1.2 }
78 greg 1.1 if (left < h)
79 greg 1.2 addsrcspan(newspan(left,h,v,spanbr));
80 greg 1.1 }
81 greg 2.4 free((void *)spanbr);
82 greg 1.1 close_allsrcs();
83     }
84    
85    
86 greg 1.13 addindirect(h, v, br) /* add brightness to indirect illuminances */
87     int h, v;
88 greg 1.1 double br;
89     {
90     double tanb, d;
91 greg 1.13 int hl;
92 greg 1.1 register int i;
93    
94 greg 1.13 hl = hlim(v);
95     if (h <= -hl) { /* left region */
96     d = (double)(-h-hl)/sampdens;
97 greg 1.9 if (d >= 1.0-FTINY)
98 greg 1.1 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 greg 1.10 indirect[i].n += d;
105 greg 1.1 }
106     }
107     return;
108     }
109 greg 1.13 if (h >= hl) { /* right region */
110     d = (double)(-h+hl)/sampdens;
111 greg 1.9 if (d <= -1.0+FTINY)
112 greg 1.1 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 greg 1.10 indirect[i].n += d;
119 greg 1.1 }
120     }
121     return;
122     }
123     /* central region */
124     for (i = 0; i < nglardirs; i++) {
125 greg 1.13 d = cos(h_theta(h,v) - indirect[i].theta);
126 greg 1.1 if (d > 0.0) {
127     indirect[i].sum += d * br;
128 greg 1.10 indirect[i].n += d;
129 greg 1.1 }
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 greg 1.12 for (v = vsize; v >= -vsize; v -= TSAMPSTEP) {
146 greg 1.1 for (h = -hsize; h <= hsize; h += TSAMPSTEP) {
147 greg 1.13 if ((br = getviewpix(h, v)) < 0.0)
148 greg 1.1 continue;
149     brsum += br;
150     nsamps++;
151     }
152 greg 1.12 }
153 greg 1.1 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 greg 1.2 if (verbose) {
163 greg 1.8 #ifdef DEBUG
164 greg 1.2 pict_stats();
165 greg 1.8 #endif
166 greg 1.1 fprintf(stderr,
167     "%s: threshold set to %f cd/m2 from %d samples\n",
168     progname, threshold, nsamps);
169 greg 1.2 }
170 greg 1.1 }
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 greg 1.7 last->next = this->next;
189 greg 1.1 mergesource(cs, this);
190 greg 1.5 this = last;
191 greg 1.1 }
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 greg 1.7 cs->dom = 0.0;
202 greg 1.1 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 greg 1.7 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 greg 2.4 free((void *)ap);
242 greg 1.1 }
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 greg 1.5 register struct source *this, *next;
267 greg 1.1
268 greg 1.5 this = curlist;
269     while (this != NULL) {
270     next = this->next;
271 greg 1.1 donesource(this);
272 greg 1.5 this = next;
273 greg 1.4 }
274 greg 1.1 curlist = NULL;
275     }
276    
277    
278 greg 1.15 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 greg 1.1 donesource(sp) /* finished with this source */
359     register struct source *sp;
360     {
361 greg 1.15 struct source *newsrc;
362 greg 1.1 register struct srcspan *ss;
363     int h, n;
364 greg 1.13 double hsum, vsum, d;
365 greg 1.1
366 greg 1.15 while ((newsrc = splitsource(sp)) != NULL) /* split it? */
367     donesource(newsrc);
368 greg 1.1 sp->dom = 0.0;
369 greg 1.13 hsum = vsum = 0.0;
370 greg 1.1 sp->brt = 0.0;
371 greg 1.3 n = 0;
372 greg 1.1 for (ss = sp->first; ss != NULL; ss = ss->next) {
373     sp->brt += ss->brsum;
374     n += ss->r - ss->l;
375 greg 1.14 for (h = ss->l; h < ss->r; h++) {
376 greg 1.13 d = pixsize(h, ss->v);
377     hsum += d*h;
378     vsum += d*ss->v;
379     sp->dom += d;
380     }
381 greg 1.1 }
382 greg 2.3 freespans(sp);
383     if (sp->dom <= FTINY) { /* must be right at edge of image */
384 greg 2.4 free((void *)sp);
385 greg 2.3 return;
386     }
387 greg 1.1 sp->brt /= (double)n;
388 greg 1.13 compdir(sp->dir, (int)(hsum/sp->dom), (int)(vsum/sp->dom));
389 greg 1.1 sp->next = donelist;
390     donelist = sp;
391     if (verbose)
392     fprintf(stderr,
393 greg 1.12 "%s: source at [%.3f,%.3f,%.3f], dw %.5f, br %.1f (%d samps)\n",
394 greg 1.2 progname, sp->dir[0], sp->dir[1], sp->dir[2],
395 greg 1.5 sp->dom, sp->brt, n);
396 greg 1.7 }
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 greg 1.11 for (this = head.next; this != NULL; this = this->next)
428 greg 1.7 if (TOOSMALL(this)) {
429     last->next = this->next;
430 greg 1.11 buddy = findbuddy(this, head.next);
431 greg 1.7 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 greg 1.10 double d;
447     register int i;
448 greg 1.7
449     for (i = 0; i < nglardirs; i++) {
450     spinvector(dir, ourview.vdir, ourview.vup, indirect[i].theta);
451 greg 1.10 d = DOT(dir,s->dir)*s->dom*(sampdens*sampdens);
452     if (d <= 0.0)
453 greg 1.7 continue;
454 greg 1.10 indirect[i].sum += d * s->brt;
455     indirect[i].n += d;
456 greg 1.7 }
457 greg 1.15 freespans(s);
458 greg 2.4 free((void *)s);
459 greg 1.15 }
460    
461    
462     freespans(sp) /* free spans associated with source */
463     struct source *sp;
464     {
465     register struct srcspan *ss;
466    
467 greg 2.3 while ((ss = sp->first) != NULL) {
468     sp->first = ss->next;
469 greg 2.4 free((void *)ss);
470 greg 2.3 }
471 greg 1.1 }