ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhd_odraw.c
Revision: 3.15
Committed: Fri Jun 20 00:25:49 2003 UTC (20 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.14: +7 -7 lines
Log Message:
Changed instances of "int4" to "int32" and "int2" to "int16"

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rhd_odraw.c,v 3.14 2003/03/04 05:49:21 greg Exp $";
3 #endif
4 /*
5 * Routines for drawing samples using depth buffer checks.
6 */
7
8 #include "standard.h"
9
10 #include <GL/glx.h>
11 #include <GL/glu.h>
12
13 #include "rhd_odraw.h"
14
15 #ifndef DEPTHEPS
16 #define DEPTHEPS 0.02 /* depth epsilon */
17 #endif
18 #ifndef SAMPSPERBLOCK
19 #define SAMPSPERBLOCK 1024 /* target samples per image block */
20 #endif
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
30 #ifndef MINFAN
31 #define MINFAN 4 /* minimum arms in a triangle fan */
32 #endif
33 #ifndef FANSIZE
34 #define FANSIZE 3.5 /* fan sizing factor */
35 #endif
36
37 #define NEWMAP 01 /* need to recompute mapping */
38 #define NEWRGB 02 /* need to remap RGB values */
39 #define NEWHIST 04 /* clear histogram as well */
40
41 struct ODview *odView; /* our view list */
42 int odNViews; /* number of views in our list */
43
44 struct ODsamp odS; /* sample values */
45
46 static int needmapping; /* what needs doing with tone map */
47
48
49 #define SAMP32 (32*(2*sizeof(short)+sizeof(union ODfunion)+sizeof(TMbright)+\
50 6*sizeof(BYTE))+sizeof(int32))
51
52 int
53 odInit(n) /* initialize drawing routines */
54 int n;
55 {
56 int nbytes, i, j, k, nextsamp, count, blockdiv;
57 int res[2];
58
59 if (odNViews > 0) { /* deallocate view structures */
60 for (i = odNViews; i--; ) {
61 free((void *)odView[i].bmap);
62 free((void *)odView[i].pmap);
63 if (odView[i].emap != NULL)
64 free((void *)odView[i].emap);
65 }
66 free((void *)odView);
67 odView = NULL;
68 odNViews = 0;
69 }
70 if (n && n != odS.nsamp) {
71 /* round space up to nearest power of 2 */
72 nbytes = (n+31)/32 * SAMP32;
73 for (i = 1024; nbytes > i-8; i <<= 1)
74 ;
75 n = (i-8)/SAMP32 * 32;
76 needmapping = NEWHIST;
77 }
78 if (n != odS.nsamp) { /* (re)allocate sample array */
79 if (odS.nsamp)
80 free(odS.base);
81 odS.nsamp = 0;
82 if (!n)
83 return(0);
84 nbytes = (n+31)/32 * SAMP32;
85 odS.base = (char *)malloc(nbytes);
86 if (odS.base == NULL)
87 return(0);
88 /* assign larger alignment types earlier */
89 odS.f = (union ODfunion *)odS.base;
90 odS.redraw = (int32 *)(odS.f + n);
91 odS.ip = (short (*)[2])(odS.redraw + n/32);
92 odS.brt = (TMbright *)(odS.ip + n);
93 odS.chr = (BYTE (*)[3])(odS.brt + n);
94 odS.rgb = (BYTE (*)[3])(odS.chr + n);
95 odS.nsamp = n;
96 }
97 if (!n)
98 return(0);
99 /* allocate view information */
100 count = 0; /* count pixels */
101 for (i = 0; dev_auxview(i, res) != NULL; i++)
102 count += res[0]*res[1];
103 odView = (struct ODview *)malloc(i*sizeof(struct ODview));
104 if (odView == NULL)
105 return(0);
106 odNViews = i;
107 blockdiv = sqrt(count/(n/SAMPSPERBLOCK)) + 0.5;
108 if (blockdiv < 8) blockdiv = 8;
109 nextsamp = 0; count /= blockdiv*blockdiv; /* # blocks */
110 while (i--) { /* initialize each view */
111 dev_auxview(i, res);
112 odView[i].hhi = res[0];
113 odView[i].hlow = (res[0] + blockdiv/2) / blockdiv;
114 if (odView[i].hlow < 1) odView[i].hlow = 1;
115 odView[i].vhi = res[1];
116 odView[i].vlow = (res[1] + blockdiv/2) / blockdiv;
117 if (odView[i].vlow < 1) odView[i].vlow = 1;
118 odView[i].emap = NULL;
119 odView[i].dmap = NULL;
120 odView[i].pmap = (int32 *)calloc(FL4NELS(res[0]*res[1]),
121 sizeof(int32));
122 if (odView[i].pmap == NULL)
123 return(0);
124 j = odView[i].hlow*odView[i].vlow;
125 odView[i].bmap = (struct ODblock *)malloc(
126 j * sizeof(struct ODblock));
127 if (odView[i].bmap == NULL)
128 return(0);
129 DCHECK(count<=0 | nextsamp>=n,
130 CONSISTENCY, "counter botch in odInit");
131 if (!i) count = j;
132 odView[i].sfirst = nextsamp;
133 while (j--) { /* initialize blocks & free lists */
134 odView[i].bmap[j].pthresh = FHUGE;
135 odView[i].bmap[j].first = k = nextsamp;
136 nextsamp += odView[i].bmap[j].nsamp =
137 (n - nextsamp)/count--;
138 odView[i].bmap[j].free = k;
139 while (++k < nextsamp)
140 odS.nextfree(k-1) = k;
141 odS.nextfree(k-1) = ENDFREE;
142 odView[i].bmap[j].nused = 0;
143 }
144 odView[i].snext = nextsamp;
145 odView[i].n2redraw = 0;
146 }
147 CLR4ALL(odS.redraw, odS.nsamp); /* clear redraw flags */
148 for (i = odS.nsamp; i--; ) { /* clear values */
149 odS.ip[i][0] = odS.ip[i][1] = -1;
150 odS.brt[i] = TM_NOBRT;
151 }
152 needmapping |= NEWMAP; /* compute new map on update */
153 return(odS.nsamp); /* return number of samples */
154 }
155
156 #undef SAMP32
157
158
159 int
160 sampcmp(s0, s1) /* sample order, descending proximity */
161 int *s0, *s1;
162 {
163 register double diff = odS.closeness(*s1) - odS.closeness(*s0);
164
165 return (diff > FTINY ? 1 : diff < -FTINY ? -1 : 0);
166 }
167
168
169 int
170 odAllocBlockSamp(vn, hh, vh, prox) /* allocate sample from block */
171 int vn, hh, vh;
172 double prox;
173 {
174 int si[SAMPSPERBLOCK+SAMPSPERBLOCK/4];
175 int hl, vl;
176 VIEW *vw;
177 FVECT ro, rd;
178 int res[2];
179 register struct ODblock *bp;
180 register int i, j;
181 /* get block */
182 hl = hh*odView[vn].hlow/odView[vn].hhi;
183 vl = vh*odView[vn].vlow/odView[vn].vhi;
184 bp = odView[vn].bmap + vl*odView[vn].hlow + hl;
185 if (prox > bp->pthresh)
186 return(-1); /* worse than free list occupants */
187 /* check for duplicate pixel */
188 if (CHK4(odView[vn].pmap, vh*odView[vn].hhi + hh))
189 i = bp->first + bp->nsamp;
190 else
191 i = 0;
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)
196 break; /* special case */
197 if (bp->free != ENDFREE)
198 for (j = bp->free; odS.nextfree(j) != ENDFREE;
199 j = odS.nextfree(j))
200 if (odS.nextfree(j) == i) {
201 odS.nextfree(j) =
202 odS.nextfree(i);
203 bp->nused++;
204 goto gotit;
205 }
206 if (prox >= 0.99*odS.closeness(i))
207 return(-1); /* previous sample is fine */
208 goto gotit;
209 }
210 if (bp->free != ENDFREE) { /* allocate from free list */
211 i = bp->free;
212 if (odS.ip[i][0] >= 0 & odS.ip[i][1] >= 0)
213 CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi +
214 odS.ip[i][0]);
215 bp->free = odS.nextfree(i);
216 bp->nused++;
217 goto gotit;
218 }
219 DCHECK(bp->nsamp<=0, CONSISTENCY,
220 "no available samples in odAllocBlockSamp");
221 DCHECK(bp->nsamp > sizeof(si)/sizeof(si[0]), CONSISTENCY,
222 "too many samples in odAllocBlockSamp");
223 /* free some samples */
224 if ((vw = dev_auxview(vn, res)) == NULL)
225 error(CONSISTENCY, "bad view number in odAllocBlockSamp");
226 for (i = bp->nsamp; i--; ) /* figure out which are worse */
227 si[i] = bp->first + i;
228 qsort((char *)si, bp->nsamp, sizeof(int), sampcmp);
229 i = bp->nsamp*SFREEFRAC + .5; /* put them into free list */
230 if (i >= bp->nsamp) i = bp->nsamp-1; /* paranoia */
231 bp->pthresh = odS.closeness(si[i]); /* new proximity threshold */
232 while (--i > 0) {
233 odS.nextfree(si[i]) = bp->free;
234 bp->free = si[i];
235 bp->nused--;
236 }
237 i = si[0]; /* use worst sample */
238 CLR4(odView[vn].pmap, odS.ip[i][1]*odView[vn].hhi + odS.ip[i][0]);
239 gotit:
240 odS.ip[i][0] = hh;
241 odS.ip[i][1] = vh;
242 odS.closeness(i) = prox;
243 SET4(odView[vn].pmap, vh*odView[vn].hhi + hh);
244 return(i);
245 }
246
247
248 odSample(c, d, p) /* add a sample value */
249 COLR c;
250 FVECT d, p;
251 {
252 FVECT disp;
253 double d0, d1, h, v, prox;
254 register VIEW *vw;
255 int hh, vh;
256 int res[2];
257 register int i, id;
258
259 DCHECK(odS.nsamp<=0, CONSISTENCY, "no samples allocated in odSample");
260 /* add value to each view */
261 for (i = 0; (vw = dev_auxview(i, res)) != NULL; i++) {
262 DCHECK(i>=odNViews, CONSISTENCY, "too many views in odSample");
263 CHECK(vw->type!=VT_PER, INTERNAL,
264 "cannot handle non-perspective views");
265 if (p != NULL) { /* compute view position */
266 VSUB(disp, p, vw->vp);
267 d0 = DOT(disp, vw->vdir);
268 if (d0 <= vw->vfore+FTINY)
269 continue; /* too close */
270 } else {
271 VCOPY(disp, d);
272 d0 = DOT(disp, vw->vdir);
273 if (d0 <= FTINY) /* behind view */
274 continue;
275 }
276 h = DOT(disp,vw->hvec)/(d0*vw->hn2) + 0.5 - vw->hoff;
277 if (h < 0. || h >= 1.)
278 continue; /* left or right */
279 v = DOT(disp,vw->vvec)/(d0*vw->vn2) + 0.5 - vw->voff;
280 if (v < 0. || v >= 1.)
281 continue; /* above or below */
282 hh = h * res[0];
283 vh = v * res[1];
284 if (odView[i].dmap != NULL) { /* check depth */
285 d1 = odView[i].dmap[vh*res[0] + hh];
286 if (d1 < 0.99*FHUGE && (d0 > (1.+DEPTHEPS)*d1 ||
287 (1.+DEPTHEPS)*d0 < d1))
288 continue; /* occlusion error */
289 }
290 if (p != NULL) { /* compute closeness (sin^2) */
291 d1 = DOT(disp, d);
292 prox = 1. - d1*d1/DOT(disp,disp);
293 } else
294 prox = 0.;
295 /* allocate sample */
296 id = odAllocBlockSamp(i, hh, vh, prox);
297 if (id < 0)
298 continue; /* not good enough */
299 /* convert color */
300 tmCvColrs(&odS.brt[id], odS.chr[id], (COLR *)c, 1);
301 if (imm_mode | needmapping) /* if immediate mode */
302 needmapping |= NEWRGB; /* map it later */
303 else /* else map it now */
304 tmMapPixels(odS.rgb[id], &odS.brt[id], odS.chr[id], 1);
305 SET4(odS.redraw, id); /* mark for redraw */
306 odView[i].n2redraw++;
307 }
308 }
309
310
311 odRemap(newhist) /* recompute tone mapping */
312 int newhist;
313 {
314 needmapping |= NEWMAP|NEWRGB;
315 if (newhist)
316 needmapping |= NEWHIST;
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 /* not right, but not important */
330 for (i = 0; i < odNViews; i++)
331 odView[i].n2redraw = odView[i].snext - odView[i].sfirst;
332 }
333
334
335 odRedraw(vn, hmin, vmin, hmax, vmax) /* redraw view region */
336 int vn, hmin, vmin, hmax, vmax;
337 {
338 int i, j;
339 register struct ODblock *bp;
340 register int k;
341
342 if (vn<0 | vn>=odNViews)
343 return;
344 /* check view limits */
345 if (hmin < 0) hmin = 0;
346 if (hmax >= odView[vn].hhi) hmax = odView[vn].hhi-1;
347 if (vmin < 0) vmin = 0;
348 if (vmax >= odView[vn].vhi) vmax = odView[vn].vhi-1;
349 if (hmax <= hmin | vmax <= vmin)
350 return;
351 /* convert to low resolution */
352 hmin = hmin * odView[vn].hlow / odView[vn].hhi;
353 hmax = hmax * odView[vn].hlow / odView[vn].hhi;
354 vmin = vmin * odView[vn].vlow / odView[vn].vhi;
355 vmax = vmax * odView[vn].vlow / odView[vn].vhi;
356 /* mark block samples for redraw, inclusive */
357 for (i = hmin; i <= hmax; i++)
358 for (j = vmin; j <= vmax; j++) {
359 bp = odView[vn].bmap + j*odView[vn].hlow + i;
360 for (k = bp->nsamp; k--; )
361 if (odS.ip[bp->first+k][0] >= 0) {
362 SET4(odS.redraw, bp->first+k);
363 odView[vn].n2redraw++;
364 }
365 }
366 }
367
368
369 odDepthMap(vn, dm) /* assign depth map for view */
370 int vn;
371 GLfloat *dm;
372 {
373 double d0, d1;
374 int i, j, hmin, hmax, vmin, vmax;
375 register int k, l;
376
377 if (dm == NULL) { /* free edge map */
378 if (vn<0 | vn>=odNViews)
379 return; /* too late -- they're gone! */
380 if (odView[vn].emap != NULL)
381 free((void *)odView[vn].emap);
382 odView[vn].emap = NULL;
383 odView[vn].dmap = NULL;
384 return;
385 }
386 DCHECK(vn<0 | vn>=odNViews, CONSISTENCY,
387 "bad view number in odDepthMap");
388 odView[vn].dmap = dm; /* initialize edge map */
389 if (odView[vn].emap == NULL) {
390 odView[vn].emap = (int32 *)malloc(
391 FL4NELS(odView[vn].hlow*odView[vn].vlow)*sizeof(int32));
392 if (odView[vn].emap == NULL)
393 error(SYSTEM, "out of memory in odDepthMap");
394 }
395 CLR4ALL(odView[vn].emap, odView[vn].hlow*odView[vn].vlow);
396 /* compute edge map */
397 vmin = odView[vn].vhi; /* enter loopsville */
398 for (j = odView[vn].vlow; j--; ) {
399 vmax = vmin;
400 vmin = j*odView[vn].vhi/odView[vn].vlow;
401 hmin = odView[vn].hhi;
402 for (i = odView[vn].hlow; i--; ) {
403 hmax = hmin;
404 hmin = i*odView[vn].hhi/odView[vn].hlow;
405 for (l = vmin; l < vmax; l++) { /* vertical edges */
406 d1 = dm[l*odView[vn].hhi+hmin];
407 for (k = hmin+1; k < hmax; k++) {
408 d0 = d1;
409 d1 = dm[l*odView[vn].hhi+k];
410 if (d0 > (1.+DEPTHEPS)*d1 ||
411 (1.+DEPTHEPS)*d0 < d1) {
412 SET4(odView[vn].emap,
413 j*odView[vn].hlow + i);
414 break;
415 }
416 }
417 if (k < hmax)
418 break;
419 }
420 if (l < vmax)
421 continue;
422 for (k = hmin; k < hmax; k++) { /* horizontal edges */
423 d1 = dm[vmin*odView[vn].hhi+k];
424 for (l = vmin+1; l < vmax; l++) {
425 d0 = d1;
426 d1 = dm[l*odView[vn].hhi+k];
427 if (d0 > (1.+DEPTHEPS)*d1 ||
428 (1.+DEPTHEPS)*d0 < d1) {
429 SET4(odView[vn].emap,
430 j*odView[vn].hlow + i);
431 break;
432 }
433 }
434 if (l < vmax)
435 break;
436 }
437 }
438 }
439 }
440
441
442 odUpdate(vn) /* update this view */
443 int vn;
444 {
445 static short primes[] = {9431,6803,4177,2659,1609,887,587,251,47,1};
446 int myprime;
447 register int i, n;
448
449 DCHECK(vn<0 | vn>=odNViews, CONSISTENCY,
450 "bad view number in odUpdate");
451 /* need to do some tone mapping? */
452 if (needmapping & NEWRGB) {
453 if (needmapping & NEWMAP) {
454 if (needmapping & NEWHIST)
455 tmClearHisto();
456 needmapping &= ~NEWHIST;
457 if (tmAddHisto(odS.brt,odS.nsamp,1) != TM_E_OK)
458 return;
459 if (tmComputeMapping(0.,0.,0.) != TM_E_OK)
460 return;
461 needmapping &= ~NEWMAP;
462 odRedrawAll(); /* redraw everything */
463 }
464 if (tmMapPixels((BYTE *)(odS.rgb), odS.brt,
465 (BYTE *)(odS.chr), odS.nsamp) != TM_E_OK)
466 return;
467 needmapping &= ~NEWRGB;
468 }
469 if (odView[vn].n2redraw <= 0)
470 return;
471 #if REDRAWTHRESH
472 if (odView[vn].n2redraw < REDRAWTHRESH)
473 goto quickdraw;
474 /* pick a good prime step size */
475 n = odView[vn].snext - odView[vn].sfirst;
476 for (i = 0; primes[i]<<5 >= n; i++)
477 ;
478 while ((myprime = primes[i++]) > 1)
479 if (n % myprime)
480 break;
481 /* dissolve in new samples */
482 for (i = odView[vn].sfirst; n-- > 0; i += myprime) {
483 if (i >= odView[vn].snext)
484 i -= odView[vn].snext - odView[vn].sfirst;
485 if (CHK4(odS.redraw, i)) {
486 odDrawSamp(vn, i);
487 CLR4(odS.redraw, i);
488 }
489 }
490 odView[vn].n2redraw = 0;
491 return;
492 quickdraw: /* quicker sparse flag checking */
493 #endif
494 /* redraw samples at end */
495 for (i = odView[vn].snext-31; i < odView[vn].snext; i++)
496 if (CHK4(odS.redraw, i)) {
497 odDrawSamp(vn, i);
498 CLR4(odS.redraw, i);
499 }
500 /* faster flag checks in middle */
501 for (n = odView[vn].snext>>5; n-- > (odView[vn].sfirst+0x1f)>>5; )
502 for (i = 0; odS.redraw[n]; i++) /* skips faster */
503 if (odS.redraw[n] & 1L<<i) {
504 odDrawSamp(vn, (n<<5)+i);
505 odS.redraw[n] &= ~(1L<<i);
506 }
507 /* redraw samples at beginning */
508 for (i = odView[vn].sfirst; i < odView[vn].sfirst+31; i++)
509 if (CHK4(odS.redraw, i)) {
510 odDrawSamp(vn, i);
511 CLR4(odS.redraw, i);
512 }
513 odView[vn].n2redraw = 0;
514 }
515
516
517 /* this turned out to be unnecessary */
518 #if 0
519 static
520 clip_end(p, o, vp) /* clip line segment to view */
521 GLshort p[3];
522 short o[2];
523 register struct ODview *vp;
524 {
525 if (p[0] < 0) {
526 p[1] = -o[0]*(p[1]-o[1])/(p[0]-o[0]) + o[1];
527 p[2] = -o[0]*p[2]/(p[0]-o[0]);
528 p[0] = 0;
529 } else if (p[0] >= vp->hhi) {
530 p[1] = (vp->hhi-1-o[0])*(p[1]-o[1])/(p[0]-o[0]) + o[1];
531 p[2] = (vp->hhi-1-o[0])*p[2]/(p[0]-o[0]);
532 p[0] = vp->hhi-1;
533 }
534 if (p[1] < 0) {
535 p[0] = -o[1]*(p[0]-o[0])/(p[1]-o[1]) + o[0];
536 p[2] = -o[1]*p[2]/(p[1]-o[1]);
537 p[1] = 0;
538 } else if (p[1] >= vp->vhi) {
539 p[0] = (vp->vhi-1-o[1])*(p[0]-o[0])/(p[1]-o[1]) + o[0];
540 p[2] = (vp->vhi-1-o[1])*p[2]/(p[1]-o[1]);
541 p[1] = vp->vhi-1;
542 }
543 }
544 #endif
545
546
547 static int
548 make_arms(ar, cp, vp, sz) /* make arms for triangle fan */
549 GLshort ar[MAXFAN][3];
550 short cp[2];
551 register struct ODview *vp;
552 double sz;
553 {
554 int na, dv;
555 double hrad, vrad, phi;
556 register int i;
557
558 DCHECK(sz > 1, CONSISTENCY, "super-unary size in make_arms");
559 na = MAXFAN*sz + 0.5; /* keep arc length constant */
560 if (na < MINFAN) na = MINFAN;
561 hrad = FANSIZE*sz*vp->hhi/vp->hlow;
562 vrad = FANSIZE*sz*vp->vhi/vp->vlow;
563 if (hrad*vrad < 2.25)
564 hrad = vrad = 1.5;
565 dv = OMAXDEPTH*sz + 0.5;
566 for (i = 0; i < na; i++) {
567 phi = (2.*PI)*i/na;
568 ar[i][0] = cp[0] + tcos(phi)*hrad + 0.5;
569 ar[i][1] = cp[1] + tsin(phi)*vrad + 0.5;
570 ar[i][2] = dv;
571 /* clip_end(ar[i], cp, vp); */
572 }
573 return(na);
574 }
575
576
577 static int
578 depthchange(vp, x0, y0, x1, y1) /* check depth discontinuity */
579 register struct ODview *vp;
580 int x0, y0, x1, y1;
581 {
582 register double d0, d1;
583
584 DCHECK(x0<0 | x0>=vp->hhi | y0<0 | y0>=vp->vhi,
585 CONSISTENCY, "coordinates off view in depthchange");
586
587 if (x1<0 | x1>=vp->hhi | y1<0 | y1>=vp->vhi)
588 return(1);
589
590 d0 = vp->dmap[y0*vp->hhi + x0];
591 d1 = vp->dmap[y1*vp->hhi + x1];
592
593 return((1.+DEPTHEPS)*d0 < d1 || d0 > (1.+DEPTHEPS)*d1);
594 }
595
596
597 static
598 clip_edge(p, o, vp) /* clip line segment to depth edge */
599 GLshort p[3];
600 short o[2];
601 register struct ODview *vp;
602 {
603 int x, y, xstep, ystep, rise, rise2, run, run2, n;
604
605 DCHECK(vp->dmap==NULL, CONSISTENCY,
606 "clip_edge called with no depth map");
607 x = o[0]; y = o[1];
608 run = p[0] - x;
609 xstep = run > 0 ? 1 : -1;
610 run *= xstep;
611 rise = p[1] - y;
612 ystep = rise > 0 ? 1 : -1;
613 rise *= ystep;
614 rise2 = run2 = 0;
615 if (rise > run) rise2 = 1;
616 else run2 = 1;
617 n = rise + run;
618 while (n--) /* run out arm, checking depth */
619 if (run2 > rise2) {
620 x += xstep;
621 rise2 += rise;
622 if (depthchange(vp, x-xstep, y, x, y))
623 break;
624 } else {
625 y += ystep;
626 run2 += run;
627 if (depthchange(vp, x, y-ystep, x, y))
628 break;
629 }
630 if (n < 0) /* found something? */
631 return;
632 if (run > rise)
633 p[2] = (x - o[0])*p[2]/(p[0] - o[0]);
634 else
635 p[2] = (y - o[1])*p[2]/(p[1] - o[1]);
636 p[0] = x;
637 p[1] = y;
638 }
639
640
641 static int
642 getblock(vp, h, v) /* get block index */
643 register struct ODview *vp;
644 register int h, v;
645 {
646 if (h<0 | h>=vp->hhi | v<0 | v>=vp->vhi)
647 return(-1);
648 return(h*vp->hlow/vp->hhi + v*vp->vlow/vp->vhi*vp->hlow);
649 }
650
651
652 static int
653 blockedge(vp, bi0, bi1) /* check for edge between blocks? */
654 register struct ODview *vp;
655 register int bi0, bi1;
656 {
657 if (bi1 == bi0)
658 return(0); /* same block */
659 if (bi1 < 0)
660 return(1); /* end off view */
661 if (CHK4(vp->emap, bi1))
662 return(1); /* end block has edges */
663 if (bi1 == bi0+1 || bi1 == bi0-1 ||
664 bi1 == bi0+vp->hlow || bi1 == bi0-vp->hlow)
665 return(0); /* end in adjacent block -- no edges */
666 return(1); /* conservative for rarer case */
667 }
668
669
670 odDrawSamp(vn, id) /* draw view sample */
671 int vn;
672 register int id;
673 {
674 GLshort arm[MAXFAN][3];
675 int narms, blockindex;
676 register struct ODview *vp;
677 double size;
678 int home_edges;
679 register int i;
680
681 vp = odView + vn;
682 blockindex = getblock(vp, odS.ip[id][0], odS.ip[id][1]);
683 DCHECK(blockindex<0, CONSISTENCY, "bad sample handed to odDrawSamp");
684 DCHECK(vp->bmap[blockindex].nused <= 0,
685 CONSISTENCY, "bad in-use count in odDrawSamp");
686 /* create triangle fan */
687 size = 1./sqrt((double)vp->bmap[blockindex].nused);
688 narms = make_arms(arm, odS.ip[id], vp, size);
689 if (vp->emap != NULL) { /* check for edge collisions */
690 home_edges = CHK4(vp->emap, blockindex);
691 for (i = 0; i < narms; i++)
692 if (home_edges || blockedge(vp, blockindex,
693 getblock(vp, arm[i][0], arm[i][1])))
694 clip_edge(arm[i], odS.ip[id], vp);
695 }
696 /* draw triangle fan */
697 glColor3ub(odS.rgb[id][0], odS.rgb[id][1], odS.rgb[id][2]);
698 glBegin(GL_TRIANGLE_FAN);
699 glVertex3s((GLshort)odS.ip[id][0], (GLshort)odS.ip[id][1], (GLshort)0);
700 for (i = 0; i < narms; i++)
701 glVertex3sv(arm[i]);
702 glVertex3sv(arm[0]); /* connect last to first */
703 glEnd();
704 }