ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.3
Committed: Thu Nov 20 18:06:35 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.2: +8 -1 lines
Log Message:
added warning for leaving or entering holodeck sections

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