ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhd_qtree.c
Revision: 3.4
Committed: Fri Nov 21 09:52:06 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.3: +18 -10 lines
Log Message:
fixed bug in newleaf()

File Contents

# User Rev Content
1 gregl 3.1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * Quadtree driver support routines.
9     */
10    
11     #include "standard.h"
12     #include "rhd_qtree.h"
13    
14 gregl 3.2 RTREE qtrunk; /* our quadtree trunk */
15     double qtDepthEps = .02; /* epsilon to compare depths (z fraction) */
16     int qtMinNodesiz = 2; /* minimum node dimension (pixels) */
17    
18 gregl 3.1 static RLEAF *leafpile; /* our collection of leaf values */
19     static int nleaves; /* count of leaves in our pile */
20     static int bleaf, tleaf; /* bottom and top (next) leaf index (ring) */
21    
22     #define TBUNDLESIZ 409 /* number of twigs in a bundle */
23    
24     static RTREE **twigbundle; /* free twig blocks (NULL term.) */
25     static int nexttwig; /* next free twig */
26    
27     static RTREE emptytree; /* empty tree for test below */
28    
29     #define is_stump(t) (!bcmp((char *)(t), (char *)&emptytree, sizeof(RTREE)))
30    
31    
32     static RTREE *
33     newtwig() /* allocate a twig */
34     {
35     register int bi;
36    
37     if (twigbundle == NULL) { /* initialize */
38     twigbundle = (RTREE **)malloc(sizeof(RTREE *));
39     if (twigbundle == NULL)
40     goto memerr;
41     twigbundle[0] = NULL;
42     }
43     bi = nexttwig / TBUNDLESIZ;
44     if (twigbundle[bi] == NULL) { /* new block */
45     twigbundle = (RTREE **)realloc((char *)twigbundle,
46     (bi+2)*sizeof(RTREE *));
47     if (twigbundle == NULL)
48     goto memerr;
49     twigbundle[bi] = (RTREE *)calloc(TBUNDLESIZ, sizeof(RTREE));
50     if (twigbundle[bi] == NULL)
51     goto memerr;
52     twigbundle[bi+1] = NULL;
53     }
54     /* nexttwig++ % TBUNDLESIZ */
55     return(twigbundle[bi] + (nexttwig++ - bi*TBUNDLESIZ));
56     memerr:
57     error(SYSTEM, "out of memory in newtwig");
58     }
59    
60    
61 gregl 3.3 qtFreeTree(really) /* free allocated twigs */
62 gregl 3.1 int really;
63     {
64     register int i;
65    
66 gregl 3.4 tmClearHisto();
67 gregl 3.1 bzero((char *)&qtrunk, sizeof(RTREE));
68     nexttwig = 0;
69     if (twigbundle == NULL)
70     return;
71     if (!really) { /* just clear allocated blocks */
72     for (i = 0; twigbundle[i] != NULL; i++)
73     bzero((char *)twigbundle[i], TBUNDLESIZ*sizeof(RTREE));
74     return;
75     }
76     /* else "really" means free up memory */
77     for (i = 0; twigbundle[i] != NULL; i++)
78     free((char *)twigbundle[i]);
79     free((char *)twigbundle);
80     twigbundle = NULL;
81     }
82    
83    
84     static RLEAF *
85     newleaf() /* allocate a leaf from our pile */
86     {
87 gregl 3.4 RLEAF *lp;
88    
89     lp = leafpile + tleaf++;
90     if (tleaf >= nleaves) /* get next leaf in ring */
91 gregl 3.1 tleaf = 0;
92     if (tleaf == bleaf) /* need to shake some free */
93     qtCompost(LFREEPCT);
94 gregl 3.4 return(lp);
95 gregl 3.1 }
96    
97    
98     int
99     qtAllocLeaves(n) /* allocate space for n leaves */
100     int n;
101     {
102     unsigned nbytes;
103     register unsigned i;
104    
105 gregl 3.3 qtFreeTree(0); /* make sure tree is empty */
106 gregl 3.1 if (n <= 0)
107     return(0);
108     if (nleaves >= n)
109     return(nleaves);
110     else if (nleaves > 0)
111     free((char *)leafpile);
112     /* round space up to nearest power of 2 */
113     nbytes = n*sizeof(RLEAF) + 8;
114     for (i = 1024; nbytes > i; i <<= 1)
115     ;
116     n = (i - 8) / sizeof(RLEAF);
117     leafpile = (RLEAF *)malloc(n*sizeof(RLEAF));
118     if (leafpile == NULL)
119     return(-1);
120     nleaves = n;
121     bleaf = tleaf = 0;
122     return(nleaves);
123     }
124    
125    
126     qtFreeLeaves() /* free our allocated leaves and twigs */
127     {
128 gregl 3.3 qtFreeTree(1); /* free tree also */
129 gregl 3.1 if (nleaves <= 0)
130     return;
131     free((char *)leafpile);
132     leafpile = NULL;
133     nleaves = 0;
134     }
135    
136    
137     static
138     shaketree(tp) /* shake dead leaves from tree */
139     register RTREE *tp;
140     {
141     register int i, li;
142    
143     for (i = 0; i < 4; i++)
144 gregl 3.2 if (tp->flgs & BRF(i))
145     shaketree(tp->k[i].b);
146     else if (tp->k[i].l != NULL) {
147 gregl 3.1 li = tp->k[i].l - leafpile;
148     if (bleaf < tleaf ? (li < bleaf || li >= tleaf) :
149     (li < bleaf && li >= tleaf)) {
150     tmAddHisto(&tp->k[i].l->brt, 1, -1);
151     tp->k[i].l = NULL;
152     }
153     }
154     }
155    
156    
157     int
158     qtCompost(pct) /* free up some leaves */
159     int pct;
160     {
161     int nused, nclear;
162 gregl 3.4
163     if (is_stump(&qtrunk))
164     return(0);
165 gregl 3.1 /* figure out how many leaves to clear */
166     nclear = nleaves * pct / 100;
167 gregl 3.4 nused = tleaf > bleaf ? tleaf-bleaf : tleaf+nleaves-bleaf;
168     nclear -= nleaves - nused; /* less what's already free */
169 gregl 3.1 if (nclear <= 0)
170     return(0);
171     if (nclear >= nused) { /* clear them all */
172 gregl 3.3 qtFreeTree(0);
173 gregl 3.1 bleaf = tleaf = 0;
174     return(nused);
175     }
176     /* else clear leaves from bottom */
177 gregl 3.4 bleaf += nclear;
178     if (bleaf >= nleaves) bleaf -= nleaves;
179 gregl 3.1 shaketree(&qtrunk);
180     return(nclear);
181     }
182    
183    
184 gregl 3.3 RLEAF *
185     qtFindLeaf(x, y) /* find closest leaf to (x,y) */
186     int x, y;
187     {
188     register RTREE *tp = &qtrunk;
189     RLEAF *lp = NULL;
190     int x0=0, y0=0, x1=odev.hres, y1=odev.vres;
191     int mx, my;
192     register int q;
193     /* check limits */
194     if (x < 0 || x >= odev.hres || y < 0 || y >= odev.vres)
195     return(NULL);
196     /* find nearby leaf in our tree */
197     for ( ; ; ) {
198     for (q = 0; q < 4; q++) /* find any leaf this level */
199     if (!(tp->flgs & BRF(q)) && tp->k[q].l != NULL) {
200     lp = tp->k[q].l;
201     break;
202     }
203     q = 0; /* which quadrant are we? */
204     mx = (x0 + x1) >> 1;
205     my = (y0 + y1) >> 1;
206     if (x < mx) x1 = mx;
207     else {x0 = mx; q |= 01;}
208     if (y < my) y1 = my;
209     else {y0 = my; q |= 02;}
210     if (tp->flgs & BRF(q)) { /* branch down if not a leaf */
211     tp = tp->k[q].b;
212     continue;
213     }
214     if (tp->k[q].l != NULL) /* good shot! */
215     return(tp->k[q].l);
216     return(lp); /* else return what we have */
217     }
218     }
219    
220    
221 gregl 3.1 static
222     addleaf(lp) /* add a leaf to our tree */
223     RLEAF *lp;
224     {
225     register RTREE *tp = &qtrunk;
226     int x0=0, y0=0, x1=odev.hres, y1=odev.vres;
227     RLEAF *lo = NULL;
228     int x, y, mx, my;
229     double z;
230     FVECT ip, wp;
231     register int q;
232     /* compute leaf location */
233     VCOPY(wp, lp->wp);
234     viewloc(ip, &odev.v, wp);
235     if (ip[2] <= 0. || ip[0] < 0. || ip[0] >= 1.
236     || ip[1] < 0. || ip[1] >= 1.)
237     return;
238     x = ip[0] * odev.hres;
239     y = ip[1] * odev.vres;
240     z = ip[2];
241     /* find the place for it */
242     for ( ; ; ) {
243     q = 0; /* which quadrant? */
244     mx = (x0 + x1) >> 1;
245     my = (y0 + y1) >> 1;
246     if (x < mx) x1 = mx;
247     else {x0 = mx; q |= 01;}
248     if (y < my) y1 = my;
249     else {y0 = my; q |= 02;}
250     if (tp->flgs & BRF(q)) { /* move to next branch */
251     tp->flgs |= CHF(q); /* not sure; guess */
252     tp = tp->k[q].b;
253     continue;
254     }
255     if (tp->k[q].l == NULL) { /* found stem for leaf */
256     tp->k[q].l = lp;
257     tp->flgs |= CHF(q);
258     break;
259     }
260     /* check existing leaf */
261     if (lo != tp->k[q].l) {
262     lo = tp->k[q].l;
263     VCOPY(wp, lo->wp);
264     viewloc(ip, &odev.v, wp);
265     }
266     /* is node minimum size? */
267     if (x1-x0 <= qtMinNodesiz || y1-y0 <= qtMinNodesiz) {
268     if (z > (1.-qtDepthEps)*ip[2]) /* who is closer? */
269     return; /* old one is */
270     tp->k[q].l = lp; /* new one is */
271     tp->flgs |= CHF(q);
272     tmAddHisto(&lo->brt, 1, -1); /* drop old one */
273     break;
274     }
275     tp->flgs |= CHBRF(q); /* else grow tree */
276     tp = tp->k[q].b = newtwig();
277     tp->flgs |= CH_ANY; /* all new */
278     q = 0; /* old leaf -> new branch */
279     mx = ip[0] * odev.hres;
280     my = ip[1] * odev.vres;
281     if (mx >= (x0 + x1) >> 1) q |= 01;
282     if (my >= (y0 + y1) >> 1) q |= 02;
283     tp->k[q].l = lo;
284     }
285     tmAddHisto(&lp->brt, 1, 1); /* add leaf to histogram */
286     }
287    
288    
289     dev_value(c, p) /* add a pixel value to our output queue */
290     COLR c;
291     FVECT p;
292     {
293     register RLEAF *lp;
294    
295     lp = newleaf();
296     VCOPY(lp->wp, p);
297     tmCvColrs(&lp->brt, lp->chr, c, 1);
298     addleaf(lp);
299     }
300    
301    
302     qtReplant() /* replant our tree using new view */
303     {
304     register int i;
305    
306     if (bleaf == tleaf) /* anything to replant? */
307     return;
308 gregl 3.3 qtFreeTree(0); /* blow the tree away */
309 gregl 3.1 /* now rebuild it */
310     for (i = bleaf; i != tleaf; ) {
311     addleaf(leafpile+i);
312     if (++i >= nleaves) i = 0;
313     }
314     tmComputeMapping(0., 0., 0.); /* update the display */
315     qtUpdate();
316     }
317    
318    
319     static
320     redraw(ca, tp, x0, y0, x1, y1, l) /* redraw portion of a tree */
321     BYTE ca[3]; /* returned average color */
322     register RTREE *tp;
323     int x0, y0, x1, y1;
324     int l[2][2];
325     {
326     int csm[3], nc;
327     BYTE rgb[3];
328     int quads = CH_ANY;
329     int mx, my;
330     register int i;
331     /* compute midpoint */
332     mx = (x0 + x1) >> 1;
333     my = (y0 + y1) >> 1;
334     /* see what to do */
335     if (l[0][0] >= mx)
336     quads &= ~(CHF(2)|CHF(0));
337     else if (l[0][1] <= mx)
338     quads &= ~(CHF(3)|CHF(1));
339     if (l[1][0] >= my)
340     quads &= ~(CHF(1)|CHF(0));
341     else if (l[1][1] <= my)
342     quads &= ~(CHF(3)|CHF(2));
343     tp->flgs &= ~quads; /* mark them done */
344     csm[0] = csm[1] = csm[2] = nc = 0;
345     /* do leaves first */
346     for (i = 0; i < 4; i++)
347     if (quads & CHF(i) && !(tp->flgs & BRF(i)) &&
348     tp->k[i].l != NULL) {
349     tmMapPixels(rgb, &tp->k[i].l->brt, tp->k[i].l->chr, 1);
350     dev_paintr(rgb, i&01 ? mx : x0, i&02 ? my : y0,
351     i&01 ? x1 : mx, i&02 ? y1 : my);
352     csm[0] += rgb[0]; csm[1] += rgb[1]; csm[2] += rgb[2];
353     nc++;
354     quads &= ~CHF(i);
355     }
356     /* now do branches */
357     for (i = 0; i < 4; i++)
358     if (quads & CHF(i) && tp->flgs & BRF(i)) {
359     redraw(rgb, tp->k[i].b, i&01 ? mx : x0, i&02 ? my : y0,
360     i&01 ? x1 : mx, i&02 ? y1 : my, l);
361     csm[0] += rgb[0]; csm[1] += rgb[1]; csm[2] += rgb[2];
362     nc++;
363     quads &= ~CHF(i);
364     }
365     if (nc > 1) {
366     ca[0] = csm[0]/nc; ca[1] = csm[1]/nc; ca[2] = csm[2]/nc;
367     } else {
368     ca[0] = csm[0]; ca[1] = csm[1]; ca[2] = csm[2];
369     }
370     if (!quads) return;
371     /* fill in gaps with average */
372     for (i = 0; i < 4; i++)
373     if (quads & CHF(i))
374     dev_paintr(ca, i&01 ? mx : x0, i&02 ? my : y0,
375     i&01 ? x1 : mx, i&02 ? y1 : my);
376     }
377    
378    
379     static
380     update(ca, tp, x0, y0, x1, y1) /* update tree display as needed */
381     BYTE ca[3]; /* returned average color */
382     register RTREE *tp;
383     int x0, y0, x1, y1;
384     {
385     int csm[3], nc;
386     BYTE rgb[3];
387     int gaps = 0;
388     int mx, my;
389     register int i;
390     /* compute midpoint */
391     mx = (x0 + x1) >> 1;
392     my = (y0 + y1) >> 1;
393     csm[0] = csm[1] = csm[2] = nc = 0;
394     /* do leaves first */
395     for (i = 0; i < 4; i++)
396     if ((tp->flgs & CHBRF(i)) == CHF(i)) {
397     if (tp->k[i].l == NULL) {
398     gaps |= 1<<i; /* empty stem */
399     continue;
400     }
401     tmMapPixels(rgb, &tp->k[i].l->brt, tp->k[i].l->chr, 1);
402     dev_paintr(rgb, i&01 ? mx : x0, i&02 ? my : y0,
403     i&01 ? x1 : mx, i&02 ? y1 : my);
404     csm[0] += rgb[0]; csm[1] += rgb[1]; csm[2] += rgb[2];
405     nc++;
406     }
407     /* now do branches */
408     for (i = 0; i < 4; i++)
409     if ((tp->flgs & CHBRF(i)) == CHBRF(i)) {
410     update(rgb, tp->k[i].b, i&01 ? mx : x0, i&02 ? my : y0,
411     i&01 ? x1 : mx, i&02 ? y1 : my);
412     csm[0] += rgb[0]; csm[1] += rgb[1]; csm[2] += rgb[2];
413     nc++;
414     }
415     if (nc > 1) {
416     ca[0] = csm[0]/nc; ca[1] = csm[1]/nc; ca[2] = csm[2]/nc;
417     } else {
418     ca[0] = csm[0]; ca[1] = csm[1]; ca[2] = csm[2];
419     }
420     /* fill in gaps with average */
421     for (i = 0; gaps && i < 4; gaps >>= 1, i++)
422     if (gaps & 01)
423     dev_paintr(ca, i&01 ? mx : x0, i&02 ? my : y0,
424     i&01 ? x1 : mx, i&02 ? y1 : my);
425     tp->flgs &= ~CH_ANY; /* all done */
426     }
427    
428    
429     qtRedraw(x0, y0, x1, y1) /* redraw part of our screen */
430     int x0, y0, x1, y1;
431     {
432     int lim[2][2];
433     BYTE ca[3];
434    
435     if (is_stump(&qtrunk))
436     return;
437 gregl 3.4 if ((lim[0][0]=x0) <= 0 & (lim[1][0]=y0) <= 0 &
438     (lim[0][1]=x1) >= odev.hres-1 & (lim[1][1]=y1) >= odev.vres-1
439     || tmTop->lumap == NULL)
440     if (tmComputeMapping(0., 0., 0.) != TM_E_OK)
441     return;
442 gregl 3.1 redraw(ca, &qtrunk, 0, 0, odev.hres, odev.vres, lim);
443     }
444    
445    
446     qtUpdate() /* update our tree display */
447     {
448     BYTE ca[3];
449    
450     if (is_stump(&qtrunk))
451     return;
452     if (tmTop->lumap == NULL)
453     tmComputeMapping(0., 0., 0.);
454     update(ca, &qtrunk, 0, 0, odev.hres, odev.vres);
455     }