| 14 |  | #include <GL/glx.h> | 
| 15 |  | #include <GL/glu.h> | 
| 16 |  |  | 
| 17 | – | #include "random.h" | 
| 17 |  | #include "rhd_odraw.h" | 
| 18 |  |  | 
| 19 |  | #ifndef DEPTHEPS | 
| 57 |  | int     nbytes, i, j, k, nextsamp, count, blockdiv; | 
| 58 |  | int     res[2]; | 
| 59 |  |  | 
| 60 | < | if (odNViews) {                 /* deallocate view structures */ | 
| 61 | < | for (i = 0; i < odNViews; i++) { | 
| 60 | > | if (odNViews > 0) {             /* deallocate view structures */ | 
| 61 | > | for (i = odNViews; i--; ) { | 
| 62 |  | free((char *)odView[i].bmap); | 
| 63 | + | free((char *)odView[i].pmap); | 
| 64 |  | if (odView[i].emap != NULL) | 
| 65 |  | free((char *)odView[i].emap); | 
| 66 |  | } | 
| 109 |  | if (blockdiv < 8) blockdiv = 8; | 
| 110 |  | nextsamp = 0; count /= blockdiv*blockdiv;       /* # blocks */ | 
| 111 |  | while (i--) {                   /* initialize each view */ | 
| 112 | – | odView[i].emap = NULL; | 
| 113 | – | odView[i].dmap = NULL; | 
| 112 |  | dev_auxview(i, res); | 
| 113 |  | odView[i].hhi = res[0]; | 
| 114 |  | odView[i].hlow = (res[0] + blockdiv/2) / blockdiv; | 
| 116 |  | odView[i].vhi = res[1]; | 
| 117 |  | odView[i].vlow = (res[1] + blockdiv/2) / blockdiv; | 
| 118 |  | if (odView[i].vlow < 1) odView[i].vlow = 1; | 
| 119 | + | odView[i].emap = NULL; | 
| 120 | + | odView[i].dmap = NULL; | 
| 121 | + | odView[i].pmap = (int4 *)calloc(FL4NELS(res[0]*res[1]), | 
| 122 | + | sizeof(int4)); | 
| 123 | + | if (odView[i].pmap == NULL) | 
| 124 | + | return(0); | 
| 125 |  | j = odView[i].hlow*odView[i].vlow; | 
| 126 |  | odView[i].bmap = (struct ODblock *)malloc( | 
| 127 |  | j * sizeof(struct ODblock)); | 
| 130 |  | DCHECK(count<=0 | nextsamp>=n, | 
| 131 |  | CONSISTENCY, "counter botch in odInit"); | 
| 132 |  | if (!i) count = j; | 
| 133 | + | odView[i].sfirst = nextsamp; | 
| 134 |  | while (j--) {           /* initialize blocks & free lists */ | 
| 135 |  | odView[i].bmap[j].pthresh = FHUGE; | 
| 136 |  | odView[i].bmap[j].first = k = nextsamp; | 
| 142 |  | odS.nextfree(k-1) = ENDFREE; | 
| 143 |  | odView[i].bmap[j].nused = 0; | 
| 144 |  | } | 
| 145 | + | odView[i].snext = nextsamp; | 
| 146 |  | } | 
| 147 |  | CLR4ALL(odS.redraw, odS.nsamp);         /* clear redraw flags */ | 
| 148 |  | for (i = odS.nsamp; i--; ) {            /* clear values */ | 
| 185 |  | if (prox > bp->pthresh) | 
| 186 |  | return(-1);             /* worse than free list occupants */ | 
| 187 |  | /* check for duplicate pixel */ | 
| 188 | < | for (i = bp->first+bp->nsamp; i-- > bp->first; ) | 
| 188 | > | if (CHK4(odView[vn].pmap, vh*odView[vn].hhi + hh)) | 
| 189 | > | i = bp->first + bp->nsamp; | 
| 190 | > | else | 
| 191 | > | i = -1; | 
| 192 | > | while (i-- > bp->first) | 
| 193 |  | if (hh == odS.ip[i][0] && vh == odS.ip[i][1]) { /* found it! */ | 
| 194 |  | /* search free list for it */ | 
| 195 |  | if (i == bp->free) | 
| 207 |  | return(-1);     /* previous sample is fine */ | 
| 208 |  | goto gotit; | 
| 209 |  | } | 
| 210 | + | DCHECK(i>=-1, WARNING, "pixel in presence map not found in block"); | 
| 211 |  | if (bp->free != ENDFREE) {      /* allocate from free list */ | 
| 212 |  | i = bp->free; | 
| 213 | + | if (odS.ip[i][0] >= 0 & odS.ip[i][1] >= 0) | 
| 214 | + | CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi + | 
| 215 | + | odS.ip[i][0]); | 
| 216 |  | bp->free = odS.nextfree(i); | 
| 217 |  | bp->nused++; | 
| 218 |  | goto gotit; | 
| 236 |  | bp->nused--; | 
| 237 |  | } | 
| 238 |  | i = si[0];                      /* use worst sample */ | 
| 239 | + | CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi + odS.ip[i][0]); | 
| 240 |  | gotit: | 
| 241 |  | odS.ip[i][0] = hh; | 
| 242 |  | odS.ip[i][1] = vh; | 
| 243 |  | odS.closeness(i) = prox; | 
| 244 | + | SET4(odView[vn].pmap, vh*odView[vn].hhi + hh); | 
| 245 |  | return(i); | 
| 246 |  | } | 
| 247 |  |  | 
| 317 |  | } | 
| 318 |  |  | 
| 319 |  |  | 
| 320 | + | odRedrawAll()                           /* mark all samples for redraw */ | 
| 321 | + | { | 
| 322 | + | register int    i; | 
| 323 | + |  | 
| 324 | + | if ((needmapping&(NEWMAP|NEWRGB)) == (NEWMAP|NEWRGB)) | 
| 325 | + | return;                 /* will be called later, anyway */ | 
| 326 | + | for (i = odS.nsamp; i--; ) | 
| 327 | + | if (odS.ip[i][0] >= 0) | 
| 328 | + | SET4(odS.redraw, i); | 
| 329 | + | } | 
| 330 | + |  | 
| 331 | + |  | 
| 332 |  | odRedraw(vn, hmin, vmin, hmax, vmax)    /* redraw view region */ | 
| 333 |  | int     vn, hmin, vmin, hmax, vmax; | 
| 334 |  | { | 
| 437 |  | odUpdate(vn)                            /* update this view */ | 
| 438 |  | int     vn; | 
| 439 |  | { | 
| 440 | < | int     i, j; | 
| 413 | < | register struct ODblock *bp; | 
| 414 | < | register int    k; | 
| 440 | > | register int    i, j; | 
| 441 |  |  | 
| 442 |  | DCHECK(vn<0 | vn>=odNViews, CONSISTENCY, | 
| 443 |  | "bad view number in odUpdate"); | 
| 446 |  | if (needmapping & NEWMAP) { | 
| 447 |  | if (needmapping & NEWHIST) | 
| 448 |  | tmClearHisto(); | 
| 449 | + | needmapping &= ~NEWHIST; | 
| 450 |  | if (tmAddHisto(odS.brt,odS.nsamp,1) != TM_E_OK) | 
| 451 |  | return; | 
| 452 |  | if (tmComputeMapping(0.,0.,0.) != TM_E_OK) | 
| 453 |  | return; | 
| 454 | < | for (k = odS.nsamp; k--; )      /* redraw all */ | 
| 455 | < | if (odS.ip[k][0] >= 0) | 
| 429 | < | SET4(odS.redraw, k); | 
| 454 | > | needmapping &= ~NEWMAP; | 
| 455 | > | odRedrawAll();                  /* redraw everything */ | 
| 456 |  | } | 
| 457 |  | if (tmMapPixels(odS.rgb,odS.brt,odS.chr,odS.nsamp) != TM_E_OK) | 
| 458 |  | return; | 
| 459 | < | needmapping = 0;                /* reset flag */ | 
| 459 | > | needmapping &= ~NEWRGB; | 
| 460 |  | } | 
| 461 | < | /* draw each block in view */ | 
| 462 | < | for (j = odView[vn].vlow; j--; ) | 
| 463 | < | for (i = 0; i < odView[vn].hlow; i++) { | 
| 464 | < | /* get block */ | 
| 465 | < | bp = odView[vn].bmap + j*odView[vn].hlow + i; | 
| 466 | < | /* do quick, conservative flag check */ | 
| 441 | < | for (k = (bp->first+bp->nsamp+31)>>5; | 
| 442 | < | k-- > bp->first>>5; ) | 
| 443 | < | if (odS.redraw[k]) | 
| 444 | < | break;          /* non-zero flag */ | 
| 445 | < | if (k < bp->first>>5) | 
| 446 | < | continue;               /* no flags set */ | 
| 447 | < | for (k = bp->nsamp; k--; )      /* sample by sample */ | 
| 448 | < | if (CHK4(odS.redraw, bp->first+k)) { | 
| 449 | < | odDrawBlockSamp(vn, i, j, bp->first+k); | 
| 450 | < | CLR4(odS.redraw, bp->first+k); | 
| 451 | < | } | 
| 461 | > | /* this code segment was too slow */ | 
| 462 | > | #if 0 | 
| 463 | > | for (i = odView[vn].sfirst; i < odView[vn].snext; i++) | 
| 464 | > | if (CHK4(odS.redraw, i)) { | 
| 465 | > | odDrawSamp(vn, i); | 
| 466 | > | CLR4(odS.redraw, i); | 
| 467 |  | } | 
| 468 | + | #else | 
| 469 | + | /* redraw samples at each end */ | 
| 470 | + | for (i = odView[vn].sfirst; i < odView[vn].sfirst+31; i++) | 
| 471 | + | if (CHK4(odS.redraw, i)) { | 
| 472 | + | odDrawSamp(vn, i); | 
| 473 | + | CLR4(odS.redraw, i); | 
| 474 | + | } | 
| 475 | + | for (i = odView[vn].snext-31; i < odView[vn].snext; i++) | 
| 476 | + | if (CHK4(odS.redraw, i)) { | 
| 477 | + | odDrawSamp(vn, i); | 
| 478 | + | CLR4(odS.redraw, i); | 
| 479 | + | } | 
| 480 | + | /* faster flag checks in middle */ | 
| 481 | + | for (j = odView[vn].snext>>5; j-- > (odView[vn].sfirst+0x1f)>>5; ) | 
| 482 | + | for (i = 0; odS.redraw[j]; i++)         /* skips faster */ | 
| 483 | + | if (odS.redraw[j] & 1L<<i) { | 
| 484 | + | odDrawSamp(vn, (j<<5)+i); | 
| 485 | + | odS.redraw[j] &= ~(1L<<i); | 
| 486 | + | } | 
| 487 | + | #endif | 
| 488 |  | } | 
| 489 |  |  | 
| 490 |  |  | 
| 491 | + | /* this turned out to be unnecessary */ | 
| 492 |  | #if 0 | 
| 493 |  | static | 
| 494 |  | clip_end(p, o, vp)                      /* clip line segment to view */ | 
| 526 |  | double  sz; | 
| 527 |  | { | 
| 528 |  | int     na, dv; | 
| 529 | < | double  hrad, vrad, phi0, phi; | 
| 529 | > | double  hrad, vrad, phi; | 
| 530 |  | register int    i; | 
| 531 |  |  | 
| 532 |  | DCHECK(sz > 1, CONSISTENCY, "super-unary size in make_arms"); | 
| 536 |  | vrad = FANSIZE*sz*vp->vhi/vp->vlow; | 
| 537 |  | if (hrad*vrad < 2.25) | 
| 538 |  | hrad = vrad = 1.5; | 
| 503 | – | phi0 = (2.*PI) * frandom(); | 
| 539 |  | dv = OMAXDEPTH*sz + 0.5; | 
| 540 |  | for (i = 0; i < na; i++) { | 
| 541 | < | phi = phi0 + (2.*PI)*i/na; | 
| 541 | > | phi = (2.*PI)*i/na; | 
| 542 |  | ar[i][0] = cp[0] + tcos(phi)*hrad + 0.5; | 
| 543 |  | ar[i][1] = cp[1] + tsin(phi)*vrad + 0.5; | 
| 544 |  | ar[i][2] = dv; | 
| 623 |  | } | 
| 624 |  |  | 
| 625 |  |  | 
| 626 | < | odDrawBlockSamp(vn, h, v, id)           /* draw sample in view block */ | 
| 627 | < | int     vn, h, v; | 
| 626 | > | static int | 
| 627 | > | blockedge(vp, bi0, bi1)                 /* check for edge between blocks? */ | 
| 628 | > | register struct ODview  *vp; | 
| 629 | > | register int    bi0, bi1; | 
| 630 | > | { | 
| 631 | > | if (bi1 < 0) | 
| 632 | > | return(1);              /* end off view */ | 
| 633 | > | if (CHK4(vp->emap, bi1)) | 
| 634 | > | return(1);              /* end has edges */ | 
| 635 | > | if (bi1 == bi0+1 || bi1 == bi0-1 || | 
| 636 | > | bi1 == bi0+vp->hlow || bi1 == bi0-vp->hlow) | 
| 637 | > | return(0);              /* end in adjacent block -- no edges */ | 
| 638 | > | return(1);                      /* conservative for rarer case */ | 
| 639 | > | } | 
| 640 | > |  | 
| 641 | > |  | 
| 642 | > | odDrawSamp(vn, id)                      /* draw view sample */ | 
| 643 | > | int     vn; | 
| 644 |  | register int    id; | 
| 645 |  | { | 
| 646 |  | GLshort arm[MAXFAN][3]; | 
| 647 | < | int     narms, blockindex, bi1; | 
| 647 | > | int     narms, blockindex; | 
| 648 |  | register struct ODview  *vp; | 
| 649 |  | double  size; | 
| 650 |  | int     home_edges; | 
| 651 |  | register int    i; | 
| 652 |  |  | 
| 653 |  | vp = odView + vn; | 
| 654 | < | blockindex = v*vp->hlow + h; | 
| 655 | < | DCHECK(odS.ip[id][0]*vp->hlow/vp->hhi != h | | 
| 605 | < | odS.ip[id][1]*vp->vlow/vp->vhi != v, | 
| 606 | < | CONSISTENCY, "bad sample position in odDrawBlockSamp"); | 
| 654 | > | blockindex = getblock(vp, odS.ip[id][0], odS.ip[id][1]); | 
| 655 | > | DCHECK(blockindex<0, CONSISTENCY, "bad sample handed to odDrawSamp"); | 
| 656 |  | DCHECK(vp->bmap[blockindex].nused <= 0, | 
| 657 | < | CONSISTENCY, "bad in-use count in odDrawBlockSamp"); | 
| 657 | > | CONSISTENCY, "bad in-use count in odDrawSamp"); | 
| 658 |  | /* create triangle fan */ | 
| 659 |  | size = 1./sqrt((double)vp->bmap[blockindex].nused); | 
| 660 |  | narms = make_arms(arm, odS.ip[id], vp, size); | 
| 661 |  | if (vp->emap != NULL) {         /* check for edge collisions */ | 
| 662 |  | home_edges = CHK4(vp->emap, blockindex); | 
| 663 |  | for (i = 0; i < narms; i++) | 
| 664 | < | /* the following test is flawed, because we could | 
| 665 | < | * be passing through a block on a diagonal run */ | 
| 617 | < | if (home_edges || | 
| 618 | < | ( (bi1 = getblock(vp, arm[i][0], arm[i][1])) | 
| 619 | < | != blockindex && | 
| 620 | < | (bi1 < 0 || CHK4(vp->emap, bi1)) )) | 
| 664 | > | if (home_edges || blockedge(vp, blockindex, | 
| 665 | > | getblock(vp, arm[i][0], arm[i][1]))) | 
| 666 |  | clip_edge(arm[i], odS.ip[id], vp); | 
| 667 |  | } | 
| 668 |  | /* draw triangle fan */ |