ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.42
Committed: Tue Jun 8 19:48:30 2004 UTC (19 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 3.41: +1 -6 lines
Log Message:
Removed redundant #include's and fixed ordering on some headers

File Contents

# User Rev Content
1 gwlarson 3.23 #ifndef lint
2 greg 3.42 static const char RCSid[] = "$Id: rholo3.c,v 3.41 2004/01/01 11:21:55 schorsch Exp $";
3 gwlarson 3.23 #endif
4 gregl 3.1 /*
5     * Routines for tracking beam compuatations
6     */
7    
8     #include "rholo.h"
9    
10 gwlarson 3.27 #ifndef NFRAG2CHUNK
11     #define NFRAG2CHUNK 4096 /* number of fragments to start chunking */
12     #endif
13    
14     #ifndef abs
15 gregl 3.1 #define abs(x) ((x) > 0 ? (x) : -(x))
16 gwlarson 3.27 #endif
17     #ifndef sgn
18 gregl 3.1 #define sgn(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
19 gwlarson 3.27 #endif
20 gregl 3.1
21 gwlarson 3.27 #define rchunk(n) (((n)+(RPACKSIZ/2))/RPACKSIZ)
22    
23 gwlarson 3.30 int chunkycmp = 0; /* clump beams together on disk */
24    
25 gregl 3.4 static PACKHEAD *complist=NULL; /* list of beams to compute */
26     static int complen=0; /* length of complist */
27     static int listpos=0; /* current list position for next_packet */
28     static int lastin= -1; /* last ordered position in list */
29 gregl 3.1
30 schorsch 3.41 static void sortcomplist(void);
31     static void mergeclists(PACKHEAD *cdest, PACKHEAD *cl1, int n1, PACKHEAD *cl2, int n2);
32     static void view_list(FILE *fp);
33     static void ambient_list(void);
34     static double beamvolume(HOLO *hp, int bi);
35     static void dispbeam(BEAM *b, HDBEAMI *hb);
36    
37 gregl 3.1
38 schorsch 3.41
39     static int
40 gwlarson 3.23 beamcmp(b0, b1) /* comparison for compute order */
41 gregl 3.2 register PACKHEAD *b0, *b1;
42     {
43 gwlarson 3.27 BEAMI *bip0, *bip1;
44     register long c;
45     /* first check desired quantities */
46 gwlarson 3.30 if (chunkycmp)
47 gwlarson 3.28 c = rchunk(b1->nr)*(rchunk(b0->nc)+1L) -
48     rchunk(b0->nr)*(rchunk(b1->nc)+1L);
49 gwlarson 3.27 else
50 gwlarson 3.28 c = b1->nr*(b0->nc+1L) - b0->nr*(b1->nc+1L);
51     if (c > 0) return(1);
52     if (c < 0) return(-1);
53 gwlarson 3.27 /* only one file, so skip the following: */
54     #if 0
55     /* next, check file descriptors */
56     c = hdlist[b0->hd]->fd - hdlist[b1->hd]->fd;
57     if (c) return(c);
58     #endif
59     /* finally, check file positions */
60     bip0 = &hdlist[b0->hd]->bi[b0->bi];
61     bip1 = &hdlist[b1->hd]->bi[b1->bi];
62     /* put diskless beams last */
63     if (!bip0->nrd)
64     return(bip1->nrd > 0);
65     if (!bip1->nrd)
66     return(-1);
67     c = bip0->fo - bip1->fo;
68     return(c < 0 ? -1 : c > 0);
69 gregl 3.2 }
70    
71    
72 gregl 3.14 int
73 gwlarson 3.23 beamidcmp(b0, b1) /* comparison for beam searching */
74     register PACKHEAD *b0, *b1;
75     {
76     register int c = b0->hd - b1->hd;
77    
78     if (c) return(c);
79     return(b0->bi - b1->bi);
80     }
81    
82    
83 schorsch 3.41 static void
84     dispbeam( /* display a holodeck beam */
85     register BEAM *b,
86     register HDBEAMI *hb
87     )
88 gregl 3.14 {
89     static int n = 0;
90     static PACKHEAD *p = NULL;
91    
92     if (b == NULL)
93     return;
94     if (b->nrm > n) { /* (re)allocate packet holder */
95     n = b->nrm;
96     if (p == NULL) p = (PACKHEAD *)malloc(packsiz(n));
97 greg 3.35 else p = (PACKHEAD *)realloc((void *)p, packsiz(n));
98 gwlarson 3.31 CHECK(p==NULL, SYSTEM, "out of memory in dispbeam");
99 gregl 3.14 }
100     /* assign packet fields */
101 schorsch 3.38 memcpy((void *)packra(p), (void *)hdbray(b), b->nrm*sizeof(RAYVAL));
102 gregl 3.14 p->nr = p->nc = b->nrm;
103 gwlarson 3.23 for (p->hd = 0; hdlist[p->hd] != hb->h; p->hd++)
104 gregl 3.14 if (hdlist[p->hd] == NULL)
105     error(CONSISTENCY, "unregistered holodeck in dispbeam");
106 gwlarson 3.23 p->bi = hb->b;
107 gregl 3.14 disp_packet(p); /* display it */
108 gwlarson 3.29 if (n >= 1024) { /* free ridiculous packets */
109 greg 3.34 free((void *)p);
110 gwlarson 3.29 p = NULL; n = 0;
111     }
112 gregl 3.14 }
113    
114    
115 schorsch 3.41 extern void
116     bundle_set( /* bundle set operation */
117     int op,
118     PACKHEAD *clist,
119     int nents
120     )
121 gregl 3.2 {
122 gwlarson 3.23 int oldnr, n;
123     HDBEAMI *hbarr;
124     register PACKHEAD *csm;
125     register int i;
126     /* search for common members */
127     for (csm = clist+nents; csm-- > clist; )
128     csm->nc = -1;
129 greg 3.36 qsort((void *)clist, nents, sizeof(PACKHEAD), beamidcmp);
130 gwlarson 3.23 for (i = 0; i < complen; i++) {
131 greg 3.36 csm = (PACKHEAD *)bsearch((void *)(complist+i), (void *)clist,
132 gwlarson 3.23 nents, sizeof(PACKHEAD), beamidcmp);
133     if (csm == NULL)
134     continue;
135     oldnr = complist[i].nr;
136     csm->nc = complist[i].nc;
137     switch (op) {
138     case BS_ADD: /* add to count */
139     complist[i].nr += csm->nr;
140     csm->nr = 0;
141     break;
142 gwlarson 3.31 case BS_MAX: /* maximum of counts */
143     if (csm->nr > complist[i].nr)
144     complist[i].nr = csm->nr;
145     csm->nr = 0;
146     break;
147 gwlarson 3.23 case BS_ADJ: /* reset count */
148     complist[i].nr = csm->nr;
149     csm->nr = 0;
150     break;
151     case BS_DEL: /* delete count */
152     if (csm->nr == 0 || csm->nr >= complist[i].nr)
153     complist[i].nr = 0;
154     else
155     complist[i].nr -= csm->nr;
156     break;
157     }
158     if (complist[i].nr != oldnr)
159     lastin = -1; /* flag sort */
160 gregl 3.20 }
161 gwlarson 3.24 /* record computed rays for uncommon beams */
162 gwlarson 3.23 for (csm = clist+nents; csm-- > clist; )
163     if (csm->nc < 0)
164     csm->nc = bnrays(hdlist[csm->hd], csm->bi);
165 gregl 3.20 /* complete list operations */
166 gregl 3.2 switch (op) {
167     case BS_NEW: /* new computation set */
168 gwlarson 3.21 listpos = 0; lastin = -1;
169 gregl 3.20 if (complen) /* free old list */
170 greg 3.34 free((void *)complist);
171 gregl 3.20 complist = NULL;
172     if (!(complen = nents))
173 gregl 3.2 return;
174     complist = (PACKHEAD *)malloc(nents*sizeof(PACKHEAD));
175     if (complist == NULL)
176     goto memerr;
177 schorsch 3.38 memcpy((void *)complist, (void *)clist, nents*sizeof(PACKHEAD));
178 gregl 3.2 break;
179     case BS_ADD: /* add to computation set */
180 gwlarson 3.31 case BS_MAX: /* maximum of quantities */
181 gregl 3.11 case BS_ADJ: /* adjust set quantities */
182 gregl 3.2 if (nents <= 0)
183     return;
184 gregl 3.20 sortcomplist(); /* sort updated list & new entries */
185 greg 3.36 qsort((void *)clist, nents, sizeof(PACKHEAD), beamcmp);
186 gregl 3.2 /* what can't we satisfy? */
187 gwlarson 3.23 for (i = nents, csm = clist; i-- && csm->nr > csm->nc; csm++)
188 gregl 3.2 ;
189 gwlarson 3.23 n = csm - clist;
190 gwlarson 3.31 if (op != BS_ADD) { /* don't regenerate adjusted beams */
191 gwlarson 3.24 for (++i; i-- && csm->nr > 0; csm++)
192 gwlarson 3.22 ;
193 gwlarson 3.24 nents = csm - clist;
194 gwlarson 3.22 }
195 gregl 3.2 if (n) { /* allocate space for merged list */
196     PACKHEAD *newlist;
197     newlist = (PACKHEAD *)malloc(
198     (complen+n)*sizeof(PACKHEAD) );
199     if (newlist == NULL)
200     goto memerr;
201     /* merge lists */
202     mergeclists(newlist, clist, n, complist, complen);
203     if (complen)
204 greg 3.34 free((void *)complist);
205 gregl 3.2 complist = newlist;
206     complen += n;
207     }
208     listpos = 0;
209     lastin = complen-1; /* list is now sorted */
210     break;
211     case BS_DEL: /* delete from computation set */
212 gregl 3.20 return; /* already done */
213 gregl 3.2 default:
214     error(CONSISTENCY, "bundle_set called with unknown operation");
215     }
216 gwlarson 3.27 if (outdev == NULL || !nents) /* nothing to display? */
217 gwlarson 3.22 return;
218     /* load and display beams we have */
219 gwlarson 3.23 hbarr = (HDBEAMI *)malloc(nents*sizeof(HDBEAMI));
220     for (i = nents; i--; ) {
221     hbarr[i].h = hdlist[clist[i].hd];
222     hbarr[i].b = clist[i].bi;
223 gregl 3.11 }
224 gwlarson 3.23 hdloadbeams(hbarr, nents, dispbeam);
225 greg 3.34 free((void *)hbarr);
226 gwlarson 3.27 if (hdfragflags&FF_READ) {
227     listpos = 0;
228     lastin = -1; /* need to re-sort list */
229     }
230 gregl 3.2 return;
231     memerr:
232     error(SYSTEM, "out of memory in bundle_set");
233     }
234    
235    
236 schorsch 3.41 static double
237     beamvolume( /* compute approximate volume of a beam */
238     HOLO *hp,
239     int bi
240     )
241 gregl 3.1 {
242 gregl 3.13 GCOORD gc[2];
243     FVECT cp[4], edgeA, edgeB, cent[2];
244 schorsch 3.41 FVECT crossp[2], diffv;
245 gregl 3.13 double vol[2];
246     register int i;
247     /* get grid coordinates */
248     if (!hdbcoord(gc, hp, bi))
249     error(CONSISTENCY, "bad beam index in beamvolume");
250     for (i = 0; i < 2; i++) { /* compute cell area vectors */
251     hdcell(cp, hp, gc+i);
252     VSUM(edgeA, cp[1], cp[0], -1.0);
253     VSUM(edgeB, cp[3], cp[1], -1.0);
254     fcross(crossp[i], edgeA, edgeB);
255     /* compute center */
256     cent[i][0] = 0.5*(cp[0][0] + cp[2][0]);
257     cent[i][1] = 0.5*(cp[0][1] + cp[2][1]);
258     cent[i][2] = 0.5*(cp[0][2] + cp[2][2]);
259 gregl 3.1 }
260 gregl 3.13 /* compute difference vector */
261     VSUM(diffv, cent[1], cent[0], -1.0);
262     for (i = 0; i < 2; i++) { /* compute volume contributions */
263 gregl 3.15 vol[i] = 0.5*DOT(crossp[i], diffv);
264 gregl 3.13 if (vol[i] < 0.) vol[i] = -vol[i];
265     }
266     return(vol[0] + vol[1]); /* return total volume */
267 gregl 3.1 }
268    
269    
270 schorsch 3.41 static void
271     ambient_list(void) /* compute ambient beam list */
272 gregl 3.1 {
273 greg 3.37 int32 wtotal, minrt;
274 gregl 3.1 double frac;
275 gregl 3.13 int i;
276     register int j, k;
277 gwlarson 3.31
278 gregl 3.1 complen = 0;
279     for (j = 0; hdlist[j] != NULL; j++)
280     complen += nbeams(hdlist[j]);
281     complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD));
282 gwlarson 3.31 CHECK(complist==NULL, SYSTEM, "out of memory in ambient_list");
283 gregl 3.1 /* compute beam weights */
284 gwlarson 3.32 k = 0; wtotal = 0;
285 gregl 3.13 for (j = 0; hdlist[j] != NULL; j++) {
286 gregl 3.19 frac = 512. * VLEN(hdlist[j]->wg[0]) *
287     VLEN(hdlist[j]->wg[1]) *
288     VLEN(hdlist[j]->wg[2]);
289 gregl 3.1 for (i = nbeams(hdlist[j]); i > 0; i--) {
290     complist[k].hd = j;
291     complist[k].bi = i;
292 gregl 3.13 complist[k].nr = frac*beamvolume(hdlist[j], i) + 0.5;
293 gregl 3.18 complist[k].nc = bnrays(hdlist[j], i);
294 gregl 3.1 wtotal += complist[k++].nr;
295     }
296 gregl 3.13 }
297 gwlarson 3.31 /* adjust sample weights */
298 gregl 3.12 if (vdef(DISKSPACE))
299 gwlarson 3.32 frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL));
300 gregl 3.12 else
301 gwlarson 3.32 frac = 1024.*1024.*2048. / (wtotal*sizeof(RAYVAL));
302     minrt = .02*frac*wtotal/complen + .5; /* heuristic mimimum */
303     if (minrt > RPACKSIZ)
304     minrt = RPACKSIZ;
305     for (k = complen; k--; )
306     if ((complist[k].nr = frac*complist[k].nr + 0.5) < minrt)
307     complist[k].nr = minrt;
308 gwlarson 3.31 listpos = 0; lastin = -1; /* flag initial sort */
309     }
310    
311    
312 schorsch 3.41 static void
313     view_list( /* assign beam priority from view list */
314     FILE *fp
315     )
316 gwlarson 3.31 {
317     double pa = 1.;
318     VIEW curview;
319     int xr, yr;
320     char *err;
321     BEAMLIST blist;
322    
323 schorsch 3.40 curview = stdview;
324 gwlarson 3.31 while (nextview(&curview, fp) != EOF) {
325     if ((err = setview(&curview)) != NULL) {
326     error(WARNING, err);
327     continue;
328     }
329     xr = yr = 1024;
330     normaspect(viewaspect(&curview), &pa, &xr, &yr);
331     viewbeams(&curview, xr, yr, &blist);
332     bundle_set(BS_MAX, blist.bl, blist.nb);
333 greg 3.34 free((void *)blist.bl);
334 gwlarson 3.31 }
335     }
336    
337    
338 schorsch 3.41 extern void
339     init_global(void) /* initialize global ray computation */
340 gwlarson 3.31 {
341     /* free old list and empty queue */
342     if (complen > 0) {
343 greg 3.34 free((void *)complist);
344 gwlarson 3.31 done_packets(flush_queue());
345     }
346     /* reseed random number generator */
347     srandom(time(NULL));
348     /* allocate beam list */
349     if (readinp)
350     view_list(stdin);
351     else
352     ambient_list();
353 gwlarson 3.25 /* no view vicinity */
354     myeye.rng = 0;
355 gregl 3.1 }
356    
357    
358 schorsch 3.41 static void
359     mergeclists( /* merge two sorted lists */
360     register PACKHEAD *cdest,
361     register PACKHEAD *cl1,
362     int n1,
363     register PACKHEAD *cl2,
364     int n2
365     )
366 gregl 3.1 {
367 gregl 3.16 register int cmp;
368 gregl 3.1
369     while (n1 | n2) {
370     if (!n1) cmp = 1;
371     else if (!n2) cmp = -1;
372     else cmp = beamcmp(cl1, cl2);
373     if (cmp > 0) {
374 schorsch 3.40 *cdest = *cl2;
375 gregl 3.1 cl2++; n2--;
376     } else {
377 schorsch 3.40 *cdest = *cl1;
378 gregl 3.1 cl1++; n1--;
379     }
380     cdest++;
381     }
382     }
383    
384    
385 schorsch 3.41 static void
386     sortcomplist(void) /* fix our list order */
387 gregl 3.1 {
388     PACKHEAD *list2;
389 gwlarson 3.27 int listlen;
390 gregl 3.2 register int i;
391    
392 gregl 3.3 if (complen <= 0) /* check to see if there is even a list */
393 gregl 3.2 return;
394 gwlarson 3.30 if (!chunkycmp) /* check to see if fragment list is full */
395 gwlarson 3.27 if (!hdfragOK(hdlist[0]->fd, &listlen, NULL)
396     #if NFRAG2CHUNK
397     || listlen >= NFRAG2CHUNK
398     #endif
399     ) {
400 gwlarson 3.30 chunkycmp++; /* use "chunky" comparison */
401     lastin = -1; /* need to re-sort list */
402 gwlarson 3.27 #ifdef DEBUG
403     error(WARNING, "using chunky comparison mode");
404     #endif
405     }
406 gregl 3.6 if (lastin < 0 || listpos*4 >= complen*3)
407 greg 3.36 qsort((void *)complist, complen, sizeof(PACKHEAD), beamcmp);
408 gregl 3.1 else if (listpos) { /* else sort and merge sublist */
409     list2 = (PACKHEAD *)malloc(listpos*sizeof(PACKHEAD));
410 gwlarson 3.31 CHECK(list2==NULL, SYSTEM, "out of memory in sortcomplist");
411 schorsch 3.38 memcpy((void *)list2,(void *)complist,listpos*sizeof(PACKHEAD));
412 greg 3.36 qsort((void *)list2, listpos, sizeof(PACKHEAD), beamcmp);
413 gregl 3.1 mergeclists(complist, list2, listpos,
414     complist+listpos, complen-listpos);
415 greg 3.34 free((void *)list2);
416 gregl 3.1 }
417 gregl 3.2 /* drop satisfied requests */
418 gregl 3.11 for (i = complen; i-- && complist[i].nr <= complist[i].nc; )
419 gregl 3.2 ;
420 gregl 3.4 if (i < 0) {
421 greg 3.34 free((void *)complist);
422 gregl 3.4 complist = NULL;
423     complen = 0;
424     } else if (i < complen-1) {
425 greg 3.35 list2 = (PACKHEAD *)realloc((void *)complist,
426 gregl 3.2 (i+1)*sizeof(PACKHEAD));
427 gwlarson 3.26 if (list2 != NULL)
428 gregl 3.2 complist = list2;
429 gwlarson 3.26 complen = i+1;
430 gregl 3.2 }
431     listpos = 0; lastin = i;
432 gregl 3.1 }
433    
434    
435     /*
436     * The following routine works on the assumption that the bundle weights are
437     * more or less evenly distributed, such that computing a packet causes
438     * a given bundle to move way down in the computation order. We keep
439     * track of where the computed bundle with the highest priority would end
440 gwlarson 3.27 * up, and if we get further in our compute list than this, we re-sort the
441 gregl 3.11 * list and start again from the beginning. Since
442     * a merge sort is used, the sorting costs are minimal.
443 gregl 3.1 */
444 schorsch 3.41 extern int
445     next_packet( /* prepare packet for computation */
446     register PACKET *p,
447     int n
448     )
449 gregl 3.1 {
450 gregl 3.10 if (listpos > lastin) /* time to sort the list */
451     sortcomplist();
452 gregl 3.1 if (complen <= 0)
453     return(0);
454     p->hd = complist[listpos].hd;
455     p->bi = complist[listpos].bi;
456 gregl 3.11 p->nc = complist[listpos].nc;
457     p->nr = complist[listpos].nr - p->nc;
458 gregl 3.1 if (p->nr <= 0)
459     return(0);
460 gwlarson 3.28 DCHECK(n < 1 | n > RPACKSIZ,
461     CONSISTENCY, "next_packet called with bad n value");
462 gregl 3.17 if (p->nr > n)
463     p->nr = n;
464 gregl 3.11 complist[listpos].nc += p->nr; /* find where this one would go */
465 gwlarson 3.27 if (hdgetbeam(hdlist[p->hd], p->bi) != NULL)
466     hdfreefrag(hdlist[p->hd], p->bi);
467 gregl 3.11 while (lastin > listpos &&
468     beamcmp(complist+lastin, complist+listpos) > 0)
469 gregl 3.1 lastin--;
470     listpos++;
471     return(1);
472     }