--- ray/src/util/glaresrc.c 1991/03/19 09:10:58 1.4 +++ ray/src/util/glaresrc.c 1991/04/10 15:59:10 1.11 @@ -16,9 +16,7 @@ static char SCCSid[] = "$SunId$ LBL"; struct source *curlist = NULL; /* current source list */ struct source *donelist = NULL; /* finished sources */ -double threshold; /* glare threshold */ - struct srcspan * newspan(l, r, v, sb) /* allocate a new source span */ int l, r, v; @@ -50,6 +48,12 @@ analyze() /* analyze our scene */ if (spanbr == NULL) memerr("view span brightness buffer"); for (v = vsize; v >= -vsize; v--) { + close_sources(v); +#ifndef DEBUG + if (verbose) + fprintf(stderr, "%s: analyzing... %3ld%%\r", + progname, 100L*(vsize-v)/(2*vsize)); +#endif getviewspan(v, spanbr); left = hsize + 1; for (h = -hsize; h <= hsize; h++) { @@ -73,10 +77,9 @@ analyze() /* analyze our scene */ } if (left < h) addsrcspan(newspan(left,h,v,spanbr)); - close_sources(v); } - close_allsrcs(); free((char *)spanbr); + close_allsrcs(); } @@ -88,29 +91,29 @@ double br; register int i; if (h <= -hlim) { /* left region */ - d = (double)(h+hlim)/sampdens; - if (d <= -1.0+FTINY) + d = (double)(-h-hlim)/sampdens; + if (d >= 1.0-FTINY) return; tanb = d/sqrt(1.0-d*d); for (i = 0; i < nglardirs; i++) { d = indirect[i].lcos - tanb*indirect[i].lsin; if (d > 0.0) { indirect[i].sum += d * br; - indirect[i].n++; + indirect[i].n += d; } } return; } if (h >= hlim) { /* right region */ - d = (double)(h-hlim)/sampdens; - if (d >= 1.0-FTINY) + d = (double)(-h+hlim)/sampdens; + if (d <= -1.0+FTINY) return; tanb = d/sqrt(1.0-d*d); for (i = 0; i < nglardirs; i++) { d = indirect[i].rcos - tanb*indirect[i].rsin; if (d > 0.0) { indirect[i].sum += d * br; - indirect[i].n++; + indirect[i].n += d; } } return; @@ -120,7 +123,7 @@ double br; d = cos(h_theta(h) - indirect[i].theta); if (d > 0.0) { indirect[i].sum += d * br; - indirect[i].n++; + indirect[i].n += d; } } } @@ -154,7 +157,9 @@ comp_thresh() /* compute glare threshold */ exit(1); } if (verbose) { +#ifdef DEBUG pict_stats(); +#endif fprintf(stderr, "%s: threshold set to %f cd/m2 from %d samples\n", progname, threshold, nsamps); @@ -167,7 +172,6 @@ struct srcspan *nss; { struct source *last, *cs, *this; register struct srcspan *ss; - register int res; cs = NULL; for (this = curlist; this != NULL; this = this->next) { @@ -178,9 +182,9 @@ struct srcspan *nss; if (cs == NULL) cs = this; else { - mergesource(cs, this); last->next = this->next; - free((char *)this); + mergesource(cs, this); + this = last; } break; } @@ -191,6 +195,7 @@ struct srcspan *nss; cs = (struct source *)malloc(sizeof(struct source)); if (cs == NULL) memerr("source records"); + cs->dom = 0.0; cs->first = NULL; cs->next = curlist; curlist = cs; @@ -221,7 +226,16 @@ struct source *sp, *ap; if (prev->next == NULL) prev->next = alp; sp->first = head.next; - ap->first = NULL; + if (ap->dom > 0.0 && sp->dom > 0.0) { /* sources are done */ + sp->dir[0] *= sp->dom; + sp->dir[1] *= sp->dom; + sp->dir[2] *= sp->dom; + fvsum(sp->dir, sp->dir, ap->dir, ap->dom); + normalize(sp->dir); + sp->brt = (sp->brt*sp->dom + ap->brt*ap->dom) + / (sp->dom + ap->dom); + } + free((char *)ap); } @@ -246,11 +260,13 @@ int v; close_allsrcs() /* done with everything */ { - register struct source *this, *nsrc; + register struct source *this, *next; - for (this = curlist; this != NULL; this = nsrc) { - nsrc = this->next; + this = curlist; + while (this != NULL) { + next = this->next; donesource(this); + this = next; } curlist = NULL; } @@ -265,32 +281,95 @@ register struct source *sp; double d; sp->dom = 0.0; - sp->dir[0] = sp->dir[1] = sp->dir[1] = 0.0; + sp->dir[0] = sp->dir[1] = sp->dir[2] = 0.0; sp->brt = 0.0; n = 0; for (ss = sp->first; ss != NULL; ss = ss->next) { sp->brt += ss->brsum; n += ss->r - ss->l; - compdir(dright, ss->r, ss->v); - for (h = ss->r-1; h >= ss->l; h--) { - compdir(dthis, h, ss->v); - d = dist2(dthis, dright); - fvsum(sp->dir, sp->dir, dthis, d); - sp->dom += d; - VCOPY(dright, dthis); - } + if (compdir(dright, ss->r, ss->v) < 0) + compdir(dright, ss->r-2, ss->v); + for (h = ss->r-1; h >= ss->l; h--) + if (compdir(dthis, h, ss->v) == 0) { + d = dist2(dthis, dright); + fvsum(sp->dir, sp->dir, dthis, d); + sp->dom += d; + VCOPY(dright, dthis); + } free((char *)ss); } sp->first = NULL; sp->brt /= (double)n; - sp->dir[0] /= sp->dom; - sp->dir[1] /= sp->dom; - sp->dir[2] /= sp->dom; + normalize(sp->dir); sp->next = donelist; donelist = sp; if (verbose) fprintf(stderr, - "%s: found source at (%f,%f,%f), dw %f, br %f\n", + "%s: found source at (%.3f,%.3f,%.3f), dw %.5f, br %.1f (%d samps)\n", progname, sp->dir[0], sp->dir[1], sp->dir[2], - sp->dom, sp->brt); + sp->dom, sp->brt, n); +} + + +struct source * +findbuddy(s, l) /* find close enough source to s in l*/ +register struct source *s, *l; +{ + struct source *bestbuddy = NULL; + double d, r, mindist = MAXBUDDY; + + r = sqrt(s->dom/PI); + for ( ; l != NULL; l = l->next) { + d = sqrt(dist2(l->dir, s->dir)) - sqrt(l->dom/PI) - r; + if (d < mindist) { + bestbuddy = l; + mindist = d; + } + } + return(bestbuddy); +} + + +absorb_specks() /* eliminate too-small sources */ +{ + struct source head, *buddy; + register struct source *last, *this; + + if (verbose) + fprintf(stderr, "%s: absorbing small sources...\n", progname); + head.next = donelist; + last = &head; + for (this = head.next; this != NULL; this = this->next) + if (TOOSMALL(this)) { + last->next = this->next; + buddy = findbuddy(this, head.next); + if (buddy != NULL) + mergesource(buddy, this); + else + absorb(this); + this = last; + } else + last = this; + donelist = head.next; +} + + +absorb(s) /* absorb a source into indirect */ +register struct source *s; +{ + FVECT dir; + double d; + register int i; + + for (i = 0; i < nglardirs; i++) { + spinvector(dir, ourview.vdir, ourview.vup, indirect[i].theta); + d = DOT(dir,s->dir)*s->dom*(sampdens*sampdens); + if (d <= 0.0) + continue; + indirect[i].sum += d * s->brt; + indirect[i].n += d; + } + for ( ; s->first != NULL; s->first = s->first->next) + free((char *)s->first); + free((char *)s); }