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.4 by greg, Tue Mar 19 09:10:58 1991 UTC vs.
Revision 2.3 by greg, Mon Jun 7 10:32:02 1993 UTC

# Line 9 | Line 9 | static char SCCSid[] = "$SunId$ LBL";
9   */
10  
11   #include "glare.h"
12 + #include "linregr.h"
13  
14   #define vcont(vd,vu)    ((vu)-(vd)<=SEPS)
15   #define hcont(s1,s2)    ((s1)->r-(s2)->l>=-SEPS&&(s2)->r-(s1)->l>=-SEPS)
# Line 16 | Line 17 | static char SCCSid[] = "$SunId$ LBL";
17   struct source   *curlist = NULL;        /* current source list */
18   struct source   *donelist = NULL;       /* finished sources */
19  
19 double  threshold;                      /* glare threshold */
20  
21
21   struct srcspan *
22   newspan(l, r, v, sb)            /* allocate a new source span */
23   int     l, r, v;
# Line 50 | Line 49 | analyze()                      /* analyze our scene */
49          if (spanbr == NULL)
50                  memerr("view span brightness buffer");
51          for (v = vsize; v >= -vsize; v--) {
52 +                close_sources(v);
53 + #ifndef DEBUG
54 +                if (verbose) {
55 +                        fprintf(stderr, "%s: analyzing... %3ld%%\r",
56 +                                progname, 100L*(vsize-v)/(2*vsize));
57 +                        fflush(stderr);
58 +                }
59 + #endif
60                  getviewspan(v, spanbr);
61                  left = hsize + 1;
62                  for (h = -hsize; h <= hsize; h++) {
# Line 68 | Line 75 | analyze()                      /* analyze our scene */
75                                          addsrcspan(newspan(left,h,v,spanbr));
76                                          left = hsize + 1;
77                                  }
78 <                                addindirect(h, spanbr[h+hsize]);
78 >                                addindirect(h, v, spanbr[h+hsize]);
79                          }
80                  }
81                  if (left < h)
82                          addsrcspan(newspan(left,h,v,spanbr));
76                close_sources(v);
83          }
78        close_allsrcs();
84          free((char *)spanbr);
85 +        close_allsrcs();
86   }
87  
88  
89 < addindirect(h, br)              /* add brightness to indirect illuminances */
90 < int     h;
89 > addindirect(h, v, br)           /* add brightness to indirect illuminances */
90 > int     h, v;
91   double  br;
92   {
93          double  tanb, d;
94 +        int     hl;
95          register int    i;
96  
97 <        if (h <= -hlim) {                       /* left region */
98 <                d = (double)(h+hlim)/sampdens;
99 <                if (d <= -1.0+FTINY)
97 >        hl = hlim(v);
98 >        if (h <= -hl) {                 /* left region */
99 >                d = (double)(-h-hl)/sampdens;
100 >                if (d >= 1.0-FTINY)
101                          return;
102                  tanb = d/sqrt(1.0-d*d);
103                  for (i = 0; i < nglardirs; i++) {
104                          d = indirect[i].lcos - tanb*indirect[i].lsin;
105                          if (d > 0.0) {
106                                  indirect[i].sum += d * br;
107 <                                indirect[i].n++;
107 >                                indirect[i].n += d;
108                          }
109                  }
110                  return;
111          }
112 <        if (h >= hlim) {                        /* right region */
113 <                d = (double)(h-hlim)/sampdens;
114 <                if (d >= 1.0-FTINY)
112 >        if (h >= hl) {                  /* right region */
113 >                d = (double)(-h+hl)/sampdens;
114 >                if (d <= -1.0+FTINY)
115                          return;
116                  tanb = d/sqrt(1.0-d*d);
117                  for (i = 0; i < nglardirs; i++) {
118                          d = indirect[i].rcos - tanb*indirect[i].rsin;
119                          if (d > 0.0) {
120                                  indirect[i].sum += d * br;
121 <                                indirect[i].n++;
121 >                                indirect[i].n += d;
122                          }
123                  }
124                  return;
125          }
126                                          /* central region */
127          for (i = 0; i < nglardirs; i++) {
128 <                d = cos(h_theta(h) - indirect[i].theta);
128 >                d = cos(h_theta(h,v) - indirect[i].theta);
129                  if (d > 0.0) {
130                          indirect[i].sum += d * br;
131 <                        indirect[i].n++;
131 >                        indirect[i].n += d;
132                  }
133          }
134   }
# Line 137 | Line 145 | comp_thresh()                  /* compute glare threshold */
145                                  progname);
146          brsum = 0.0;
147          nsamps = 0;
148 <        for (v = vsize; v >= -vsize; v -= TSAMPSTEP)
148 >        for (v = vsize; v >= -vsize; v -= TSAMPSTEP) {
149                  for (h = -hsize; h <= hsize; h += TSAMPSTEP) {
150                          if ((br = getviewpix(h, v)) < 0.0)
151                                  continue;
152                          brsum += br;
153                          nsamps++;
154                  }
155 +        }
156          if (nsamps == 0) {
157                  fprintf(stderr, "%s: no viewable scene!\n", progname);
158                  exit(1);
# Line 154 | Line 163 | comp_thresh()                  /* compute glare threshold */
163                  exit(1);
164          }
165          if (verbose) {
166 + #ifdef DEBUG
167                  pict_stats();
168 + #endif
169                  fprintf(stderr,
170                          "%s: threshold set to %f cd/m2 from %d samples\n",
171                                  progname, threshold, nsamps);
# Line 167 | Line 178 | struct srcspan *nss;
178   {
179          struct source   *last, *cs, *this;
180          register struct srcspan *ss;
170        register int    res;
181  
182          cs = NULL;
183          for (this = curlist; this != NULL; this = this->next) {
# Line 178 | Line 188 | struct srcspan *nss;
188                                  if (cs == NULL)
189                                          cs = this;
190                                  else {
181                                        mergesource(cs, this);
191                                          last->next = this->next;
192 <                                        free((char *)this);
192 >                                        mergesource(cs, this);
193 >                                        this = last;
194                                  }
195                                  break;
196                          }
# Line 191 | Line 201 | struct srcspan *nss;
201                  cs = (struct source *)malloc(sizeof(struct source));
202                  if (cs == NULL)
203                          memerr("source records");
204 +                cs->dom = 0.0;
205                  cs->first = NULL;
206                  cs->next = curlist;
207                  curlist = cs;
# Line 221 | Line 232 | struct source  *sp, *ap;
232          if (prev->next == NULL)
233                  prev->next = alp;
234          sp->first = head.next;
235 <        ap->first = NULL;
235 >        if (ap->dom > 0.0 && sp->dom > 0.0) {           /* sources are done */
236 >                sp->dir[0] *= sp->dom;
237 >                sp->dir[1] *= sp->dom;
238 >                sp->dir[2] *= sp->dom;
239 >                fvsum(sp->dir, sp->dir, ap->dir, ap->dom);
240 >                normalize(sp->dir);
241 >                sp->brt = (sp->brt*sp->dom + ap->brt*ap->dom)
242 >                                / (sp->dom + ap->dom);
243 >        }
244 >        free((char *)ap);
245   }
246  
247  
# Line 246 | Line 266 | int    v;
266  
267   close_allsrcs()                 /* done with everything */
268   {
269 <        register struct source  *this, *nsrc;
269 >        register struct source  *this, *next;
270  
271 <        for (this = curlist; this != NULL; this = nsrc) {
272 <                nsrc = this->next;
271 >        this = curlist;
272 >        while (this != NULL) {
273 >                next = this->next;
274                  donesource(this);
275 +                this = next;
276          }
277          curlist = NULL;
278   }
279  
280  
281 + struct srcspan *
282 + splitspan(sso, h, v, m)         /* divide source span at point */
283 + register struct srcspan *sso;
284 + double  h, v, m;
285 + {
286 +        register struct srcspan *ssn;
287 +        double  d;
288 +        int     hs;
289 +
290 +        d = h - m*(sso->v - v);
291 +        hs = d < 0. ? d-.5 : d+.5;
292 +        if (sso->l >= hs)
293 +                return(NULL);
294 +        if (sso->r <= hs)
295 +                return(sso);
296 +                                /* need to split it */
297 +        ssn = (struct srcspan *)malloc(sizeof(struct srcspan));
298 +        if (ssn == NULL)
299 +                memerr("source spans in splitspan");
300 +        ssn->brsum = (double)(hs - sso->l)/(sso->r - sso->l) * sso->brsum;
301 +        sso->brsum -= ssn->brsum;
302 +        ssn->v = sso->v;
303 +        ssn->l = sso->l;
304 +        ssn->r = sso->l = hs;
305 +        return(ssn);
306 + }
307 +
308 +
309 + struct source *
310 + splitsource(so)                 /* divide source in two if it's big and long */
311 + struct source   *so;
312 + {
313 +        LRSUM   lr;
314 +        LRLIN   fit;
315 +        register struct srcspan *ss, *ssn;
316 +        struct srcspan  *ssl, *ssnl, head;
317 +        int     h;
318 +        double  mh, mv;
319 +        struct source   *sn;
320 +
321 +        lrclear(&lr);
322 +        for (ss = so->first; ss != NULL; ss = ss->next)
323 +                for (h = ss->l; h < ss->r; h++)
324 +                        lrpoint(h, ss->v, &lr);
325 +        if ((double)lr.n/(sampdens*sampdens) < SABIG)
326 +                return(NULL);                   /* too small */
327 +        if (lrfit(&fit, &lr) < 0)
328 +                return(NULL);                   /* can't fit a line */
329 +        if (fit.correlation < LCORR && fit.correlation > -LCORR)
330 +                return(NULL);
331 +        if (verbose)
332 +                fprintf(stderr, "%s: splitting large source\n", progname);
333 +        mh = lrxavg(&lr);
334 +        mv = lryavg(&lr);
335 +        sn = (struct source *)malloc(sizeof(struct source));
336 +        if (sn == NULL)
337 +                memerr("source records in splitsource");
338 +        sn->dom = 0.0;
339 +        sn->first = NULL;
340 +        ssnl = NULL;
341 +        head.next = so->first;
342 +        ssl = &head;
343 +        for (ss = so->first; ss != NULL; ssl = ss, ss = ss->next)
344 +                if ((ssn = splitspan(ss, mh, mv, fit.slope)) != NULL) {
345 +                        if (ssn == ss) {        /* remove from old */
346 +                                ssl->next = ss->next;
347 +                                ss = ssl;
348 +                        }
349 +                        if (ssnl == NULL)       /* add to new */
350 +                                sn->first = ssn;
351 +                        else
352 +                                ssnl->next = ssn;
353 +                        ssn->next = NULL;
354 +                        ssnl = ssn;
355 +                }
356 +        so->first = head.next;
357 +        return(sn);
358 + }
359 +
360 +
361   donesource(sp)                  /* finished with this source */
362   register struct source  *sp;
363   {
364 <        FVECT   dthis, dright;
364 >        struct source   *newsrc;
365          register struct srcspan *ss;
366          int     h, n;
367 <        double  d;
367 >        double  hsum, vsum, d;
368  
369 +        while ((newsrc = splitsource(sp)) != NULL)      /* split it? */
370 +                donesource(newsrc);
371          sp->dom = 0.0;
372 <        sp->dir[0] = sp->dir[1] = sp->dir[1] = 0.0;
372 >        hsum = vsum = 0.0;
373          sp->brt = 0.0;
374          n = 0;
375          for (ss = sp->first; ss != NULL; ss = ss->next) {
376                  sp->brt += ss->brsum;
377                  n += ss->r - ss->l;
378 <                compdir(dright, ss->r, ss->v);
379 <                for (h = ss->r-1; h >= ss->l; h--) {
380 <                        compdir(dthis, h, ss->v);
381 <                        d = dist2(dthis, dright);
278 <                        fvsum(sp->dir, sp->dir, dthis, d);
378 >                for (h = ss->l; h < ss->r; h++) {
379 >                        d = pixsize(h, ss->v);
380 >                        hsum += d*h;
381 >                        vsum += d*ss->v;
382                          sp->dom += d;
280                        VCOPY(dright, dthis);
383                  }
282                free((char *)ss);
384          }
385 <        sp->first = NULL;
385 >        freespans(sp);
386 >        if (sp->dom <= FTINY) {         /* must be right at edge of image */
387 >                free((char *)sp);
388 >                return;
389 >        }
390          sp->brt /= (double)n;
391 <        sp->dir[0] /= sp->dom;
287 <        sp->dir[1] /= sp->dom;
288 <        sp->dir[2] /= sp->dom;
391 >        compdir(sp->dir, (int)(hsum/sp->dom), (int)(vsum/sp->dom));
392          sp->next = donelist;
393          donelist = sp;
394          if (verbose)
395                  fprintf(stderr,
396 <        "%s: found source at (%f,%f,%f), dw %f, br %f\n",
396 >        "%s: source at [%.3f,%.3f,%.3f], dw %.5f, br %.1f (%d samps)\n",
397                          progname, sp->dir[0], sp->dir[1], sp->dir[2],
398 <                        sp->dom, sp->brt);
398 >                        sp->dom, sp->brt, n);
399 > }
400 >
401 >
402 > struct source *
403 > findbuddy(s, l)                 /* find close enough source to s in l*/
404 > register struct source  *s, *l;
405 > {
406 >        struct source   *bestbuddy = NULL;
407 >        double  d, r, mindist = MAXBUDDY;
408 >
409 >        r = sqrt(s->dom/PI);
410 >        for ( ; l != NULL; l = l->next) {
411 >                d = sqrt(dist2(l->dir, s->dir)) - sqrt(l->dom/PI) - r;
412 >                if (d < mindist) {
413 >                        bestbuddy = l;
414 >                        mindist = d;
415 >                }
416 >        }
417 >        return(bestbuddy);
418 > }
419 >
420 >
421 > absorb_specks()                 /* eliminate too-small sources */
422 > {
423 >        struct source   head, *buddy;
424 >        register struct source  *last, *this;
425 >
426 >        if (verbose)
427 >                fprintf(stderr, "%s: absorbing small sources...\n", progname);
428 >        head.next = donelist;
429 >        last = &head;
430 >        for (this = head.next; this != NULL; this = this->next)
431 >                if (TOOSMALL(this)) {
432 >                        last->next = this->next;
433 >                        buddy = findbuddy(this, head.next);
434 >                        if (buddy != NULL)
435 >                                mergesource(buddy, this);
436 >                        else
437 >                                absorb(this);
438 >                        this = last;
439 >                } else
440 >                        last = this;
441 >        donelist = head.next;
442 > }
443 >
444 >
445 > absorb(s)                       /* absorb a source into indirect */
446 > register struct source  *s;
447 > {
448 >        FVECT   dir;
449 >        double  d;
450 >        register int    i;
451 >
452 >        for (i = 0; i < nglardirs; i++) {
453 >                spinvector(dir, ourview.vdir, ourview.vup, indirect[i].theta);
454 >                d = DOT(dir,s->dir)*s->dom*(sampdens*sampdens);
455 >                if (d <= 0.0)
456 >                        continue;
457 >                indirect[i].sum += d * s->brt;
458 >                indirect[i].n += d;
459 >        }
460 >        freespans(s);
461 >        free((char *)s);
462 > }
463 >
464 >
465 > freespans(sp)                   /* free spans associated with source */
466 > struct source   *sp;
467 > {
468 >        register struct srcspan *ss;
469 >
470 >        while ((ss = sp->first) != NULL) {
471 >                sp->first = ss->next;
472 >                free((char *)ss);
473 >        }
474   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines