ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.45
Committed: Tue Jan 21 22:30:01 2025 UTC (3 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.44: +4 -3 lines
Log Message:
fix(rholo): Minimum # rays/packet was zero in some cases

File Contents

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