ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.1
Committed: Wed Nov 19 18:01:03 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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