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

# 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
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 close_sources(v);
52 getviewspan(v, spanbr);
53 left = hsize + 1;
54 for (h = -hsize; h <= hsize; h++) {
55 if (spanbr[h+hsize] < 0.0) { /* off view */
56 if (left < h) {
57 addsrcspan(newspan(left,h,v,spanbr));
58 left = hsize + 1;
59 }
60 continue;
61 }
62 if (spanbr[h+hsize] > threshold) { /* in source */
63 if (left > h)
64 left = h;
65 } else { /* out of source */
66 if (left < h) {
67 addsrcspan(newspan(left,h,v,spanbr));
68 left = hsize + 1;
69 }
70 addindirect(h, spanbr[h+hsize]);
71 }
72 }
73 if (left < h)
74 addsrcspan(newspan(left,h,v,spanbr));
75 }
76 free((char *)spanbr);
77 close_allsrcs();
78 absorb_specks();
79 }
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 d = (double)(h+hlim)/sampdens;
91 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 d = (double)(h-hlim)/sampdens;
105 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 if (verbose) {
156 pict_stats();
157 fprintf(stderr,
158 "%s: threshold set to %f cd/m2 from %d samples\n",
159 progname, threshold, nsamps);
160 }
161 }
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 last->next = this->next;
180 mergesource(cs, this);
181 this = last;
182 }
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 cs->dom = 0.0;
193 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 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 }
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 register struct source *this, *next;
258
259 this = curlist;
260 while (this != NULL) {
261 next = this->next;
262 donesource(this);
263 this = next;
264 }
265 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 sp->dir[0] = sp->dir[1] = sp->dir[2] = 0.0;
279 sp->brt = 0.0;
280 n = 0;
281 for (ss = sp->first; ss != NULL; ss = ss->next) {
282 sp->brt += ss->brsum;
283 n += ss->r - ss->l;
284 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 free((char *)ss);
294 }
295 sp->first = NULL;
296 sp->brt /= (double)n;
297 normalize(sp->dir);
298 sp->next = donelist;
299 donelist = sp;
300 if (verbose)
301 fprintf(stderr,
302 "%s: found source at (%.3f,%.3f,%.3f), dw %.5f, br %.1f (%d samps)\n",
303 progname, sp->dir[0], sp->dir[1], sp->dir[2],
304 sp->dom, sp->brt, n);
305 }
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 }