| 1 | – | /* Copyright (c) 1998 Silicon Graphics, Inc. */ | 
| 2 | – |  | 
| 1 |  | #ifndef lint | 
| 2 | < | static char SCCSid[] = "$SunId$ SGI"; | 
| 2 | > | static const char       RCSid[] = "$Id$"; | 
| 3 |  | #endif | 
| 6 | – |  | 
| 4 |  | /* | 
| 5 |  | * Routines for drawing samples using depth buffer checks. | 
| 6 |  | */ | 
| 7 |  |  | 
| 8 |  | #include "standard.h" | 
| 9 |  |  | 
| 13 | – | #include <sys/types.h> | 
| 10 |  | #include <GL/glx.h> | 
| 11 |  | #include <GL/glu.h> | 
| 12 |  |  | 
| 17 | – | #include "random.h" | 
| 13 |  | #include "rhd_odraw.h" | 
| 14 |  |  | 
| 15 |  | #ifndef DEPTHEPS | 
| 21 |  | #ifndef SFREEFRAC | 
| 22 |  | #define SFREEFRAC       0.2             /* fraction to free at a time */ | 
| 23 |  | #endif | 
| 24 | + | #ifndef REDRAWTHRESH | 
| 25 | + | #define REDRAWTHRESH    10240           /* number of samples for dissolve */ | 
| 26 | + | #endif | 
| 27 |  | #ifndef MAXFAN | 
| 28 |  | #define MAXFAN          32              /* maximum arms in a triangle fan */ | 
| 29 |  | #endif | 
| 47 |  |  | 
| 48 |  |  | 
| 49 |  | #define SAMP32  (32*(2*sizeof(short)+sizeof(union ODfunion)+sizeof(TMbright)+\ | 
| 50 | < | 6*sizeof(BYTE))+sizeof(int4)) | 
| 50 | > | 6*sizeof(BYTE))+sizeof(int32)) | 
| 51 |  |  | 
| 52 | < | int | 
| 53 | < | odInit(n)                               /* initialize drawing routines */ | 
| 54 | < | int     n; | 
| 52 | > | static int sampcmp(const void *s0, const void *s1); | 
| 53 | > | static int odAllocBlockSamp(int vn, int hh, int vh, double prox); | 
| 54 | > | static int make_arms(GLshort ar[MAXFAN][3], short cp[2], struct ODview *vp, | 
| 55 | > | double sz); | 
| 56 | > | static int depthchange(struct ODview *vp, int x0, int y0, int x1, int y1); | 
| 57 | > | static void clip_edge(GLshort p[3], short o[2], struct ODview *vp); | 
| 58 | > | static int getblock(struct ODview *vp, int h, int v); | 
| 59 | > | static int blockedge(struct ODview *vp, int bi0, int bi1); | 
| 60 | > | static void odDrawSamp(int vn, int id); | 
| 61 | > |  | 
| 62 | > |  | 
| 63 | > | extern int | 
| 64 | > | odInit(                         /* initialize drawing routines */ | 
| 65 | > | int     n | 
| 66 | > | ) | 
| 67 |  | { | 
| 68 |  | int     nbytes, i, j, k, nextsamp, count, blockdiv; | 
| 69 |  | int     res[2]; | 
| 70 |  |  | 
| 71 | < | if (odNViews) {                 /* deallocate view structures */ | 
| 72 | < | for (i = 0; i < odNViews; i++) { | 
| 73 | < | free((char *)odView[i].bmap); | 
| 71 | > | if (odNViews > 0) {             /* deallocate view structures */ | 
| 72 | > | for (i = odNViews; i--; ) { | 
| 73 | > | free((void *)odView[i].bmap); | 
| 74 | > | free((void *)odView[i].pmap); | 
| 75 |  | if (odView[i].emap != NULL) | 
| 76 | < | free((char *)odView[i].emap); | 
| 76 | > | free((void *)odView[i].emap); | 
| 77 |  | } | 
| 78 | < | free((char *)odView); | 
| 78 | > | free((void *)odView); | 
| 79 |  | odView = NULL; | 
| 80 |  | odNViews = 0; | 
| 81 |  | } | 
| 99 |  | return(0); | 
| 100 |  | /* assign larger alignment types earlier */ | 
| 101 |  | odS.f = (union ODfunion *)odS.base; | 
| 102 | < | odS.redraw = (int4 *)(odS.f + n); | 
| 102 | > | odS.redraw = (int32 *)(odS.f + n); | 
| 103 |  | odS.ip = (short (*)[2])(odS.redraw + n/32); | 
| 104 |  | odS.brt = (TMbright *)(odS.ip + n); | 
| 105 |  | odS.chr = (BYTE (*)[3])(odS.brt + n); | 
| 120 |  | if (blockdiv < 8) blockdiv = 8; | 
| 121 |  | nextsamp = 0; count /= blockdiv*blockdiv;       /* # blocks */ | 
| 122 |  | while (i--) {                   /* initialize each view */ | 
| 112 | – | odView[i].emap = NULL; | 
| 113 | – | odView[i].dmap = NULL; | 
| 123 |  | dev_auxview(i, res); | 
| 124 |  | odView[i].hhi = res[0]; | 
| 125 |  | odView[i].hlow = (res[0] + blockdiv/2) / blockdiv; | 
| 127 |  | odView[i].vhi = res[1]; | 
| 128 |  | odView[i].vlow = (res[1] + blockdiv/2) / blockdiv; | 
| 129 |  | if (odView[i].vlow < 1) odView[i].vlow = 1; | 
| 130 | + | odView[i].emap = NULL; | 
| 131 | + | odView[i].dmap = NULL; | 
| 132 | + | odView[i].pmap = (int32 *)calloc(FL4NELS(res[0]*res[1]), | 
| 133 | + | sizeof(int32)); | 
| 134 | + | if (odView[i].pmap == NULL) | 
| 135 | + | return(0); | 
| 136 |  | j = odView[i].hlow*odView[i].vlow; | 
| 137 |  | odView[i].bmap = (struct ODblock *)malloc( | 
| 138 |  | j * sizeof(struct ODblock)); | 
| 141 |  | DCHECK(count<=0 | nextsamp>=n, | 
| 142 |  | CONSISTENCY, "counter botch in odInit"); | 
| 143 |  | if (!i) count = j; | 
| 144 | + | odView[i].sfirst = nextsamp; | 
| 145 |  | while (j--) {           /* initialize blocks & free lists */ | 
| 146 |  | odView[i].bmap[j].pthresh = FHUGE; | 
| 147 |  | odView[i].bmap[j].first = k = nextsamp; | 
| 153 |  | odS.nextfree(k-1) = ENDFREE; | 
| 154 |  | odView[i].bmap[j].nused = 0; | 
| 155 |  | } | 
| 156 | + | odView[i].snext = nextsamp; | 
| 157 | + | odView[i].n2redraw = 0; | 
| 158 |  | } | 
| 159 |  | CLR4ALL(odS.redraw, odS.nsamp);         /* clear redraw flags */ | 
| 160 |  | for (i = odS.nsamp; i--; ) {            /* clear values */ | 
| 169 |  |  | 
| 170 |  |  | 
| 171 |  | int | 
| 172 | < | sampcmp(s0, s1)                 /* sample order, descending proximity */ | 
| 173 | < | int     *s0, *s1; | 
| 172 | > | sampcmp(                        /* sample order, descending proximity */ | 
| 173 | > | const void      *s0, | 
| 174 | > | const void      *s1 | 
| 175 | > | ) | 
| 176 |  | { | 
| 177 | < | register double diff = odS.closeness(*s1) - odS.closeness(*s0); | 
| 177 | > | register double diff = odS.closeness(*(int*)s1) - odS.closeness(*(int*)s0); | 
| 178 |  |  | 
| 179 |  | return (diff > FTINY ? 1 : diff < -FTINY ? -1 : 0); | 
| 180 |  | } | 
| 181 |  |  | 
| 182 |  |  | 
| 183 |  | int | 
| 184 | < | odAllocBlockSamp(vn, hh, vh, prox)      /* allocate sample from block */ | 
| 185 | < | int     vn, hh, vh; | 
| 186 | < | double  prox; | 
| 184 | > | odAllocBlockSamp(       /* allocate sample from block */ | 
| 185 | > | int     vn, | 
| 186 | > | int     hh, | 
| 187 | > | int     vh, | 
| 188 | > | double  prox | 
| 189 | > | ) | 
| 190 |  | { | 
| 191 |  | int     si[SAMPSPERBLOCK+SAMPSPERBLOCK/4]; | 
| 192 |  | int     hl, vl; | 
| 193 |  | VIEW    *vw; | 
| 171 | – | FVECT   ro, rd; | 
| 194 |  | int     res[2]; | 
| 195 |  | register struct ODblock *bp; | 
| 196 |  | register int    i, j; | 
| 201 |  | if (prox > bp->pthresh) | 
| 202 |  | return(-1);             /* worse than free list occupants */ | 
| 203 |  | /* check for duplicate pixel */ | 
| 204 | < | for (i = bp->first+bp->nsamp; i-- > bp->first; ) | 
| 204 | > | if (CHK4(odView[vn].pmap, vh*odView[vn].hhi + hh)) | 
| 205 | > | i = bp->first + bp->nsamp; | 
| 206 | > | else | 
| 207 | > | i = 0; | 
| 208 | > | while (i-- > bp->first) | 
| 209 |  | if (hh == odS.ip[i][0] && vh == odS.ip[i][1]) { /* found it! */ | 
| 210 |  | /* search free list for it */ | 
| 211 |  | if (i == bp->free) | 
| 219 |  | bp->nused++; | 
| 220 |  | goto gotit; | 
| 221 |  | } | 
| 222 | < | if (prox >= 0.999*odS.closeness(i)) | 
| 222 | > | if (prox >= 0.99*odS.closeness(i)) | 
| 223 |  | return(-1);     /* previous sample is fine */ | 
| 224 |  | goto gotit; | 
| 225 |  | } | 
| 226 |  | if (bp->free != ENDFREE) {      /* allocate from free list */ | 
| 227 |  | i = bp->free; | 
| 228 | + | if ((odS.ip[i][0] >= 0) & (odS.ip[i][1] >= 0)) | 
| 229 | + | CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi + | 
| 230 | + | odS.ip[i][0]); | 
| 231 |  | bp->free = odS.nextfree(i); | 
| 232 |  | bp->nused++; | 
| 233 |  | goto gotit; | 
| 251 |  | bp->nused--; | 
| 252 |  | } | 
| 253 |  | i = si[0];                      /* use worst sample */ | 
| 254 | + | CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi + odS.ip[i][0]); | 
| 255 |  | gotit: | 
| 256 |  | odS.ip[i][0] = hh; | 
| 257 |  | odS.ip[i][1] = vh; | 
| 258 |  | odS.closeness(i) = prox; | 
| 259 | + | SET4(odView[vn].pmap, vh*odView[vn].hhi + hh); | 
| 260 |  | return(i); | 
| 261 |  | } | 
| 262 |  |  | 
| 263 |  |  | 
| 264 | < | odSample(c, d, p)                       /* add a sample value */ | 
| 265 | < | COLR    c; | 
| 266 | < | FVECT   d, p; | 
| 264 | > | extern void | 
| 265 | > | odSample(                       /* add a sample value */ | 
| 266 | > | COLR    c, | 
| 267 | > | FVECT   d, | 
| 268 | > | FVECT   p | 
| 269 | > | ) | 
| 270 |  | { | 
| 271 |  | FVECT   disp; | 
| 272 |  | double  d0, d1, h, v, prox; | 
| 316 |  | if (id < 0) | 
| 317 |  | continue;               /* not good enough */ | 
| 318 |  | /* convert color */ | 
| 319 | < | tmCvColrs(&odS.brt[id], odS.chr[id], c, 1); | 
| 319 | > | tmCvColrs(&odS.brt[id], odS.chr[id], (COLR *)c, 1); | 
| 320 |  | if (imm_mode | needmapping)             /* if immediate mode */ | 
| 321 |  | needmapping |= NEWRGB;          /* map it later */ | 
| 322 |  | else                                    /* else map it now */ | 
| 323 |  | tmMapPixels(odS.rgb[id], &odS.brt[id], odS.chr[id], 1); | 
| 324 |  | SET4(odS.redraw, id);                   /* mark for redraw */ | 
| 325 | + | odView[i].n2redraw++; | 
| 326 |  | } | 
| 327 |  | } | 
| 328 |  |  | 
| 329 |  |  | 
| 330 | < | odRemap(newhist)                        /* recompute tone mapping */ | 
| 331 | < | int     newhist; | 
| 330 | > | extern void | 
| 331 | > | odRemap(                        /* recompute tone mapping */ | 
| 332 | > | int     newhist | 
| 333 | > | ) | 
| 334 |  | { | 
| 335 |  | needmapping |= NEWMAP|NEWRGB; | 
| 336 |  | if (newhist) | 
| 338 |  | } | 
| 339 |  |  | 
| 340 |  |  | 
| 341 | < | odRedraw(vn, hmin, vmin, hmax, vmax)    /* redraw view region */ | 
| 342 | < | int     vn, hmin, vmin, hmax, vmax; | 
| 341 | > | extern void | 
| 342 | > | odRedrawAll(void)                               /* mark all samples for redraw */ | 
| 343 |  | { | 
| 344 | + | register int    i; | 
| 345 | + |  | 
| 346 | + | if ((needmapping&(NEWMAP|NEWRGB)) == (NEWMAP|NEWRGB)) | 
| 347 | + | return;                 /* will be called later, anyway */ | 
| 348 | + | for (i = odS.nsamp; i--; ) | 
| 349 | + | if (odS.ip[i][0] >= 0) | 
| 350 | + | SET4(odS.redraw, i); | 
| 351 | + | /* not right, but not important */ | 
| 352 | + | for (i = 0; i < odNViews; i++) | 
| 353 | + | odView[i].n2redraw = odView[i].snext - odView[i].sfirst; | 
| 354 | + | } | 
| 355 | + |  | 
| 356 | + |  | 
| 357 | + | extern void | 
| 358 | + | odRedraw(       /* redraw view region */ | 
| 359 | + | int     vn, | 
| 360 | + | int     hmin, | 
| 361 | + | int     vmin, | 
| 362 | + | int     hmax, | 
| 363 | + | int     vmax | 
| 364 | + | ) | 
| 365 | + | { | 
| 366 |  | int     i, j; | 
| 367 |  | register struct ODblock *bp; | 
| 368 |  | register int    k; | 
| 369 |  |  | 
| 370 | < | if (vn<0 | vn>=odNViews) | 
| 370 | > | if ((vn<0) | (vn>=odNViews)) | 
| 371 |  | return; | 
| 372 |  | /* check view limits */ | 
| 373 |  | if (hmin < 0) hmin = 0; | 
| 374 |  | if (hmax >= odView[vn].hhi) hmax = odView[vn].hhi-1; | 
| 375 |  | if (vmin < 0) vmin = 0; | 
| 376 |  | if (vmax >= odView[vn].vhi) vmax = odView[vn].vhi-1; | 
| 377 | < | if (hmax <= hmin | vmax <= vmin) | 
| 377 | > | if ((hmax <= hmin) | (vmax <= vmin)) | 
| 378 |  | return; | 
| 379 |  | /* convert to low resolution */ | 
| 380 |  | hmin = hmin * odView[vn].hlow / odView[vn].hhi; | 
| 386 |  | for (j = vmin; j <= vmax; j++) { | 
| 387 |  | bp = odView[vn].bmap + j*odView[vn].hlow + i; | 
| 388 |  | for (k = bp->nsamp; k--; ) | 
| 389 | < | if (odS.ip[bp->first+k][0] >= 0) | 
| 389 | > | if (odS.ip[bp->first+k][0] >= 0) { | 
| 390 |  | SET4(odS.redraw, bp->first+k); | 
| 391 | + | odView[vn].n2redraw++; | 
| 392 | + | } | 
| 393 |  | } | 
| 394 |  | } | 
| 395 |  |  | 
| 396 |  |  | 
| 397 | < | odDepthMap(vn, dm)                      /* assign depth map for view */ | 
| 398 | < | int     vn; | 
| 399 | < | GLfloat *dm; | 
| 397 | > | extern void | 
| 398 | > | odDepthMap(                     /* assign depth map for view */ | 
| 399 | > | int     vn, | 
| 400 | > | GLfloat *dm | 
| 401 | > | ) | 
| 402 |  | { | 
| 403 |  | double  d0, d1; | 
| 404 |  | int     i, j, hmin, hmax, vmin, vmax; | 
| 405 |  | register int    k, l; | 
| 406 |  |  | 
| 407 |  | if (dm == NULL) {                       /* free edge map */ | 
| 408 | < | if (vn<0 | vn>=odNViews) | 
| 408 | > | if ((vn<0) | (vn>=odNViews)) | 
| 409 |  | return;                 /* too late -- they're gone! */ | 
| 410 |  | if (odView[vn].emap != NULL) | 
| 411 | < | free((char *)odView[vn].emap); | 
| 411 | > | free((void *)odView[vn].emap); | 
| 412 |  | odView[vn].emap = NULL; | 
| 413 |  | odView[vn].dmap = NULL; | 
| 414 |  | return; | 
| 417 |  | "bad view number in odDepthMap"); | 
| 418 |  | odView[vn].dmap = dm;                   /* initialize edge map */ | 
| 419 |  | if (odView[vn].emap == NULL) { | 
| 420 | < | odView[vn].emap = (int4 *)malloc( | 
| 421 | < | FL4NELS(odView[vn].hlow*odView[vn].vlow)*sizeof(int4)); | 
| 420 | > | odView[vn].emap = (int32 *)malloc( | 
| 421 | > | FL4NELS(odView[vn].hlow*odView[vn].vlow)*sizeof(int32)); | 
| 422 |  | if (odView[vn].emap == NULL) | 
| 423 |  | error(SYSTEM, "out of memory in odDepthMap"); | 
| 424 |  | } | 
| 469 |  | } | 
| 470 |  |  | 
| 471 |  |  | 
| 472 | < | odUpdate(vn)                            /* update this view */ | 
| 473 | < | int     vn; | 
| 472 | > | extern void | 
| 473 | > | odUpdate(                               /* update this view */ | 
| 474 | > | int     vn | 
| 475 | > | ) | 
| 476 |  | { | 
| 477 | < | int     i, j; | 
| 478 | < | register struct ODblock *bp; | 
| 479 | < | register int    k; | 
| 477 | > | static short    primes[] = {9431,6803,4177,2659,1609,887,587,251,47,1}; | 
| 478 | > | int     myprime; | 
| 479 | > | register int    i, n; | 
| 480 |  |  | 
| 481 |  | DCHECK(vn<0 | vn>=odNViews, CONSISTENCY, | 
| 482 |  | "bad view number in odUpdate"); | 
| 485 |  | if (needmapping & NEWMAP) { | 
| 486 |  | if (needmapping & NEWHIST) | 
| 487 |  | tmClearHisto(); | 
| 488 | + | needmapping &= ~NEWHIST; | 
| 489 |  | if (tmAddHisto(odS.brt,odS.nsamp,1) != TM_E_OK) | 
| 490 |  | return; | 
| 491 |  | if (tmComputeMapping(0.,0.,0.) != TM_E_OK) | 
| 492 |  | return; | 
| 493 | < | for (k = odS.nsamp; k--; )      /* redraw all */ | 
| 494 | < | if (odS.ip[k][0] >= 0) | 
| 429 | < | SET4(odS.redraw, k); | 
| 493 | > | needmapping &= ~NEWMAP; | 
| 494 | > | odRedrawAll();                  /* redraw everything */ | 
| 495 |  | } | 
| 496 | < | if (tmMapPixels(odS.rgb,odS.brt,odS.chr,odS.nsamp) != TM_E_OK) | 
| 496 | > | if (tmMapPixels((BYTE *)(odS.rgb), odS.brt, | 
| 497 | > | (BYTE *)(odS.chr), odS.nsamp) != TM_E_OK) | 
| 498 |  | return; | 
| 499 | < | needmapping = 0;                /* reset flag */ | 
| 499 | > | needmapping &= ~NEWRGB; | 
| 500 |  | } | 
| 501 | < | /* draw each block in view */ | 
| 502 | < | for (j = odView[vn].vlow; j--; ) | 
| 503 | < | for (i = 0; i < odView[vn].hlow; i++) { | 
| 504 | < | /* get block */ | 
| 505 | < | bp = odView[vn].bmap + j*odView[vn].hlow + i; | 
| 506 | < | /* do quick, conservative flag check */ | 
| 507 | < | for (k = (bp->first+bp->nsamp+31)>>5; | 
| 508 | < | k-- > bp->first>>5; ) | 
| 509 | < | if (odS.redraw[k]) | 
| 510 | < | break;          /* non-zero flag */ | 
| 511 | < | if (k < bp->first>>5) | 
| 512 | < | continue;               /* no flags set */ | 
| 513 | < | for (k = bp->nsamp; k--; )      /* sample by sample */ | 
| 514 | < | if (CHK4(odS.redraw, bp->first+k)) { | 
| 515 | < | odDrawBlockSamp(vn, i, j, bp->first+k); | 
| 516 | < | CLR4(odS.redraw, bp->first+k); | 
| 517 | < | } | 
| 501 | > | if (odView[vn].n2redraw <= 0) | 
| 502 | > | return; | 
| 503 | > | #if REDRAWTHRESH | 
| 504 | > | if (odView[vn].n2redraw < REDRAWTHRESH) | 
| 505 | > | goto quickdraw; | 
| 506 | > | /* pick a good prime step size */ | 
| 507 | > | n = odView[vn].snext - odView[vn].sfirst; | 
| 508 | > | for (i = 0; primes[i]<<5 >= n; i++) | 
| 509 | > | ; | 
| 510 | > | while ((myprime = primes[i++]) > 1) | 
| 511 | > | if (n % myprime) | 
| 512 | > | break; | 
| 513 | > | /* dissolve in new samples */ | 
| 514 | > | for (i = odView[vn].sfirst; n-- > 0; i += myprime) { | 
| 515 | > | if (i >= odView[vn].snext) | 
| 516 | > | i -= odView[vn].snext - odView[vn].sfirst; | 
| 517 | > | if (CHK4(odS.redraw, i)) { | 
| 518 | > | odDrawSamp(vn, i); | 
| 519 | > | CLR4(odS.redraw, i); | 
| 520 |  | } | 
| 521 | + | } | 
| 522 | + | odView[vn].n2redraw = 0; | 
| 523 | + | return; | 
| 524 | + | quickdraw:                              /* quicker sparse flag checking */ | 
| 525 | + | #endif | 
| 526 | + | /* redraw samples at end */ | 
| 527 | + | for (i = odView[vn].snext-31; i < odView[vn].snext; i++) | 
| 528 | + | if (CHK4(odS.redraw, i)) { | 
| 529 | + | odDrawSamp(vn, i); | 
| 530 | + | CLR4(odS.redraw, i); | 
| 531 | + | } | 
| 532 | + | /* faster flag checks in middle */ | 
| 533 | + | for (n = odView[vn].snext>>5; n-- > (odView[vn].sfirst+0x1f)>>5; ) | 
| 534 | + | for (i = 0; odS.redraw[n]; i++)         /* skips faster */ | 
| 535 | + | if (odS.redraw[n] & 1L<<i) { | 
| 536 | + | odDrawSamp(vn, (n<<5)+i); | 
| 537 | + | odS.redraw[n] &= ~(1L<<i); | 
| 538 | + | } | 
| 539 | + | /* redraw samples at beginning */ | 
| 540 | + | for (i = odView[vn].sfirst; i < odView[vn].sfirst+31; i++) | 
| 541 | + | if (CHK4(odS.redraw, i)) { | 
| 542 | + | odDrawSamp(vn, i); | 
| 543 | + | CLR4(odS.redraw, i); | 
| 544 | + | } | 
| 545 | + | odView[vn].n2redraw = 0; | 
| 546 |  | } | 
| 547 |  |  | 
| 548 |  |  | 
| 549 | + | /* this turned out to be unnecessary */ | 
| 550 |  | #if 0 | 
| 551 |  | static | 
| 552 |  | clip_end(p, o, vp)                      /* clip line segment to view */ | 
| 577 |  |  | 
| 578 |  |  | 
| 579 |  | static int | 
| 580 | < | make_arms(ar, cp, vp, sz)               /* make arms for triangle fan */ | 
| 581 | < | GLshort ar[MAXFAN][3]; | 
| 582 | < | short   cp[2]; | 
| 583 | < | register struct ODview  *vp; | 
| 584 | < | double  sz; | 
| 580 | > | make_arms(              /* make arms for triangle fan */ | 
| 581 | > | GLshort ar[MAXFAN][3], | 
| 582 | > | short   cp[2], | 
| 583 | > | register struct ODview  *vp, | 
| 584 | > | double  sz | 
| 585 | > | ) | 
| 586 |  | { | 
| 587 |  | int     na, dv; | 
| 588 | < | double  hrad, vrad, phi0, phi; | 
| 588 | > | double  hrad, vrad, phi; | 
| 589 |  | register int    i; | 
| 590 |  |  | 
| 591 |  | DCHECK(sz > 1, CONSISTENCY, "super-unary size in make_arms"); | 
| 592 | < | na = MAXFAN*sz*sz + 0.5;                /* keep area constant */ | 
| 592 | > | na = MAXFAN*sz + 0.5;                   /* keep arc length constant */ | 
| 593 |  | if (na < MINFAN) na = MINFAN; | 
| 594 |  | hrad = FANSIZE*sz*vp->hhi/vp->hlow; | 
| 595 |  | vrad = FANSIZE*sz*vp->vhi/vp->vlow; | 
| 596 |  | if (hrad*vrad < 2.25) | 
| 597 |  | hrad = vrad = 1.5; | 
| 503 | – | phi0 = (2.*PI) * frandom(); | 
| 598 |  | dv = OMAXDEPTH*sz + 0.5; | 
| 599 |  | for (i = 0; i < na; i++) { | 
| 600 | < | phi = phi0 + (2.*PI)*i/na; | 
| 600 | > | phi = (2.*PI)*i/na; | 
| 601 |  | ar[i][0] = cp[0] + tcos(phi)*hrad + 0.5; | 
| 602 |  | ar[i][1] = cp[1] + tsin(phi)*vrad + 0.5; | 
| 603 |  | ar[i][2] = dv; | 
| 608 |  |  | 
| 609 |  |  | 
| 610 |  | static int | 
| 611 | < | depthchange(vp, x0, y0, x1, y1)         /* check depth discontinuity */ | 
| 612 | < | register struct ODview  *vp; | 
| 613 | < | int     x0, y0, x1, y1; | 
| 611 | > | depthchange(            /* check depth discontinuity */ | 
| 612 | > | register struct ODview  *vp, | 
| 613 | > | int     x0, | 
| 614 | > | int     y0, | 
| 615 | > | int     x1, | 
| 616 | > | int     y1 | 
| 617 | > | ) | 
| 618 |  | { | 
| 619 |  | register double d0, d1; | 
| 620 |  |  | 
| 621 |  | DCHECK(x0<0 | x0>=vp->hhi | y0<0 | y0>=vp->vhi, | 
| 622 |  | CONSISTENCY, "coordinates off view in depthchange"); | 
| 623 |  |  | 
| 624 | < | if (x1<0 | x1>=vp->hhi | y1<0 | y1>=vp->vhi) | 
| 624 | > | if ((x1<0) | (x1>=vp->hhi) | (y1<0) | (y1>=vp->vhi)) | 
| 625 |  | return(1); | 
| 626 |  |  | 
| 627 |  | d0 = vp->dmap[y0*vp->hhi + x0]; | 
| 631 |  | } | 
| 632 |  |  | 
| 633 |  |  | 
| 634 | < | static | 
| 635 | < | clip_edge(p, o, vp)                     /* clip line segment to depth edge */ | 
| 636 | < | GLshort p[3]; | 
| 637 | < | short   o[2]; | 
| 638 | < | register struct ODview  *vp; | 
| 634 | > | static void | 
| 635 | > | clip_edge(                      /* clip line segment to depth edge */ | 
| 636 | > | GLshort p[3], | 
| 637 | > | short   o[2], | 
| 638 | > | register struct ODview  *vp | 
| 639 | > | ) | 
| 640 |  | { | 
| 641 |  | int     x, y, xstep, ystep, rise, rise2, run, run2, n; | 
| 642 |  |  | 
| 655 |  | n = rise + run; | 
| 656 |  | while (n--)                     /* run out arm, checking depth */ | 
| 657 |  | if (run2 > rise2) { | 
| 559 | – | if (depthchange(vp, x, y, x+xstep, y)) | 
| 560 | – | break; | 
| 658 |  | x += xstep; | 
| 659 |  | rise2 += rise; | 
| 660 | < | } else { | 
| 564 | < | if (depthchange(vp, x, y, x, y+ystep)) | 
| 660 | > | if (depthchange(vp, x-xstep, y, x, y)) | 
| 661 |  | break; | 
| 662 | + | } else { | 
| 663 |  | y += ystep; | 
| 664 |  | run2 += run; | 
| 665 | + | if (depthchange(vp, x, y-ystep, x, y)) | 
| 666 | + | break; | 
| 667 |  | } | 
| 668 |  | if (n < 0)                      /* found something? */ | 
| 669 |  | return; | 
| 677 |  |  | 
| 678 |  |  | 
| 679 |  | static int | 
| 680 | < | getblock(vp, h, v)                      /* get block index */ | 
| 681 | < | register struct ODview  *vp; | 
| 682 | < | register int    h, v; | 
| 680 | > | getblock(                       /* get block index */ | 
| 681 | > | register struct ODview  *vp, | 
| 682 | > | register int    h, | 
| 683 | > | register int    v | 
| 684 | > | ) | 
| 685 |  | { | 
| 686 | < | if (h<0 | h>=vp->hhi | v<0 | v>=vp->vhi) | 
| 686 | > | if ((h<0) | (h>=vp->hhi) | (v<0) | (v>=vp->vhi)) | 
| 687 |  | return(-1); | 
| 688 |  | return(h*vp->hlow/vp->hhi + v*vp->vlow/vp->vhi*vp->hlow); | 
| 689 |  | } | 
| 690 |  |  | 
| 691 |  |  | 
| 692 | < | odDrawBlockSamp(vn, h, v, id)           /* draw sample in view block */ | 
| 693 | < | int     vn, h, v; | 
| 694 | < | register int    id; | 
| 692 | > | static int | 
| 693 | > | blockedge(                      /* check for edge between blocks? */ | 
| 694 | > | register struct ODview  *vp, | 
| 695 | > | register int    bi0, | 
| 696 | > | register int    bi1 | 
| 697 | > | ) | 
| 698 |  | { | 
| 699 | + | if (bi1 == bi0) | 
| 700 | + | return(0);              /* same block */ | 
| 701 | + | if (bi1 < 0) | 
| 702 | + | return(1);              /* end off view */ | 
| 703 | + | if (CHK4(vp->emap, bi1)) | 
| 704 | + | return(1);              /* end block has edges */ | 
| 705 | + | if (bi1 == bi0+1 || bi1 == bi0-1 || | 
| 706 | + | bi1 == bi0+vp->hlow || bi1 == bi0-vp->hlow) | 
| 707 | + | return(0);              /* end in adjacent block -- no edges */ | 
| 708 | + | return(1);                      /* conservative for rarer case */ | 
| 709 | + | } | 
| 710 | + |  | 
| 711 | + |  | 
| 712 | + | static void | 
| 713 | + | odDrawSamp(                     /* draw view sample */ | 
| 714 | + | int     vn, | 
| 715 | + | register int    id | 
| 716 | + | ) | 
| 717 | + | { | 
| 718 |  | GLshort arm[MAXFAN][3]; | 
| 719 | < | int     narms, blockindex, bi1; | 
| 719 | > | int     narms, blockindex; | 
| 720 |  | register struct ODview  *vp; | 
| 721 |  | double  size; | 
| 722 |  | int     home_edges; | 
| 723 |  | register int    i; | 
| 724 |  |  | 
| 725 |  | vp = odView + vn; | 
| 726 | < | blockindex = v*vp->hlow + h; | 
| 727 | < | 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"); | 
| 726 | > | blockindex = getblock(vp, odS.ip[id][0], odS.ip[id][1]); | 
| 727 | > | DCHECK(blockindex<0, CONSISTENCY, "bad sample handed to odDrawSamp"); | 
| 728 |  | DCHECK(vp->bmap[blockindex].nused <= 0, | 
| 729 | < | CONSISTENCY, "bad in-use count in odDrawBlockSamp"); | 
| 729 | > | CONSISTENCY, "bad in-use count in odDrawSamp"); | 
| 730 |  | /* create triangle fan */ | 
| 731 |  | size = 1./sqrt((double)vp->bmap[blockindex].nused); | 
| 732 |  | narms = make_arms(arm, odS.ip[id], vp, size); | 
| 733 |  | if (vp->emap != NULL) {         /* check for edge collisions */ | 
| 734 |  | home_edges = CHK4(vp->emap, blockindex); | 
| 735 |  | for (i = 0; i < narms; i++) | 
| 736 | < | /* the following test is flawed, because we could | 
| 737 | < | * 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)) )) | 
| 736 | > | if (home_edges || blockedge(vp, blockindex, | 
| 737 | > | getblock(vp, arm[i][0], arm[i][1]))) | 
| 738 |  | clip_edge(arm[i], odS.ip[id], vp); | 
| 739 |  | } | 
| 740 |  | /* draw triangle fan */ |