ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.8
Committed: Tue Dec 2 15:02:37 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.7: +40 -0 lines
Log Message:
made beam list updating more efficient using DR_ADJSET request

File Contents

# User Rev Content
1 gregl 3.1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8 gregl 3.2 * Holodeck beam tracking for display process
9 gregl 3.1 */
10    
11     #include "rholo.h"
12     #include "rhdisp.h"
13     #include "rhdriver.h"
14    
15 gregl 3.5 extern GCOORD *getviewcells();
16 gregl 3.1
17 gregl 3.7 static VIEW dvw; /* current view corresponding to beam list */
18    
19 gregl 3.1 typedef struct {
20 gregl 3.2 int hd; /* holodeck section number (-1 if inactive) */
21 gregl 3.1 int i[3]; /* voxel index (may be outside section) */
22     } VOXL; /* a voxel */
23    
24     static VOXL voxel[8] = { /* current voxel list */
25     {-1}, {-1}, {-1}, {-1},
26     {-1}, {-1}, {-1}, {-1}
27     };
28    
29     #define CBEAMBLK 1024 /* cbeam allocation block size */
30    
31     static struct beamcomp {
32     short wants; /* flags telling which voxels want us */
33     short hd; /* holodeck section number */
34     int bi; /* beam index */
35     } *cbeam = NULL; /* current beam list */
36    
37     static int ncbeams = 0; /* number of sorted beams in cbeam */
38     static int xcbeams = 0; /* extra (unregistered) beams past ncbeams */
39     static int maxcbeam = 0; /* size of cbeam array */
40    
41     struct cellact {
42     short vi; /* voxel index */
43     short add; /* zero means delete */
44 gregl 3.5 short rev; /* reverse ray direction? */
45 gregl 3.1 }; /* action for cell */
46    
47     struct beamact {
48     struct cellact ca; /* cell action */
49     GCOORD gc; /* grid coordinate */
50     }; /* beam origin and action */
51    
52    
53     int
54     newcbeam() /* allocate new entry at end of cbeam array */
55     {
56     int i;
57    
58     if ((i = ncbeams + xcbeams++) >= maxcbeam) { /* grow array */
59     maxcbeam += CBEAMBLK;
60     if (cbeam == NULL)
61     cbeam = (struct beamcomp *)malloc(
62     maxcbeam*sizeof(struct beamcomp) );
63     else
64     cbeam = (struct beamcomp *)realloc( (char *)cbeam,
65     maxcbeam*sizeof(struct beamcomp) );
66     if (cbeam == NULL)
67     error(SYSTEM, "out of memory in newcbeam");
68     }
69     return(i);
70     }
71    
72    
73     int
74     cbeamcmp(cb1, cb2) /* compare two cbeam entries for sort: keep orphans */
75     register struct beamcomp *cb1, *cb2;
76     {
77     register int c;
78    
79     if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
80     return(c);
81     return(cb1->hd - cb2->hd); /* use hd to resolve matches */
82     }
83    
84    
85     int
86     cbeamcmp2(cb1, cb2) /* compare two cbeam entries for sort: no orphans */
87     register struct beamcomp *cb1, *cb2;
88     {
89     register int c;
90    
91     if (!cb1->wants) /* put orphans at the end, unsorted */
92     return(cb2->wants);
93     if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
94     return(c);
95     return(cb1->hd - cb2->hd); /* use hd to resolve matches */
96     }
97    
98    
99     int
100     findcbeam(hd, bi) /* find the specified beam in our sorted list */
101     int hd, bi;
102     {
103     struct beamcomp cb;
104     register struct beamcomp *p;
105    
106     if (ncbeams <= 0)
107     return(-1);
108     cb.wants = 0; cb.hd = hd; cb.bi = bi;
109     p = (struct beamcomp *)bsearch((char *)&cb, (char *)cbeam, ncbeams,
110     sizeof(struct beamcomp), cbeamcmp);
111     if (p == NULL)
112     return(-1);
113     return(p - cbeam);
114     }
115    
116    
117     int
118     getcbeam(hd, bi) /* get the specified beam, allocating as necessary */
119     register int hd;
120     int bi;
121     {
122     register int n;
123     /* first, look in sorted list */
124     if ((n = findcbeam(hd, bi)) >= 0)
125     return(n);
126     /* linear search through xcbeams to be sure */
127     for (n = ncbeams+xcbeams; n-- > ncbeams; )
128     if (cbeam[n].bi == bi && cbeam[n].hd == hd)
129     return(n);
130     /* check legality */
131     if (hd < 0 | hd >= HDMAX || hdlist[hd] == NULL)
132     error(INTERNAL, "illegal holodeck number in getcbeam");
133     if (bi < 1 | bi > nbeams(hdlist[hd]))
134     error(INTERNAL, "illegal beam index in getcbeam");
135     n = newcbeam(); /* allocate and assign */
136     cbeam[n].wants = 0; cbeam[n].hd = hd; cbeam[n].bi = bi;
137     return(n);
138     }
139    
140    
141     cbeamsort(adopt) /* sort our beam list, possibly turning out orphans */
142     int adopt;
143     {
144     register int i;
145    
146     if (!(ncbeams += xcbeams))
147     return;
148     xcbeams = 0;
149     qsort((char *)cbeam, ncbeams, sizeof(struct beamcomp),
150     adopt ? cbeamcmp : cbeamcmp2);
151     if (adopt)
152     return;
153     for (i = ncbeams; i--; ) /* identify orphans */
154     if (cbeam[i].wants)
155     break;
156     xcbeams = ncbeams - ++i; /* put orphans after ncbeams */
157     ncbeams = i;
158     }
159    
160    
161 gregl 3.8 cbeamadj(v, hr, vr) /* adjust our beam list */
162     VIEW *v;
163     int hr, vr;
164     {
165     register PACKHEAD *pa;
166     register int i;
167     int n;
168     /* first handle additions */
169     pa = (PACKHEAD *)malloc(xcbeams*sizeof(PACKHEAD));
170     if (xcbeams && pa == NULL)
171     goto memerr;
172     for (i = xcbeams; i--; ) {
173     pa[i].hd = cbeam[ncbeams+i].hd;
174     pa[i].bi = cbeam[ncbeams+i].bi;
175     pa[i].nr = npixels(v, hr, vr, hdlist[pa[i].hd], pa[i].bi);
176     }
177     n = xcbeams; /* now sort list for deletions */
178     cbeamsort(0);
179     pa = (PACKHEAD *)realloc((char *)pa, (n+xcbeams)*sizeof(PACKHEAD));
180     if (n+xcbeams && pa == NULL)
181     goto memerr;
182     for (i = xcbeams; i--; ) {
183     pa[n+i].hd = cbeam[ncbeams+i].hd;
184     pa[n+i].bi = cbeam[ncbeams+i].bi;
185     pa[n+i].nr = 0;
186     }
187     n += xcbeams;
188     xcbeams = 0; /* delete orphans */
189     serv_request(DR_ADJSET, n*sizeof(PACKHEAD), (char *)pa);
190     free((char *)pa);
191     return;
192     memerr:
193     error(SYSTEM, "out of memory in cbeamadj");
194     }
195    
196    
197 gregl 3.4 cbeamop(op, bl, n, v, hr, vr) /* update beams on server list */
198     int op;
199 gregl 3.1 register struct beamcomp *bl;
200     int n;
201     VIEW *v;
202     int hr, vr;
203     {
204     register PACKHEAD *pa;
205     register int i;
206    
207     if (n <= 0)
208     return;
209     pa = (PACKHEAD *)malloc(n*sizeof(PACKHEAD));
210     if (pa == NULL)
211     error(SYSTEM, "out of memory in cbeamadd");
212     for (i = 0; i < n; i++) {
213     pa[i].hd = bl[i].hd;
214     pa[i].bi = bl[i].bi;
215 gregl 3.4 pa[i].nr = v==NULL ? 0 :
216     npixels(v, hr, vr, hdlist[bl[i].hd], bl[i].bi);
217 gregl 3.1 }
218 gregl 3.4 serv_request(op, n*sizeof(PACKHEAD), (char *)pa);
219 gregl 3.1 free((char *)pa);
220     }
221    
222    
223     int
224     set_voxels(vl, n) /* set new voxel array */
225     VOXL vl[8];
226     int n;
227     {
228     short wmap[256];
229     int vmap[8];
230     int comn = 0;
231     int no;
232     register int i, j;
233     /* find common voxels */
234     for (j = 0; j < 8 && voxel[j].hd >= 0; j++) {
235     vmap[j] = -1;
236     for (i = n; i--; )
237     if (!bcmp((char *)(vl+i), (char *)(voxel+j),
238     sizeof(VOXL))) {
239     vmap[j] = i;
240     comn |= 1<<i;
241     break;
242     }
243     }
244     no = comn ? j : 0; /* compute flag mapping */
245     for (i = 256; i--; ) {
246     wmap[i] = 0;
247     for (j = no; j--; )
248     if (vmap[j] >= 0 && i & 1<<j)
249     wmap[i] |= 1<<vmap[j];
250     }
251     /* fix cbeam flags */
252     for (i = ncbeams; i--; )
253     cbeam[i].wants = wmap[cbeam[i].wants];
254     /* update our voxel list */
255     bcopy((char *)vl, (char *)voxel, n*sizeof(VOXL));
256     for (j = n; j < 8; j++)
257     voxel[j].hd = -1;
258     return(comn); /* return bit array of common voxels */
259     }
260    
261    
262     int
263     get_voxels(vl, vp) /* find voxels corresponding to view point */
264     VOXL vl[8];
265     FVECT vp;
266     {
267 gregl 3.3 static int lastn = 0, lastd = -1;
268 gregl 3.1 int n = 0;
269     FVECT gp;
270     double d;
271     int dist, bestd = 0x7fff;
272     VOXL vox;
273     register int i, j, k;
274     /* find closest voxels */
275     for (i = 0; n < 8 && hdlist[i]; i++) {
276     hdgrid(gp, hdlist[i], vp);
277     for (j = 0; n < 8 && j < 8; j++) {
278     dist = 0;
279     for (k = 0; k < 3; k++) {
280     d = gp[k] - .5 + (j>>k & 1);
281     if (d < 0.)
282     dist += -(vox.i[k] = (int)d - 1);
283     else if ((vox.i[k] = d) >= hdlist[i]->grid[k])
284     dist += vox.i[k] -
285     hdlist[i]->grid[k] + 1;
286     }
287     if (dist > bestd) /* others were closer */
288     continue;
289     if (dist < bestd) { /* start closer list */
290     n = 0;
291     bestd = dist;
292     }
293     vox.hd = i; /* add this voxel */
294     copystruct(&vl[n], &vox);
295     n++;
296     }
297     }
298 gregl 3.3 /* warn of dangerous moves */
299     if (n < lastn && bestd >= lastd)
300     error(WARNING, "moving outside holodeck section");
301     else if (n > lastn && bestd <= lastd)
302     error(WARNING, "moving inside holodeck section");
303     lastd = bestd;
304     return(lastn = n);
305 gregl 3.1 }
306    
307    
308     int
309     dobeam(gcp, bp) /* express interest or disintrest in a beam */
310     GCOORD *gcp;
311     register struct beamact *bp;
312     {
313     GCOORD gc[2];
314     int bi, i;
315     /* compute beam index */
316 gregl 3.5 if (bp->ca.rev) {
317     copystruct(gc, &bp->gc);
318     copystruct(gc+1, gcp);
319     } else {
320     copystruct(gc, gcp);
321     copystruct(gc+1, &bp->gc);
322     }
323 gregl 3.1 if ((bi = hdbindex(hdlist[voxel[bp->ca.vi].hd], gc)) <= 0)
324 gregl 3.2 error(CONSISTENCY, "bad grid coordinate in dobeam");
325 gregl 3.1 if (bp->ca.add) { /* add it in */
326     i = getcbeam(voxel[bp->ca.vi].hd, bi);
327     cbeam[i].wants |= 1<<bp->ca.vi; /* say we want it */
328     return(i == ncbeams+xcbeams-1); /* return 1 if totally new */
329     }
330     /* else delete it */
331     i = findcbeam(voxel[bp->ca.vi].hd, bi);
332     if (i >= 0 && cbeam[i].wants & 1<<bp->ca.vi) {
333     cbeam[i].wants &= ~(1<<bp->ca.vi); /* we don't want it */
334     return(1); /* indicate change */
335     }
336     return(0);
337     }
338    
339    
340    
341     int
342     docell(gcp, cap) /* find beams corresponding to cell and voxel */
343     GCOORD *gcp;
344     register struct cellact *cap;
345     {
346     FVECT org, dir[4];
347     FVECT gp, cv[4], vc;
348     struct beamact bo;
349     register int i;
350     /* compute cell vertices */
351     hdcell(cv, hdlist[voxel[cap->vi].hd], gcp);
352     /* compute cell and voxel centers */
353     for (i = 0; i < 3; i++) {
354     org[i] = 0.5*(cv[0][i] + cv[2][i]);
355     gp[i] = voxel[cap->vi].i[i] + 0.5;
356     }
357     hdworld(vc, hdlist[voxel[cap->vi].hd], gp);
358     /* compute voxel pyramid using vector trick */
359     for (i = 0; i < 3; i++) {
360     dir[0][i] = vc[i] - cv[0][i]; /* to 3 */
361     dir[2][i] = vc[i] - cv[3][i]; /* to 0 */
362     if (gcp->w & 1) { /* watch vertex order! */
363     dir[1][i] = vc[i] - cv[2][i]; /* to 1 */
364     dir[3][i] = vc[i] - cv[1][i]; /* to 2 */
365     } else {
366     dir[1][i] = vc[i] - cv[1][i]; /* to 2 */
367     dir[3][i] = vc[i] - cv[2][i]; /* to 1 */
368     }
369     }
370     /* visit beams for opposite cells */
371     copystruct(&bo.ca, cap);
372     copystruct(&bo.gc, gcp);
373     return(visit_cells(org, dir, hdlist[voxel[cap->vi].hd], dobeam, &bo));
374     }
375    
376    
377     int
378     doview(cap, vp) /* visit cells for a given view */
379     struct cellact *cap;
380     VIEW *vp;
381     {
382 gregl 3.5 int orient;
383 gregl 3.1 FVECT org, dir[4];
384     /* compute view pyramid */
385 gregl 3.5 orient = viewpyramid(org, dir, hdlist[voxel[cap->vi].hd], vp);
386     if (!orient)
387     error(INTERNAL, "unusable view in doview");
388     cap->rev = orient < 0;
389 gregl 3.1 /* visit cells within pyramid */
390     return(visit_cells(org, dir, hdlist[voxel[cap->vi].hd], docell, cap));
391     }
392    
393    
394     mvview(voxi, vold, vnew) /* move view for a voxel */
395     int voxi;
396     VIEW *vold, *vnew;
397     {
398     int netchange = 0;
399 gregl 3.5 struct cellact oca, nca;
400 gregl 3.1 int ocnt, ncnt;
401     int c;
402 gregl 3.7 GCOORD *ogcl, *ngcl;
403 gregl 3.1 register GCOORD *ogcp, *ngcp;
404     /* get old and new cell lists */
405 gregl 3.7 ogcp = ogcl = getviewcells(&ocnt, hdlist[voxel[voxi].hd], vold);
406     ngcp = ngcl = getviewcells(&ncnt, hdlist[voxel[voxi].hd], vnew);
407 gregl 3.5 /* set up actions */
408     oca.vi = nca.vi = voxi;
409     oca.rev = nca.rev = 0;
410     oca.add = 0; nca.add = 1;
411     if ((oca.rev = ocnt < 0))
412     ocnt = -ocnt;
413     if ((nca.rev = ncnt < 0))
414     ncnt = -ncnt;
415 gregl 3.6 if (nca.rev == oca.rev) /* add and delete cells in order */
416     while (ocnt > 0 & ncnt > 0)
417     if ((c = cellcmp(ogcp, ngcp)) > 0) { /* new cell */
418     netchange += docell(ngcp++, &nca);
419     ncnt--;
420     } else if (c < 0) { /* old cell */
421     netchange -= docell(ogcp++, &oca);
422     ocnt--;
423     } else { /* same cell */
424     ogcp++; ocnt--;
425     ngcp++; ncnt--;
426     }
427 gregl 3.1 /* take care of list tails */
428 gregl 3.5 for ( ; ncnt > 0; ncnt--)
429     netchange += docell(ngcp++, &nca);
430     for ( ; ocnt > 0; ocnt--)
431     netchange -= docell(ogcp++, &oca);
432 gregl 3.1 /* clean up */
433 gregl 3.7 if (ogcl != NULL) free((char *)ogcl);
434     if (ngcl != NULL) free((char *)ngcl);
435 gregl 3.1 return(netchange);
436     }
437    
438    
439 gregl 3.4 beam_sync() /* synchronize beams on server */
440     {
441     cbeamop(DR_NEWSET, cbeam, ncbeams, &odev.v, odev.hres, odev.vres);
442     }
443    
444    
445 gregl 3.7 beam_view(vn) /* change beam view */
446     VIEW *vn;
447 gregl 3.1 {
448     struct cellact ca;
449     VOXL vlnew[8];
450     int n, comn;
451    
452     if (!vn->type) { /* clear our beam list */
453     set_voxels(vlnew, 0);
454 gregl 3.4 cbeamop(DR_DELSET, cbeam, ncbeams, NULL, 0, 0);
455 gregl 3.1 ncbeams = 0;
456 gregl 3.7 copystruct(&dvw, vn);
457 gregl 3.1 return;
458     }
459     /* find our new voxels */
460     n = get_voxels(vlnew, vn->vp);
461     /* set the new voxels */
462     comn = set_voxels(vlnew, n);
463 gregl 3.7 if (!dvw.type)
464 gregl 3.1 comn = 0;
465     ca.add = 1; /* update our beam list */
466     for (ca.vi = n; ca.vi--; )
467     if (comn & 1<<ca.vi) /* change which cells we see */
468 gregl 3.7 mvview(ca.vi, &dvw, vn);
469 gregl 3.1 else /* else add all new cells */
470     doview(&ca, vn);
471 gregl 3.8 #if 1
472     cbeamadj(vn, odev.hres, odev.vres);
473     #else
474 gregl 3.1 /* inform server of new beams */
475 gregl 3.4 cbeamop(DR_ADDSET, cbeam+ncbeams, xcbeams, vn, odev.hres, odev.vres);
476 gregl 3.1 /* sort list to put orphans at end */
477     cbeamsort(0);
478     /* tell server to delete orphans */
479 gregl 3.4 cbeamop(DR_DELSET, cbeam+ncbeams, xcbeams, NULL, 0, 0);
480 gregl 3.1 xcbeams = 0; /* truncate our list */
481 gregl 3.8 #endif
482 gregl 3.7 copystruct(&dvw, vn); /* record new view */
483 gregl 3.1 }