ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.9
Committed: Fri Dec 5 15:50:43 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.8: +16 -2 lines
Log Message:
added guard for inappropriate moves

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