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

Comparing ray/src/hd/rhd_odraw.c (file contents):
Revision 3.1 by gwlarson, Fri Dec 18 11:55:19 1998 UTC vs.
Revision 3.11 by gwlarson, Tue Dec 29 09:51:07 1998 UTC

# Line 14 | Line 14 | static char SCCSid[] = "$SunId$ SGI";
14   #include <GL/glx.h>
15   #include <GL/glu.h>
16  
17 #include "random.h"
17   #include "rhd_odraw.h"
18  
19   #ifndef DEPTHEPS
# Line 26 | Line 25 | static char SCCSid[] = "$SunId$ SGI";
25   #ifndef SFREEFRAC
26   #define SFREEFRAC       0.2             /* fraction to free at a time */
27   #endif
28 + #ifndef REDRAWTHRESH
29 + #define REDRAWTHRESH    10240           /* number of samples for dissolve */
30 + #endif
31   #ifndef MAXFAN
32   #define MAXFAN          32              /* maximum arms in a triangle fan */
33   #endif
# Line 38 | Line 40 | static char SCCSid[] = "$SunId$ SGI";
40  
41   #define NEWMAP          01              /* need to recompute mapping */
42   #define NEWRGB          02              /* need to remap RGB values */
43 + #define NEWHIST         04              /* clear histogram as well */
44  
45   struct ODview   *odView;        /* our view list */
46   int     odNViews;               /* number of views in our list */
# Line 57 | Line 60 | int    n;
60          int     nbytes, i, j, k, nextsamp, count, blockdiv;
61          int     res[2];
62  
63 <        if (odNViews) {                 /* deallocate view structures */
64 <                for (i = 0; i < odNViews; i++) {
63 >        if (odNViews > 0) {             /* deallocate view structures */
64 >                for (i = odNViews; i--; ) {
65                          free((char *)odView[i].bmap);
66 +                        free((char *)odView[i].pmap);
67                          if (odView[i].emap != NULL)
68                                  free((char *)odView[i].emap);
69                  }
# Line 73 | Line 77 | int    n;
77                  for (i = 1024; nbytes > i-8; i <<= 1)
78                          ;
79                  n = (i-8)/SAMP32 * 32;
80 <                needmapping = NEWMAP;
80 >                needmapping = NEWHIST;
81          }
82          if (n != odS.nsamp) {   /* (re)allocate sample array */
83                  if (odS.nsamp)
# Line 108 | Line 112 | int    n;
112          if (blockdiv < 8) blockdiv = 8;
113          nextsamp = 0; count /= blockdiv*blockdiv;       /* # blocks */
114          while (i--) {                   /* initialize each view */
111                odView[i].emap = NULL;
112                odView[i].dmap = NULL;
115                  dev_auxview(i, res);
116                  odView[i].hhi = res[0];
117                  odView[i].hlow = (res[0] + blockdiv/2) / blockdiv;
# Line 117 | Line 119 | int    n;
119                  odView[i].vhi = res[1];
120                  odView[i].vlow = (res[1] + blockdiv/2) / blockdiv;
121                  if (odView[i].vlow < 1) odView[i].vlow = 1;
122 +                odView[i].emap = NULL;
123 +                odView[i].dmap = NULL;
124 +                odView[i].pmap = (int4 *)calloc(FL4NELS(res[0]*res[1]),
125 +                                sizeof(int4));
126 +                if (odView[i].pmap == NULL)
127 +                        return(0);
128                  j = odView[i].hlow*odView[i].vlow;
129                  odView[i].bmap = (struct ODblock *)malloc(
130                                  j * sizeof(struct ODblock));
# Line 125 | Line 133 | int    n;
133                  DCHECK(count<=0 | nextsamp>=n,
134                                  CONSISTENCY, "counter botch in odInit");
135                  if (!i) count = j;
136 <                while (j--) {
136 >                odView[i].sfirst = nextsamp;
137 >                while (j--) {           /* initialize blocks & free lists */
138 >                        odView[i].bmap[j].pthresh = FHUGE;
139                          odView[i].bmap[j].first = k = nextsamp;
140                          nextsamp += odView[i].bmap[j].nsamp =
141                                  (n - nextsamp)/count--;
# Line 135 | Line 145 | int    n;
145                          odS.nextfree(k-1) = ENDFREE;
146                          odView[i].bmap[j].nused = 0;
147                  }
148 +                odView[i].snext = nextsamp;
149 +                odView[i].n2redraw = 0;
150          }
151          CLR4ALL(odS.redraw, odS.nsamp);         /* clear redraw flags */
152 <        for (i = odS.nsamp; i--; )              /* clear values */
152 >        for (i = odS.nsamp; i--; ) {            /* clear values */
153                  odS.ip[i][0] = odS.ip[i][1] = -1;
154 +                odS.brt[i] = TM_NOBRT;
155 +        }
156 +        needmapping |= NEWMAP;                  /* compute new map on update */
157          return(odS.nsamp);                      /* return number of samples */
158   }
159  
# Line 156 | Line 171 | int    *s0, *s1;
171  
172  
173   int
174 < odAllocBlockSamp(vn, hl, vl)            /* allocate sample from block */
175 < int     vn, hl, vl;
174 > odAllocBlockSamp(vn, hh, vh, prox)      /* allocate sample from block */
175 > int     vn, hh, vh;
176 > double  prox;
177   {
178          int     si[SAMPSPERBLOCK+SAMPSPERBLOCK/4];
179 +        int     hl, vl;
180          VIEW    *vw;
181          FVECT   ro, rd;
182          int     res[2];
183          register struct ODblock *bp;
184 <        register int    i;
185 <
184 >        register int    i, j;
185 >                                        /* get block */
186 >        hl = hh*odView[vn].hlow/odView[vn].hhi;
187 >        vl = vh*odView[vn].vlow/odView[vn].vhi;
188          bp = odView[vn].bmap + vl*odView[vn].hlow + hl;
189 <        if (bp->free != ENDFREE) {      /* check free list first */
189 >        if (prox > bp->pthresh)
190 >                return(-1);             /* worse than free list occupants */
191 >                                        /* check for duplicate pixel */
192 >        if (CHK4(odView[vn].pmap, vh*odView[vn].hhi + hh))
193 >                i = bp->first + bp->nsamp;
194 >        else
195 >                i = 0;
196 >        while (i-- > bp->first)
197 >                if (hh == odS.ip[i][0] && vh == odS.ip[i][1]) { /* found it! */
198 >                                                /* search free list for it */
199 >                        if (i == bp->free)
200 >                                break;          /* special case */
201 >                        if (bp->free != ENDFREE)
202 >                                for (j = bp->free; odS.nextfree(j) != ENDFREE;
203 >                                                j = odS.nextfree(j))
204 >                                        if (odS.nextfree(j) == i) {
205 >                                                odS.nextfree(j) =
206 >                                                        odS.nextfree(i);
207 >                                                bp->nused++;
208 >                                                goto gotit;
209 >                                        }
210 >                        if (prox >= 0.99*odS.closeness(i))
211 >                                return(-1);     /* previous sample is fine */
212 >                        goto gotit;
213 >                }
214 >        if (bp->free != ENDFREE) {      /* allocate from free list */
215                  i = bp->free;
216 +                if (odS.ip[i][0] >= 0 & odS.ip[i][1] >= 0)
217 +                        CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi +
218 +                                                        odS.ip[i][0]);
219                  bp->free = odS.nextfree(i);
220                  bp->nused++;
221 <                return(i);
221 >                goto gotit;
222          }
223          DCHECK(bp->nsamp<=0, CONSISTENCY,
224                          "no available samples in odAllocBlockSamp");
# Line 183 | Line 230 | int    vn, hl, vl;
230          for (i = bp->nsamp; i--; )      /* figure out which are worse */
231                  si[i] = bp->first + i;
232          qsort((char *)si, bp->nsamp, sizeof(int), sampcmp);
233 <        i = bp->nsamp*SFREEFRAC + .5;   /* put them in a list */
233 >        i = bp->nsamp*SFREEFRAC + .5;   /* put them into free list */
234 >        if (i >= bp->nsamp) i = bp->nsamp-1;    /* paranoia */
235 >        bp->pthresh = odS.closeness(si[i]);     /* new proximity threshold */
236          while (--i > 0) {
237                  odS.nextfree(si[i]) = bp->free;
238                  bp->free = si[i];
239                  bp->nused--;
240          }
241 <        return(si[0]);                  /* return first free sample */
241 >        i = si[0];                      /* use worst sample */
242 >        CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi + odS.ip[i][0]);
243 > gotit:
244 >        odS.ip[i][0] = hh;
245 >        odS.ip[i][1] = vh;
246 >        odS.closeness(i) = prox;
247 >        SET4(odView[vn].pmap, vh*odView[vn].hhi + hh);
248 >        return(i);
249   }
250  
251  
# Line 198 | Line 254 | COLR   c;
254   FVECT   d, p;
255   {
256          FVECT   disp;
257 <        double  d0, d1, h, v;
257 >        double  d0, d1, h, v, prox;
258          register VIEW   *vw;
259 <        int     hl, vl, hh, vh;
259 >        int     hh, vh;
260          int     res[2];
261          register int    i, id;
262  
# Line 235 | Line 291 | FVECT  d, p;
291                                                  (1.+DEPTHEPS)*d0 < d1))
292                          continue;                       /* occlusion error */
293                  }
238                hl = hh*odView[i].hlow/res[0];
239                vl = vh*odView[i].vlow/res[1];
240                                                /* may duplicate samples */
241                id = odAllocBlockSamp(i, hl, vl);
242                odS.ip[id][0] = hh;
243                odS.ip[id][1] = vh;
294                  if (p != NULL) {                /* compute closeness (sin^2) */
295                          d1 = DOT(disp, d);
296 <                        odS.closeness(id) = 1. - d1*d1/DOT(disp,disp);
296 >                        prox = 1. - d1*d1/DOT(disp,disp);
297                  } else
298 <                        odS.closeness(id) = 0.;
298 >                        prox = 0.;
299 >                                                /* allocate sample */
300 >                id = odAllocBlockSamp(i, hh, vh, prox);
301 >                if (id < 0)
302 >                        continue;               /* not good enough */
303                                                          /* convert color */
304                  tmCvColrs(&odS.brt[id], odS.chr[id], c, 1);
305                  if (imm_mode | needmapping)             /* if immediate mode */
# Line 253 | Line 307 | FVECT  d, p;
307                  else                                    /* else map it now */
308                          tmMapPixels(odS.rgb[id], &odS.brt[id], odS.chr[id], 1);
309                  SET4(odS.redraw, id);                   /* mark for redraw */
310 +                odView[i].n2redraw++;
311          }
312   }
313  
314  
315 < odRemap()                               /* recompute tone mapping */
315 > odRemap(newhist)                        /* recompute tone mapping */
316 > int     newhist;
317   {
318          needmapping |= NEWMAP|NEWRGB;
319 +        if (newhist)
320 +                needmapping |= NEWHIST;
321   }
322  
323  
324 + odRedrawAll()                           /* mark all samples for redraw */
325 + {
326 +        register int    i;
327 +
328 +        if ((needmapping&(NEWMAP|NEWRGB)) == (NEWMAP|NEWRGB))
329 +                return;                 /* will be called later, anyway */
330 +        for (i = odS.nsamp; i--; )
331 +                if (odS.ip[i][0] >= 0)
332 +                        SET4(odS.redraw, i);
333 +                                        /* not right, but not important */
334 +        for (i = 0; i < odNViews; i++)
335 +                odView[i].n2redraw = odView[i].snext - odView[i].sfirst;
336 + }
337 +
338 +
339   odRedraw(vn, hmin, vmin, hmax, vmax)    /* redraw view region */
340   int     vn, hmin, vmin, hmax, vmax;
341   {
# Line 289 | Line 362 | int    vn, hmin, vmin, hmax, vmax;
362                  for (j = vmin; j <= vmax; j++) {
363                          bp = odView[vn].bmap + j*odView[vn].hlow + i;
364                          for (k = bp->nsamp; k--; )
365 <                                if (odS.ip[bp->first+k][0] >= 0)
365 >                                if (odS.ip[bp->first+k][0] >= 0) {
366                                          SET4(odS.redraw, bp->first+k);
367 +                                        odView[vn].n2redraw++;
368 +                                }
369                  }
370   }
371  
# Line 303 | Line 378 | GLfloat        *dm;
378          int     i, j, hmin, hmax, vmin, vmax;
379          register int    k, l;
380  
306        DCHECK(vn<0 | vn>=odNViews, CONSISTENCY,
307                        "bad view number in odDepthMap");
381          if (dm == NULL) {                       /* free edge map */
382 +                if (vn<0 | vn>=odNViews)
383 +                        return;                 /* too late -- they're gone! */
384                  if (odView[vn].emap != NULL)
385                          free((char *)odView[vn].emap);
386                  odView[vn].emap = NULL;
387                  odView[vn].dmap = NULL;
388                  return;
389          }
390 +        DCHECK(vn<0 | vn>=odNViews, CONSISTENCY,
391 +                        "bad view number in odDepthMap");
392          odView[vn].dmap = dm;                   /* initialize edge map */
393          if (odView[vn].emap == NULL) {
394                  odView[vn].emap = (int4 *)malloc(
# Line 369 | Line 446 | GLfloat        *dm;
446   odUpdate(vn)                            /* update this view */
447   int     vn;
448   {
449 <        int     i, j;
450 <        register struct ODblock *bp;
451 <        register int    k;
449 >        static short    primes[] = {9431,6803,4177,2659,1609,887,587,251,47,1};
450 >        int     myprime;
451 >        register int    i, n;
452  
453          DCHECK(vn<0 | vn>=odNViews, CONSISTENCY,
454                          "bad view number in odUpdate");
455                                          /* need to do some tone mapping? */
456          if (needmapping & NEWRGB) {
457                  if (needmapping & NEWMAP) {
458 <                        tmClearHisto();
458 >                        if (needmapping & NEWHIST)
459 >                                tmClearHisto();
460 >                        needmapping &= ~NEWHIST;
461                          if (tmAddHisto(odS.brt,odS.nsamp,1) != TM_E_OK)
462                                  return;
463                          if (tmComputeMapping(0.,0.,0.) != TM_E_OK)
464                                  return;
465 <                        for (k = odS.nsamp; k--; )      /* redraw all */
466 <                                if (odS.ip[k][0] >= 0)
388 <                                        SET4(odS.redraw, k);
465 >                        needmapping &= ~NEWMAP;
466 >                        odRedrawAll();                  /* redraw everything */
467                  }
468                  if (tmMapPixels(odS.rgb,odS.brt,odS.chr,odS.nsamp) != TM_E_OK)
469                          return;
470 <                needmapping = 0;                /* reset flag */
470 >                needmapping &= ~NEWRGB;
471          }
472 <                                        /* draw each block in view */
473 <        for (i = odView[vn].hlow; i--; )
474 <                for (j = odView[vn].vlow; j--; ) {
475 <                                        /* get block */
476 <                        bp = odView[vn].bmap + j*odView[vn].hlow + i;
477 <                                        /* do quick, conservative flag check */
478 <                        for (k = (bp->first+bp->nsamp+31)>>5;
479 <                                        k-- > bp->first>>5; )
480 <                                if (odS.redraw[k])
481 <                                        break;          /* non-zero flag */
482 <                        if (k < bp->first>>5)
483 <                                continue;               /* no flags set */
484 <                        for (k = bp->nsamp; k--; )      /* sample by sample */
485 <                                if (CHK4(odS.redraw, bp->first+k)) {
486 <                                        odDrawBlockSamp(vn, i, j, bp->first+k);
487 <                                        CLR4(odS.redraw, bp->first+k);
488 <                                }
472 >        if (odView[vn].n2redraw <= 0)
473 >                return;
474 > #if REDRAWTHRESH
475 >        if (odView[vn].n2redraw < REDRAWTHRESH)
476 >                goto quickdraw;
477 >                                        /* pick a good prime step size */
478 >        n = odView[vn].snext - odView[vn].sfirst;
479 >        for (i = 0; primes[i]<<5 >= n; i++)
480 >                ;
481 >        while ((myprime = primes[i++]) > 1)
482 >                if (n % myprime)
483 >                        break;
484 >                                        /* dissolve in new samples */
485 >        for (i = odView[vn].sfirst; n-- > 0; i += myprime) {
486 >                if (i >= odView[vn].snext)
487 >                        i -= odView[vn].snext - odView[vn].sfirst;
488 >                if (CHK4(odS.redraw, i)) {
489 >                        odDrawSamp(vn, i);
490 >                        CLR4(odS.redraw, i);
491                  }
492 +        }
493 +        odView[vn].n2redraw = 0;
494 +        return;
495 + quickdraw:                              /* quicker sparse flag checking */
496 + #endif
497 +                                        /* redraw samples at end */
498 +        for (i = odView[vn].snext-31; i < odView[vn].snext; i++)
499 +                if (CHK4(odS.redraw, i)) {
500 +                        odDrawSamp(vn, i);
501 +                        CLR4(odS.redraw, i);
502 +                }
503 +                                        /* faster flag checks in middle */
504 +        for (n = odView[vn].snext>>5; n-- > (odView[vn].sfirst+0x1f)>>5; )
505 +                for (i = 0; odS.redraw[n]; i++)         /* skips faster */
506 +                        if (odS.redraw[n] & 1L<<i) {
507 +                                odDrawSamp(vn, (n<<5)+i);
508 +                                odS.redraw[n] &= ~(1L<<i);
509 +                        }
510 +                                        /* redraw samples at beginning */
511 +        for (i = odView[vn].sfirst; i < odView[vn].sfirst+31; i++)
512 +                if (CHK4(odS.redraw, i)) {
513 +                        odDrawSamp(vn, i);
514 +                        CLR4(odS.redraw, i);
515 +                }
516 +        odView[vn].n2redraw = 0;
517   }
518  
519  
520 +                                        /* this turned out to be unnecessary */
521   #if 0
522   static
523   clip_end(p, o, vp)                      /* clip line segment to view */
# Line 449 | Line 555 | register struct ODview *vp;
555   double  sz;
556   {
557          int     na, dv;
558 <        double  hrad, vrad, phi0, phi;
558 >        double  hrad, vrad, phi;
559          register int    i;
560  
561          DCHECK(sz > 1, CONSISTENCY, "super-unary size in make_arms");
562 <        na = MAXFAN*sz*sz + 0.5;                /* keep area constant */
562 >        na = MAXFAN*sz + 0.5;                   /* keep arc length constant */
563          if (na < MINFAN) na = MINFAN;
564          hrad = FANSIZE*sz*vp->hhi/vp->hlow;
565          vrad = FANSIZE*sz*vp->vhi/vp->vlow;
566          if (hrad*vrad < 2.25)
567                  hrad = vrad = 1.5;
462        phi0 = (2.*PI) * frandom();
568          dv = OMAXDEPTH*sz + 0.5;
569          for (i = 0; i < na; i++) {
570 <                phi = phi0 + (2.*PI)*i/na;
570 >                phi = (2.*PI)*i/na;
571                  ar[i][0] = cp[0] + tcos(phi)*hrad + 0.5;
572                  ar[i][1] = cp[1] + tsin(phi)*vrad + 0.5;
573                  ar[i][2] = dv;
# Line 515 | Line 620 | register struct ODview *vp;
620          n = rise + run;
621          while (n--)                     /* run out arm, checking depth */
622                  if (run2 > rise2) {
518                        if (depthchange(vp, x, y, x+xstep, y))
519                                break;
623                          x += xstep;
624                          rise2 += rise;
625 <                } else {
523 <                        if (depthchange(vp, x, y, x, y+ystep))
625 >                        if (depthchange(vp, x-xstep, y, x, y))
626                                  break;
627 +                } else {
628                          y += ystep;
629                          run2 += run;
630 +                        if (depthchange(vp, x, y-ystep, x, y))
631 +                                break;
632                  }
633          if (n < 0)                      /* found something? */
634                  return;
# Line 547 | Line 652 | register int   h, v;
652   }
653  
654  
655 < odDrawBlockSamp(vn, h, v, id)           /* draw sample in view block */
656 < int     vn, h, v;
655 > static int
656 > blockedge(vp, bi0, bi1)                 /* check for edge between blocks? */
657 > register struct ODview  *vp;
658 > register int    bi0, bi1;
659 > {
660 >        if (bi1 == bi0)
661 >                return(0);              /* same block */
662 >        if (bi1 < 0)
663 >                return(1);              /* end off view */
664 >        if (CHK4(vp->emap, bi1))
665 >                return(1);              /* end block has edges */
666 >        if (bi1 == bi0+1 || bi1 == bi0-1 ||
667 >                        bi1 == bi0+vp->hlow || bi1 == bi0-vp->hlow)
668 >                return(0);              /* end in adjacent block -- no edges */
669 >        return(1);                      /* conservative for rarer case */
670 > }
671 >
672 >
673 > odDrawSamp(vn, id)                      /* draw view sample */
674 > int     vn;
675   register int    id;
676   {
677          GLshort arm[MAXFAN][3];
678 <        int     narms, blockindex, bi1;
678 >        int     narms, blockindex;
679          register struct ODview  *vp;
680          double  size;
681          int     home_edges;
682          register int    i;
683  
684          vp = odView + vn;
685 <        blockindex = v*vp->hlow + h;
686 <        DCHECK(odS.ip[id][0]*vp->hlow/vp->hhi != h |
564 <                        odS.ip[id][1]*vp->vlow/vp->vhi != v,
565 <                        CONSISTENCY, "bad sample position in odDrawBlockSamp");
685 >        blockindex = getblock(vp, odS.ip[id][0], odS.ip[id][1]);
686 >        DCHECK(blockindex<0, CONSISTENCY, "bad sample handed to odDrawSamp");
687          DCHECK(vp->bmap[blockindex].nused <= 0,
688 <                        CONSISTENCY, "bad in-use count in odDrawBlockSamp");
688 >                        CONSISTENCY, "bad in-use count in odDrawSamp");
689                                          /* create triangle fan */
690          size = 1./sqrt((double)vp->bmap[blockindex].nused);
691          narms = make_arms(arm, odS.ip[id], vp, size);
692          if (vp->emap != NULL) {         /* check for edge collisions */
693                  home_edges = CHK4(vp->emap, blockindex);
694                  for (i = 0; i < narms; i++)
695 <                        /* the following test is flawed, because we could
696 <                         * be passing through a block on a diagonal run */
576 <                        if (home_edges ||
577 <                                ( (bi1 = getblock(vp, arm[i][0], arm[i][1]))
578 <                                                != blockindex &&
579 <                                        (bi1 < 0 || CHK4(vp->emap, bi1)) ))
695 >                        if (home_edges || blockedge(vp, blockindex,
696 >                                        getblock(vp, arm[i][0], arm[i][1])))
697                                  clip_edge(arm[i], odS.ip[id], vp);
698          }
699                                          /* draw triangle fan */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines