ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.41
Committed: Thu Jan 1 11:21:55 2004 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.40: +53 -33 lines
Log Message:
Ansification and prototypes.

File Contents

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