ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhd_odraw.c
Revision: 3.17
Committed: Fri Jan 7 20:33:02 2005 UTC (19 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R0, rad3R8, rad3R9
Changes since 3.16: +8 -7 lines
Log Message:
Modernized tone-mapping routines with structure pointer r.t. stack

File Contents

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