ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glaresrc.c
(Generate patch)

Comparing ray/src/util/glaresrc.c (file contents):
Revision 1.5 by greg, Tue Mar 19 17:06:25 1991 UTC vs.
Revision 2.5 by schorsch, Fri Jan 2 12:51:54 2004 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1991 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
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)
# Line 16 | Line 14 | static char SCCSid[] = "$SunId$ LBL";
14   struct source   *curlist = NULL;        /* current source list */
15   struct source   *donelist = NULL;       /* finished sources */
16  
17 < double  threshold;                      /* glare threshold */
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 < struct srcspan *
33 < newspan(l, r, v, sb)            /* allocate a new source span */
34 < int     l, r, v;
35 < float   *sb;
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;
# Line 40 | Line 53 | float  *sb;
53   }
54  
55  
56 < analyze()                       /* analyze our scene */
56 > extern void
57 > analyze(void)                   /* analyze our scene */
58   {
59          int     h, v;
60          int     left;
# Line 51 | Line 65 | analyze()                      /* analyze our scene */
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++) {
# Line 69 | Line 90 | analyze()                      /* analyze our scene */
90                                          addsrcspan(newspan(left,h,v,spanbr));
91                                          left = hsize + 1;
92                                  }
93 <                                addindirect(h, spanbr[h+hsize]);
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();
79        free((char *)spanbr);
101   }
102  
103  
104 < addindirect(h, br)              /* add brightness to indirect illuminances */
105 < int     h;
106 < double  br;
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 <        if (h <= -hlim) {                       /* left region */
116 <                d = (double)(h+hlim)/sampdens;
117 <                if (d <= -1.0+FTINY)
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++;
125 >                                indirect[i].n += d;
126                          }
127                  }
128                  return;
129          }
130 <        if (h >= hlim) {                        /* right region */
131 <                d = (double)(h-hlim)/sampdens;
132 <                if (d >= 1.0-FTINY)
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++;
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) - indirect[i].theta);
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++;
149 >                        indirect[i].n += d;
150                  }
151          }
152   }
153  
154  
155 < comp_thresh()                   /* compute glare threshold */
155 > extern void
156 > comp_thresh(void)                       /* compute glare threshold */
157   {
158          int     h, v;
159          int     nsamps;
# Line 137 | Line 164 | comp_thresh()                  /* compute glare threshold */
164                                  progname);
165          brsum = 0.0;
166          nsamps = 0;
167 <        for (v = vsize; v >= -vsize; v -= TSAMPSTEP)
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);
# Line 154 | Line 182 | comp_thresh()                  /* compute glare threshold */
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);
# Line 162 | Line 192 | comp_thresh()                  /* compute glare threshold */
192   }
193  
194  
195 < addsrcspan(nss)                 /* add new source span to our list */
196 < struct srcspan  *nss;
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;
# Line 177 | Line 209 | struct srcspan *nss;
209                                  if (cs == NULL)
210                                          cs = this;
211                                  else {
180                                        mergesource(cs, this);
212                                          last->next = this->next;
213 <                                        free((char *)this);
213 >                                        mergesource(cs, this);
214                                          this = last;
215                                  }
216                                  break;
# Line 191 | Line 222 | struct srcspan *nss;
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;
# Line 200 | Line 232 | struct srcspan *nss;
232   }
233  
234  
235 < mergesource(sp, ap)             /* merge source ap into source sp */
236 < struct source   *sp, *ap;
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;
# Line 221 | Line 256 | struct source  *sp, *ap;
256          if (prev->next == NULL)
257                  prev->next = alp;
258          sp->first = head.next;
259 <        ap->first = NULL;
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 < close_sources(v)                /* close sources above v */
273 < int     v;
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;
# Line 244 | Line 290 | int    v;
290   }
291  
292  
293 < close_allsrcs()                 /* done with everything */
293 > static void
294 > close_allsrcs(void)                     /* done with everything */
295   {
296          register struct source  *this, *next;
297  
# Line 258 | Line 305 | close_allsrcs()                        /* done with everything */
305   }
306  
307  
308 < donesource(sp)                  /* finished with this source */
309 < register struct source  *sp;
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 <        FVECT   dthis, dright;
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  d;
400 >        double  hsum, vsum, d;
401  
402 +        while ((newsrc = splitsource(sp)) != NULL)      /* split it? */
403 +                donesource(newsrc);
404          sp->dom = 0.0;
405 <        sp->dir[0] = sp->dir[1] = sp->dir[2] = 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 <                if (compdir(dright, ss->r, ss->v) < 0)
412 <                        compdir(dright, ss->r-2, ss->v);
413 <                for (h = ss->r-1; h >= ss->l; h--)
414 <                        if (compdir(dthis, h, ss->v) == 0) {
415 <                                d = dist2(dthis, dright);
416 <                                fvsum(sp->dir, sp->dir, dthis, d);
282 <                                sp->dom += d;
283 <                                VCOPY(dright, dthis);
284 <                        }
285 <                free((char *)ss);
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 <        sp->first = NULL;
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 <        normalize(sp->dir);
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: found source at (%.3f,%.3f,%.3f), dw %.5f, br %.1f (%d samps)\n",
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   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines