ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glaresrc.c
Revision: 1.7
Committed: Wed Mar 20 12:18:14 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +77 -4 lines
Log Message:
added routines to absorb too-small sources

File Contents

# User Rev Content
1 greg 1.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    
13     #define vcont(vd,vu) ((vu)-(vd)<=SEPS)
14     #define hcont(s1,s2) ((s1)->r-(s2)->l>=-SEPS&&(s2)->r-(s1)->l>=-SEPS)
15    
16     struct source *curlist = NULL; /* current source list */
17     struct source *donelist = NULL; /* finished sources */
18    
19    
20     struct srcspan *
21     newspan(l, r, v, sb) /* allocate a new source span */
22     int l, r, v;
23     float *sb;
24     {
25     register struct srcspan *ss;
26     register int i;
27    
28     ss = (struct srcspan *)malloc(sizeof(struct srcspan));
29     if (ss == NULL)
30     memerr("source spans");
31     ss->l = l;
32     ss->r = r;
33     ss->v = v;
34     ss->brsum = 0.0;
35     for (i = l; i < r; i++)
36     ss->brsum += sb[i+hsize];
37     return(ss);
38     }
39    
40    
41     analyze() /* analyze our scene */
42     {
43     int h, v;
44     int left;
45     float *spanbr;
46    
47     spanbr = (float *)malloc((2*hsize+1)*sizeof(float));
48     if (spanbr == NULL)
49     memerr("view span brightness buffer");
50     for (v = vsize; v >= -vsize; v--) {
51 greg 1.5 close_sources(v);
52 greg 1.1 getviewspan(v, spanbr);
53     left = hsize + 1;
54 greg 1.2 for (h = -hsize; h <= hsize; h++) {
55 greg 1.1 if (spanbr[h+hsize] < 0.0) { /* off view */
56     if (left < h) {
57 greg 1.2 addsrcspan(newspan(left,h,v,spanbr));
58 greg 1.1 left = hsize + 1;
59     }
60     continue;
61     }
62     if (spanbr[h+hsize] > threshold) { /* in source */
63 greg 1.2 if (left > h)
64 greg 1.1 left = h;
65     } else { /* out of source */
66     if (left < h) {
67 greg 1.2 addsrcspan(newspan(left,h,v,spanbr));
68 greg 1.1 left = hsize + 1;
69     }
70     addindirect(h, spanbr[h+hsize]);
71     }
72 greg 1.2 }
73 greg 1.1 if (left < h)
74 greg 1.2 addsrcspan(newspan(left,h,v,spanbr));
75 greg 1.1 }
76 greg 1.7 free((char *)spanbr);
77 greg 1.1 close_allsrcs();
78 greg 1.7 absorb_specks();
79 greg 1.1 }
80    
81    
82     addindirect(h, br) /* add brightness to indirect illuminances */
83     int h;
84     double br;
85     {
86     double tanb, d;
87     register int i;
88    
89     if (h <= -hlim) { /* left region */
90 greg 1.3 d = (double)(h+hlim)/sampdens;
91 greg 1.1 if (d <= -1.0+FTINY)
92     return;
93     tanb = d/sqrt(1.0-d*d);
94     for (i = 0; i < nglardirs; i++) {
95     d = indirect[i].lcos - tanb*indirect[i].lsin;
96     if (d > 0.0) {
97     indirect[i].sum += d * br;
98     indirect[i].n++;
99     }
100     }
101     return;
102     }
103     if (h >= hlim) { /* right region */
104 greg 1.3 d = (double)(h-hlim)/sampdens;
105 greg 1.1 if (d >= 1.0-FTINY)
106     return;
107     tanb = d/sqrt(1.0-d*d);
108     for (i = 0; i < nglardirs; i++) {
109     d = indirect[i].rcos - tanb*indirect[i].rsin;
110     if (d > 0.0) {
111     indirect[i].sum += d * br;
112     indirect[i].n++;
113     }
114     }
115     return;
116     }
117     /* central region */
118     for (i = 0; i < nglardirs; i++) {
119     d = cos(h_theta(h) - indirect[i].theta);
120     if (d > 0.0) {
121     indirect[i].sum += d * br;
122     indirect[i].n++;
123     }
124     }
125     }
126    
127    
128     comp_thresh() /* compute glare threshold */
129     {
130     int h, v;
131     int nsamps;
132     double brsum, br;
133    
134     if (verbose)
135     fprintf(stderr, "%s: computing glare threshold...\n",
136     progname);
137     brsum = 0.0;
138     nsamps = 0;
139     for (v = vsize; v >= -vsize; v -= TSAMPSTEP)
140     for (h = -hsize; h <= hsize; h += TSAMPSTEP) {
141     if ((br = getviewpix(h, v)) < 0.0)
142     continue;
143     brsum += br;
144     nsamps++;
145     }
146     if (nsamps == 0) {
147     fprintf(stderr, "%s: no viewable scene!\n", progname);
148     exit(1);
149     }
150     threshold = GLAREBR * brsum / nsamps;
151     if (threshold <= FTINY) {
152     fprintf(stderr, "%s: threshold zero!\n", progname);
153     exit(1);
154     }
155 greg 1.2 if (verbose) {
156     pict_stats();
157 greg 1.1 fprintf(stderr,
158     "%s: threshold set to %f cd/m2 from %d samples\n",
159     progname, threshold, nsamps);
160 greg 1.2 }
161 greg 1.1 }
162    
163    
164     addsrcspan(nss) /* add new source span to our list */
165     struct srcspan *nss;
166     {
167     struct source *last, *cs, *this;
168     register struct srcspan *ss;
169    
170     cs = NULL;
171     for (this = curlist; this != NULL; this = this->next) {
172     for (ss = this->first; ss != NULL; ss = ss->next) {
173     if (!vcont(nss->v, ss->v))
174     break;
175     if (hcont(ss, nss)) {
176     if (cs == NULL)
177     cs = this;
178     else {
179 greg 1.7 last->next = this->next;
180 greg 1.1 mergesource(cs, this);
181 greg 1.5 this = last;
182 greg 1.1 }
183     break;
184     }
185     }
186     last = this;
187     }
188     if (cs == NULL) {
189     cs = (struct source *)malloc(sizeof(struct source));
190     if (cs == NULL)
191     memerr("source records");
192 greg 1.7 cs->dom = 0.0;
193 greg 1.1 cs->first = NULL;
194     cs->next = curlist;
195     curlist = cs;
196     }
197     nss->next = cs->first;
198     cs->first = nss;
199     }
200    
201    
202     mergesource(sp, ap) /* merge source ap into source sp */
203     struct source *sp, *ap;
204     {
205     struct srcspan head;
206     register struct srcspan *alp, *prev, *tp;
207    
208     head.next = sp->first;
209     prev = &head;
210     alp = ap->first;
211     while (alp != NULL && prev->next != NULL) {
212     if (prev->next->v > alp->v) {
213     tp = alp->next;
214     alp->next = prev->next;
215     prev->next = alp;
216     alp = tp;
217     }
218     prev = prev->next;
219     }
220     if (prev->next == NULL)
221     prev->next = alp;
222     sp->first = head.next;
223 greg 1.7 if (ap->dom > 0.0 && sp->dom > 0.0) { /* sources are done */
224     sp->dir[0] *= sp->dom;
225     sp->dir[1] *= sp->dom;
226     sp->dir[2] *= sp->dom;
227     fvsum(sp->dir, sp->dir, ap->dir, ap->dom);
228     normalize(sp->dir);
229     sp->brt = (sp->brt*sp->dom + ap->brt*ap->dom)
230     / (sp->dom + ap->dom);
231     }
232     free((char *)ap);
233 greg 1.1 }
234    
235    
236     close_sources(v) /* close sources above v */
237     int v;
238     {
239     struct source head;
240     register struct source *last, *this;
241    
242     head.next = curlist;
243     last = &head;
244     for (this = curlist; this != NULL; this = this->next)
245     if (!vcont(v, this->first->v)) {
246     last->next = this->next;
247     donesource(this);
248     this = last;
249     } else
250     last = this;
251     curlist = head.next;
252     }
253    
254    
255     close_allsrcs() /* done with everything */
256     {
257 greg 1.5 register struct source *this, *next;
258 greg 1.1
259 greg 1.5 this = curlist;
260     while (this != NULL) {
261     next = this->next;
262 greg 1.1 donesource(this);
263 greg 1.5 this = next;
264 greg 1.4 }
265 greg 1.1 curlist = NULL;
266     }
267    
268    
269     donesource(sp) /* finished with this source */
270     register struct source *sp;
271     {
272     FVECT dthis, dright;
273     register struct srcspan *ss;
274     int h, n;
275     double d;
276    
277     sp->dom = 0.0;
278 greg 1.5 sp->dir[0] = sp->dir[1] = sp->dir[2] = 0.0;
279 greg 1.1 sp->brt = 0.0;
280 greg 1.3 n = 0;
281 greg 1.1 for (ss = sp->first; ss != NULL; ss = ss->next) {
282     sp->brt += ss->brsum;
283     n += ss->r - ss->l;
284 greg 1.5 if (compdir(dright, ss->r, ss->v) < 0)
285     compdir(dright, ss->r-2, ss->v);
286     for (h = ss->r-1; h >= ss->l; h--)
287     if (compdir(dthis, h, ss->v) == 0) {
288     d = dist2(dthis, dright);
289     fvsum(sp->dir, sp->dir, dthis, d);
290     sp->dom += d;
291     VCOPY(dright, dthis);
292     }
293 greg 1.1 free((char *)ss);
294     }
295     sp->first = NULL;
296     sp->brt /= (double)n;
297 greg 1.5 normalize(sp->dir);
298 greg 1.1 sp->next = donelist;
299     donelist = sp;
300     if (verbose)
301     fprintf(stderr,
302 greg 1.5 "%s: found source at (%.3f,%.3f,%.3f), dw %.5f, br %.1f (%d samps)\n",
303 greg 1.2 progname, sp->dir[0], sp->dir[1], sp->dir[2],
304 greg 1.5 sp->dom, sp->brt, n);
305 greg 1.7 }
306    
307    
308     struct source *
309     findbuddy(s, l) /* find close enough source to s in l*/
310     register struct source *s, *l;
311     {
312     struct source *bestbuddy = NULL;
313     double d, r, mindist = MAXBUDDY;
314    
315     r = sqrt(s->dom/PI);
316     for ( ; l != NULL; l = l->next) {
317     d = sqrt(dist2(l->dir, s->dir)) - sqrt(l->dom/PI) - r;
318     if (d < mindist) {
319     bestbuddy = l;
320     mindist = d;
321     }
322     }
323     return(bestbuddy);
324     }
325    
326    
327     absorb_specks() /* eliminate too-small sources */
328     {
329     struct source head, *buddy;
330     register struct source *last, *this;
331    
332     if (verbose)
333     fprintf(stderr, "%s: absorbing small sources...\n", progname);
334     head.next = donelist;
335     last = &head;
336     for (this = donelist; this != NULL; this = this->next)
337     if (TOOSMALL(this)) {
338     last->next = this->next;
339     buddy = findbuddy(this, donelist);
340     if (buddy != NULL)
341     mergesource(buddy, this);
342     else
343     absorb(this);
344     this = last;
345     } else
346     last = this;
347     donelist = head.next;
348     }
349    
350    
351     absorb(s) /* absorb a source into indirect */
352     register struct source *s;
353     {
354     FVECT dir;
355     register int i, n;
356    
357     for (i = 0; i < nglardirs; i++) {
358     spinvector(dir, ourview.vdir, ourview.vup, indirect[i].theta);
359     n = DOT(dir,s->dir)*s->dom*(sampdens*sampdens) + 0.5;
360     if (n == 0)
361     continue;
362     indirect[i].sum += n * s->brt;
363     indirect[i].n += n;
364     }
365     for ( ; s->first != NULL; s->first = s->first->next)
366     free((char *)s->first);
367     free((char *)s);
368 greg 1.1 }