ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glaresrc.c
Revision: 2.5
Committed: Fri Jan 2 12:51:54 2004 UTC (20 years, 3 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.4: +78 -35 lines
Log Message:
Ansification.

File Contents

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