ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glaresrc.c
Revision: 1.11
Committed: Wed Apr 10 15:59:10 1991 UTC (32 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +2 -3 lines
Log Message:
fixed small bug in absorb_specks() and added -c option

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