ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.13
Committed: Mon Dec 15 20:44:28 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.12: +38 -65 lines
Log Message:
eliminated OCCUPANCY variable and improved beam volume calculation

File Contents

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
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 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
21
22 int
23 beamcmp(b0, b1) /* comparison for descending compute order */
24 register PACKHEAD *b0, *b1;
25 {
26 return( b1->nr*(b0->nc+1) - b0->nr*(b1->nc+1) );
27 }
28
29
30 bundle_set(op, clist, nents) /* bundle set operation */
31 int op;
32 PACKHEAD *clist;
33 int nents;
34 {
35 BEAM *b;
36 PACKHEAD *p;
37 register int i, n;
38
39 switch (op) {
40 case BS_NEW: /* new computation set */
41 if (complen)
42 free((char *)complist);
43 if (nents <= 0) {
44 complist = NULL;
45 listpos = complen = 0;
46 lastin = -1;
47 return;
48 }
49 complist = (PACKHEAD *)malloc(nents*sizeof(PACKHEAD));
50 if (complist == NULL)
51 goto memerr;
52 bcopy((char *)clist, (char *)complist, nents*sizeof(PACKHEAD));
53 complen = nents; /* finish initialization below */
54 break;
55 case BS_ADD: /* add to computation set */
56 case BS_ADJ: /* adjust set quantities */
57 if (nents <= 0)
58 return;
59 /* merge any common members */
60 for (n = 0; n < nents; n++) {
61 for (i = 0; i < complen; i++)
62 if (clist[n].bi == complist[i].bi &&
63 clist[n].hd == complist[i].hd) {
64 int oldnr = complist[i].nr;
65 if (op == BS_ADD)
66 complist[i].nr += clist[n].nr;
67 else /* op == BS_ADJ */
68 complist[i].nr = clist[n].nr;
69 clist[n].nr = 0;
70 clist[n].nc = complist[i].nc;
71 if (complist[i].nr != oldnr)
72 lastin = -1; /* flag sort */
73 break;
74 }
75 if (i >= complen)
76 clist[n].nc = bnrays(hdlist[clist[n].hd],
77 clist[n].bi);
78 }
79 /* sort updated list */
80 sortcomplist();
81 /* sort new entries */
82 qsort((char *)clist, nents, sizeof(PACKHEAD), beamcmp);
83 /* what can't we satisfy? */
84 for (n = 0; n < nents && clist[n].nr > clist[n].nc; n++)
85 ;
86 if (op == BS_ADJ)
87 nents = n;
88 if (n) { /* allocate space for merged list */
89 PACKHEAD *newlist;
90 newlist = (PACKHEAD *)malloc(
91 (complen+n)*sizeof(PACKHEAD) );
92 if (newlist == NULL)
93 goto memerr;
94 /* merge lists */
95 mergeclists(newlist, clist, n, complist, complen);
96 if (complen)
97 free((char *)complist);
98 complist = newlist;
99 complen += n;
100 }
101 listpos = 0;
102 lastin = complen-1; /* list is now sorted */
103 break;
104 case BS_DEL: /* delete from computation set */
105 if (nents <= 0)
106 return;
107 /* find each member */
108 for (i = 0; i < complen; i++)
109 for (n = 0; n < nents; n++)
110 if (clist[n].bi == complist[i].bi &&
111 clist[n].hd == complist[i].hd) {
112 if (clist[n].nr == 0 ||
113 clist[n].nr >= complist[i].nr)
114 complist[i].nr = 0;
115 else
116 complist[i].nr -= clist[n].nr;
117 lastin = -1; /* flag full sort */
118 break;
119 }
120 return; /* no display */
121 default:
122 error(CONSISTENCY, "bundle_set called with unknown operation");
123 }
124 if (outdev == NULL)
125 return;
126 n = 32*RPACKSIZ; /* allocate packet holder */
127 p = (PACKHEAD *)malloc(packsiz(n));
128 if (p == NULL)
129 goto memerr;
130 /* display what we have */
131 for (i = 0; i < nents; i++)
132 if ((b = hdgetbeam(hdlist[clist[i].hd], clist[i].bi)) != NULL) {
133 if (b->nrm > n) {
134 n = b->nrm;
135 p = (PACKHEAD *)realloc((char *)p, packsiz(n));
136 if (p == NULL)
137 goto memerr;
138 }
139 bcopy((char *)hdbray(b), (char *)packra(p),
140 b->nrm*sizeof(RAYVAL));
141 p->hd = clist[i].hd;
142 p->bi = clist[i].bi;
143 p->nr = p->nc = b->nrm;
144 disp_packet(p);
145 }
146 free((char *)p); /* clean up */
147 if (op == BS_NEW) {
148 done_packets(flush_queue()); /* empty queue, so we can... */
149 for (i = 0; i < complen; i++) /* ...get number computed */
150 complist[i].nc = bnrays(hdlist[complist[i].hd],
151 complist[i].bi);
152 listpos = 0;
153 lastin = -1; /* flag for initial sort */
154 }
155 return;
156 memerr:
157 error(SYSTEM, "out of memory in bundle_set");
158 }
159
160
161 double
162 beamvolume(hp, bi) /* compute approximate volume of a beam */
163 HOLO *hp;
164 int bi;
165 {
166 GCOORD gc[2];
167 FVECT cp[4], edgeA, edgeB, cent[2];
168 FVECT v, crossp[2], diffv;
169 double vol[2];
170 register int i;
171 /* get grid coordinates */
172 if (!hdbcoord(gc, hp, bi))
173 error(CONSISTENCY, "bad beam index in beamvolume");
174 for (i = 0; i < 2; i++) { /* compute cell area vectors */
175 hdcell(cp, hp, gc+i);
176 VSUM(edgeA, cp[1], cp[0], -1.0);
177 VSUM(edgeB, cp[3], cp[1], -1.0);
178 fcross(crossp[i], edgeA, edgeB);
179 VSUM(edgeA, cp[2], cp[3], -1.0);
180 VSUM(edgeB, cp[0], cp[2], -1.0);
181 fcross(v, edgeA, edgeB);
182 VSUM(crossp[i], crossp[i], v, 1.0);
183 /* compute center */
184 cent[i][0] = 0.5*(cp[0][0] + cp[2][0]);
185 cent[i][1] = 0.5*(cp[0][1] + cp[2][1]);
186 cent[i][2] = 0.5*(cp[0][2] + cp[2][2]);
187 }
188 /* compute difference vector */
189 VSUM(diffv, cent[1], cent[0], -1.0);
190 for (i = 0; i < 2; i++) { /* compute volume contributions */
191 vol[i] = 0.25*DOT(crossp[i], diffv);
192 if (vol[i] < 0.) vol[i] = -vol[i];
193 }
194 return(vol[0] + vol[1]); /* return total volume */
195 }
196
197
198 init_global() /* initialize global ray computation */
199 {
200 long wtotal = 0;
201 double frac;
202 int i;
203 register int j, k;
204 /* free old list */
205 if (complen > 0)
206 free((char *)complist);
207 /* allocate beam list */
208 complen = 0;
209 for (j = 0; hdlist[j] != NULL; j++)
210 complen += nbeams(hdlist[j]);
211 complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD));
212 if (complist == NULL)
213 error(SYSTEM, "out of memory in init_global");
214 /* compute beam weights */
215 k = 0;
216 for (j = 0; hdlist[j] != NULL; j++) {
217 frac = 512. * hdlist[j]->wg[0] *
218 hdlist[j]->wg[1] * hdlist[j]->wg[2];
219 for (i = nbeams(hdlist[j]); i > 0; i--) {
220 complist[k].hd = j;
221 complist[k].bi = i;
222 complist[k].nr = frac*beamvolume(hdlist[j], i) + 0.5;
223 wtotal += complist[k++].nr;
224 }
225 }
226 /* adjust weights */
227 if (vdef(DISKSPACE))
228 frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL));
229 else
230 frac = 1024.*1024.*16384. / (wtotal*sizeof(RAYVAL));
231 while (k--)
232 complist[k].nr = frac * complist[k].nr;
233 listpos = 0; lastin = -1; /* flag initial sort */
234 }
235
236
237 mergeclists(cdest, cl1, n1, cl2, n2) /* merge two sorted lists */
238 PACKHEAD *cdest;
239 PACKHEAD *cl1, *cl2;
240 int n1, n2;
241 {
242 int cmp;
243
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 register int i;
264
265 if (complen <= 0) /* check to see if there is even a list */
266 return;
267 if (lastin < 0 || listpos*4 >= complen*3)
268 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 /* drop satisfied requests */
280 for (i = complen; i-- && complist[i].nr <= complist[i].nc; )
281 ;
282 if (i < 0) {
283 free((char *)complist);
284 complist = NULL;
285 complen = 0;
286 } else if (i < complen-1) {
287 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 }
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 * list and start again from the beginning. Since
305 * a merge sort is used, the sorting costs are minimal.
306 */
307 next_packet(p) /* prepare packet for computation */
308 register PACKET *p;
309 {
310 register int i;
311
312 if (listpos > lastin) /* time to sort the list */
313 sortcomplist();
314 if (complen <= 0)
315 return(0);
316 p->hd = complist[listpos].hd;
317 p->bi = complist[listpos].bi;
318 p->nc = complist[listpos].nc;
319 p->nr = complist[listpos].nr - p->nc;
320 if (p->nr <= 0)
321 return(0);
322 if (p->nr > RPACKSIZ)
323 p->nr = RPACKSIZ;
324 complist[listpos].nc += p->nr; /* find where this one would go */
325 while (lastin > listpos &&
326 beamcmp(complist+lastin, complist+listpos) > 0)
327 lastin--;
328 listpos++;
329 return(1);
330 }