ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.21
Committed: Mon Feb 2 11:42:10 1998 UTC (26 years, 2 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.20: +3 -3 lines
Log Message:
perform sorting in init_global() rather than delaying for later

File Contents

# User Rev Content
1 gregl 3.18 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2 gregl 3.1
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * Routines for tracking beam compuatations
9     */
10    
11     #include "rholo.h"
12    
13     #define abs(x) ((x) > 0 ? (x) : -(x))
14     #define sgn(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
15    
16 gregl 3.4 static PACKHEAD *complist=NULL; /* list of beams to compute */
17     static int complen=0; /* length of complist */
18     static int listpos=0; /* current list position for next_packet */
19     static int lastin= -1; /* last ordered position in list */
20 gregl 3.1
21    
22     int
23 gregl 3.2 beamcmp(b0, b1) /* comparison for descending compute order */
24     register PACKHEAD *b0, *b1;
25     {
26 gregl 3.11 return( b1->nr*(b0->nc+1) - b0->nr*(b1->nc+1) );
27 gregl 3.2 }
28    
29    
30 gregl 3.14 int
31     dispbeam(b, hp, bi) /* display a holodeck beam */
32     register BEAM *b;
33     HOLO *hp;
34     int bi;
35     {
36     static int n = 0;
37     static PACKHEAD *p = NULL;
38    
39     if (b == NULL)
40     return;
41     if (b->nrm > n) { /* (re)allocate packet holder */
42     n = b->nrm;
43     if (p == NULL) p = (PACKHEAD *)malloc(packsiz(n));
44     else p = (PACKHEAD *)realloc((char *)p, packsiz(n));
45     if (p == NULL)
46     error(SYSTEM, "out of memory in dispbeam");
47     }
48     /* assign packet fields */
49     bcopy((char *)hdbray(b), (char *)packra(p), b->nrm*sizeof(RAYVAL));
50     p->nr = p->nc = b->nrm;
51     for (p->hd = 0; hdlist[p->hd] != hp; p->hd++)
52     if (hdlist[p->hd] == NULL)
53     error(CONSISTENCY, "unregistered holodeck in dispbeam");
54     p->bi = bi;
55     disp_packet(p); /* display it */
56     }
57    
58    
59 gregl 3.2 bundle_set(op, clist, nents) /* bundle set operation */
60     int op;
61 gregl 3.14 register PACKHEAD *clist;
62 gregl 3.2 int nents;
63     {
64 gregl 3.20 int oldnr;
65 gregl 3.2 register int i, n;
66 gregl 3.20 /* look for common members */
67     for (n = 0; n < nents; n++) {
68     for (i = 0; i < complen; i++)
69     if (clist[n].bi == complist[i].bi &&
70     clist[n].hd == complist[i].hd) {
71     oldnr = complist[i].nr;
72     clist[n].nc = complist[i].nc;
73     switch (op) {
74     case BS_ADD: /* add to count */
75     complist[i].nr += clist[n].nr;
76     clist[n].nr = 0;
77     break;
78     case BS_ADJ: /* reset count */
79     complist[i].nr = clist[n].nr;
80     clist[n].nr = 0;
81     break;
82     case BS_DEL: /* delete count */
83     if (clist[n].nr == 0 ||
84     clist[n].nr >= complist[i].nr)
85     complist[i].nr = 0;
86     else
87     complist[i].nr -= clist[n].nr;
88     break;
89     }
90     if (complist[i].nr != oldnr)
91     lastin = -1; /* flag sort */
92     break;
93     }
94     if (i >= complen)
95     clist[n].nc = bnrays(hdlist[clist[n].hd], clist[n].bi);
96     }
97     /* complete list operations */
98 gregl 3.2 switch (op) {
99     case BS_NEW: /* new computation set */
100 gwlarson 3.21 listpos = 0; lastin = -1;
101 gregl 3.20 if (complen) /* free old list */
102 gregl 3.2 free((char *)complist);
103 gregl 3.20 complist = NULL;
104     if (!(complen = nents))
105 gregl 3.2 return;
106     complist = (PACKHEAD *)malloc(nents*sizeof(PACKHEAD));
107     if (complist == NULL)
108     goto memerr;
109     bcopy((char *)clist, (char *)complist, nents*sizeof(PACKHEAD));
110     break;
111     case BS_ADD: /* add to computation set */
112 gregl 3.11 case BS_ADJ: /* adjust set quantities */
113 gregl 3.2 if (nents <= 0)
114     return;
115 gregl 3.20 sortcomplist(); /* sort updated list & new entries */
116 gregl 3.2 qsort((char *)clist, nents, sizeof(PACKHEAD), beamcmp);
117     /* what can't we satisfy? */
118 gregl 3.11 for (n = 0; n < nents && clist[n].nr > clist[n].nc; n++)
119 gregl 3.2 ;
120 gregl 3.11 if (op == BS_ADJ)
121     nents = n;
122 gregl 3.2 if (n) { /* allocate space for merged list */
123     PACKHEAD *newlist;
124     newlist = (PACKHEAD *)malloc(
125     (complen+n)*sizeof(PACKHEAD) );
126     if (newlist == NULL)
127     goto memerr;
128     /* merge lists */
129     mergeclists(newlist, clist, n, complist, complen);
130     if (complen)
131     free((char *)complist);
132     complist = newlist;
133     complen += n;
134     }
135     listpos = 0;
136     lastin = complen-1; /* list is now sorted */
137     break;
138     case BS_DEL: /* delete from computation set */
139 gregl 3.20 return; /* already done */
140 gregl 3.2 default:
141     error(CONSISTENCY, "bundle_set called with unknown operation");
142     }
143 gregl 3.14 if (outdev != NULL) { /* load and display beams we have */
144     register HDBEAMI *hb;
145    
146     hb = (HDBEAMI *)malloc(nents*sizeof(HDBEAMI));
147     for (i = 0; i < nents; i++) {
148     hb[i].h = hdlist[clist[i].hd];
149     hb[i].b = clist[i].bi;
150 gregl 3.2 }
151 gregl 3.14 hdloadbeams(hb, nents, dispbeam);
152     free((char *)hb);
153 gregl 3.11 }
154 gregl 3.2 return;
155     memerr:
156     error(SYSTEM, "out of memory in bundle_set");
157     }
158    
159    
160 gregl 3.13 double
161     beamvolume(hp, bi) /* compute approximate volume of a beam */
162 gregl 3.1 HOLO *hp;
163 gregl 3.13 int bi;
164 gregl 3.1 {
165 gregl 3.13 GCOORD gc[2];
166     FVECT cp[4], edgeA, edgeB, cent[2];
167     FVECT v, crossp[2], diffv;
168     double vol[2];
169     register int i;
170     /* get grid coordinates */
171     if (!hdbcoord(gc, hp, bi))
172     error(CONSISTENCY, "bad beam index in beamvolume");
173     for (i = 0; i < 2; i++) { /* compute cell area vectors */
174     hdcell(cp, hp, gc+i);
175     VSUM(edgeA, cp[1], cp[0], -1.0);
176     VSUM(edgeB, cp[3], cp[1], -1.0);
177     fcross(crossp[i], edgeA, edgeB);
178     /* compute center */
179     cent[i][0] = 0.5*(cp[0][0] + cp[2][0]);
180     cent[i][1] = 0.5*(cp[0][1] + cp[2][1]);
181     cent[i][2] = 0.5*(cp[0][2] + cp[2][2]);
182 gregl 3.1 }
183 gregl 3.13 /* compute difference vector */
184     VSUM(diffv, cent[1], cent[0], -1.0);
185     for (i = 0; i < 2; i++) { /* compute volume contributions */
186 gregl 3.15 vol[i] = 0.5*DOT(crossp[i], diffv);
187 gregl 3.13 if (vol[i] < 0.) vol[i] = -vol[i];
188     }
189     return(vol[0] + vol[1]); /* return total volume */
190 gregl 3.1 }
191    
192    
193     init_global() /* initialize global ray computation */
194     {
195     long wtotal = 0;
196     double frac;
197 gregl 3.13 int i;
198     register int j, k;
199 gregl 3.18 /* free old list and empty queue */
200     if (complen > 0) {
201 gregl 3.3 free((char *)complist);
202 gregl 3.18 done_packets(flush_queue());
203     }
204 gregl 3.1 /* allocate beam list */
205     complen = 0;
206     for (j = 0; hdlist[j] != NULL; j++)
207     complen += nbeams(hdlist[j]);
208     complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD));
209     if (complist == NULL)
210     error(SYSTEM, "out of memory in init_global");
211     /* compute beam weights */
212     k = 0;
213 gregl 3.13 for (j = 0; hdlist[j] != NULL; j++) {
214 gregl 3.19 frac = 512. * VLEN(hdlist[j]->wg[0]) *
215     VLEN(hdlist[j]->wg[1]) *
216     VLEN(hdlist[j]->wg[2]);
217 gregl 3.1 for (i = nbeams(hdlist[j]); i > 0; i--) {
218     complist[k].hd = j;
219     complist[k].bi = i;
220 gregl 3.13 complist[k].nr = frac*beamvolume(hdlist[j], i) + 0.5;
221 gregl 3.18 complist[k].nc = bnrays(hdlist[j], i);
222 gregl 3.1 wtotal += complist[k++].nr;
223     }
224 gregl 3.13 }
225 gregl 3.1 /* adjust weights */
226 gregl 3.12 if (vdef(DISKSPACE))
227 gregl 3.1 frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL));
228 gregl 3.12 else
229     frac = 1024.*1024.*16384. / (wtotal*sizeof(RAYVAL));
230     while (k--)
231     complist[k].nr = frac * complist[k].nr;
232 gwlarson 3.21 listpos = 0; lastin = -1; /* perform initial sort */
233     sortcomplist();
234 gregl 3.1 }
235    
236    
237     mergeclists(cdest, cl1, n1, cl2, n2) /* merge two sorted lists */
238 gregl 3.16 register PACKHEAD *cdest;
239     register PACKHEAD *cl1, *cl2;
240 gregl 3.1 int n1, n2;
241     {
242 gregl 3.16 register int cmp;
243 gregl 3.1
244     while (n1 | n2) {
245     if (!n1) cmp = 1;
246     else if (!n2) cmp = -1;
247     else cmp = beamcmp(cl1, cl2);
248     if (cmp > 0) {
249     copystruct(cdest, cl2);
250     cl2++; n2--;
251     } else {
252     copystruct(cdest, cl1);
253     cl1++; n1--;
254     }
255     cdest++;
256     }
257     }
258    
259    
260     sortcomplist() /* fix our list order */
261     {
262     PACKHEAD *list2;
263 gregl 3.2 register int i;
264    
265 gregl 3.3 if (complen <= 0) /* check to see if there is even a list */
266 gregl 3.2 return;
267 gregl 3.6 if (lastin < 0 || listpos*4 >= complen*3)
268 gregl 3.1 qsort((char *)complist, complen, sizeof(PACKHEAD), beamcmp);
269     else if (listpos) { /* else sort and merge sublist */
270     list2 = (PACKHEAD *)malloc(listpos*sizeof(PACKHEAD));
271     if (list2 == NULL)
272     error(SYSTEM, "out of memory in sortcomplist");
273     bcopy((char *)complist,(char *)list2,listpos*sizeof(PACKHEAD));
274     qsort((char *)list2, listpos, sizeof(PACKHEAD), beamcmp);
275     mergeclists(complist, list2, listpos,
276     complist+listpos, complen-listpos);
277     free((char *)list2);
278     }
279 gregl 3.2 /* drop satisfied requests */
280 gregl 3.11 for (i = complen; i-- && complist[i].nr <= complist[i].nc; )
281 gregl 3.2 ;
282 gregl 3.4 if (i < 0) {
283     free((char *)complist);
284     complist = NULL;
285     complen = 0;
286     } else if (i < complen-1) {
287 gregl 3.2 list2 = (PACKHEAD *)realloc((char *)complist,
288     (i+1)*sizeof(PACKHEAD));
289     if (list2 != NULL) {
290     complist = list2;
291     complen = i+1;
292     }
293     }
294     listpos = 0; lastin = i;
295 gregl 3.1 }
296    
297    
298     /*
299     * The following routine works on the assumption that the bundle weights are
300     * more or less evenly distributed, such that computing a packet causes
301     * a given bundle to move way down in the computation order. We keep
302     * track of where the computed bundle with the highest priority would end
303     * up, and if we get further in our compute list than this, we resort the
304 gregl 3.11 * list and start again from the beginning. Since
305     * a merge sort is used, the sorting costs are minimal.
306 gregl 3.1 */
307 gregl 3.17 next_packet(p, n) /* prepare packet for computation */
308 gregl 3.1 register PACKET *p;
309 gregl 3.17 int n;
310 gregl 3.1 {
311     register int i;
312    
313 gregl 3.10 if (listpos > lastin) /* time to sort the list */
314     sortcomplist();
315 gregl 3.1 if (complen <= 0)
316     return(0);
317     p->hd = complist[listpos].hd;
318     p->bi = complist[listpos].bi;
319 gregl 3.11 p->nc = complist[listpos].nc;
320     p->nr = complist[listpos].nr - p->nc;
321 gregl 3.1 if (p->nr <= 0)
322     return(0);
323 gregl 3.17 #ifdef DEBUG
324     if (n < 1 | n > RPACKSIZ)
325     error(CONSISTENCY, "next_packet called with bad n value");
326     #endif
327     if (p->nr > n)
328     p->nr = n;
329 gregl 3.11 complist[listpos].nc += p->nr; /* find where this one would go */
330     while (lastin > listpos &&
331     beamcmp(complist+lastin, complist+listpos) > 0)
332 gregl 3.1 lastin--;
333     listpos++;
334     return(1);
335     }