ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhd_odraw.c
Revision: 3.12
Committed: Mon Mar 8 17:31:49 1999 UTC (25 years, 1 month ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.11: +1 -2 lines
Log Message:
removed unnecessary inclusion of sys/types.h

File Contents

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