ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.17
Committed: Thu Jan 1 13:00:16 1998 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.16: +2 -75 lines
Log Message:
increased interactive update rate with periodic display flushing

File Contents

# User Rev Content
1 gregl 3.17 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2 gregl 3.1
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 gregl 3.14 #define MAXDIST 42 /* maximum distance outside section */
17 gregl 3.9 #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 gregl 3.15 if (!cb2->wants)
98     return(-1);
99 gregl 3.1 if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
100     return(c);
101     return(cb1->hd - cb2->hd); /* use hd to resolve matches */
102     }
103    
104    
105     int
106     findcbeam(hd, bi) /* find the specified beam in our sorted list */
107     int hd, bi;
108     {
109     struct beamcomp cb;
110     register struct beamcomp *p;
111    
112     if (ncbeams <= 0)
113     return(-1);
114     cb.wants = 0; cb.hd = hd; cb.bi = bi;
115     p = (struct beamcomp *)bsearch((char *)&cb, (char *)cbeam, ncbeams,
116     sizeof(struct beamcomp), cbeamcmp);
117     if (p == NULL)
118     return(-1);
119     return(p - cbeam);
120     }
121    
122    
123     int
124     getcbeam(hd, bi) /* get the specified beam, allocating as necessary */
125     register int hd;
126     int bi;
127     {
128     register int n;
129     /* first, look in sorted list */
130     if ((n = findcbeam(hd, bi)) >= 0)
131     return(n);
132     /* linear search through xcbeams to be sure */
133     for (n = ncbeams+xcbeams; n-- > ncbeams; )
134     if (cbeam[n].bi == bi && cbeam[n].hd == hd)
135     return(n);
136     /* check legality */
137     if (hd < 0 | hd >= HDMAX || hdlist[hd] == NULL)
138     error(INTERNAL, "illegal holodeck number in getcbeam");
139     if (bi < 1 | bi > nbeams(hdlist[hd]))
140     error(INTERNAL, "illegal beam index in getcbeam");
141     n = newcbeam(); /* allocate and assign */
142     cbeam[n].wants = 0; cbeam[n].hd = hd; cbeam[n].bi = bi;
143     return(n);
144     }
145    
146    
147     cbeamsort(adopt) /* sort our beam list, possibly turning out orphans */
148     int adopt;
149     {
150     register int i;
151    
152     if (!(ncbeams += xcbeams))
153     return;
154     xcbeams = 0;
155     qsort((char *)cbeam, ncbeams, sizeof(struct beamcomp),
156     adopt ? cbeamcmp : cbeamcmp2);
157     if (adopt)
158     return;
159     for (i = ncbeams; i--; ) /* identify orphans */
160     if (cbeam[i].wants)
161     break;
162     xcbeams = ncbeams - ++i; /* put orphans after ncbeams */
163     ncbeams = i;
164     }
165    
166    
167 gregl 3.4 cbeamop(op, bl, n, v, hr, vr) /* update beams on server list */
168     int op;
169 gregl 3.1 register struct beamcomp *bl;
170     int n;
171     VIEW *v;
172     int hr, vr;
173     {
174     register PACKHEAD *pa;
175     register int i;
176    
177     if (n <= 0)
178     return;
179     pa = (PACKHEAD *)malloc(n*sizeof(PACKHEAD));
180     if (pa == NULL)
181     error(SYSTEM, "out of memory in cbeamadd");
182     for (i = 0; i < n; i++) {
183     pa[i].hd = bl[i].hd;
184     pa[i].bi = bl[i].bi;
185 gregl 3.4 pa[i].nr = v==NULL ? 0 :
186     npixels(v, hr, vr, hdlist[bl[i].hd], bl[i].bi);
187 gregl 3.16 pa[i].nc = 0;
188 gregl 3.1 }
189 gregl 3.4 serv_request(op, n*sizeof(PACKHEAD), (char *)pa);
190 gregl 3.1 free((char *)pa);
191     }
192    
193    
194     int
195     set_voxels(vl, n) /* set new voxel array */
196     VOXL vl[8];
197     int n;
198     {
199     short wmap[256];
200     int vmap[8];
201     int comn = 0;
202     int no;
203     register int i, j;
204     /* find common voxels */
205     for (j = 0; j < 8 && voxel[j].hd >= 0; j++) {
206     vmap[j] = -1;
207     for (i = n; i--; )
208     if (!bcmp((char *)(vl+i), (char *)(voxel+j),
209     sizeof(VOXL))) {
210     vmap[j] = i;
211     comn |= 1<<i;
212     break;
213     }
214     }
215     no = comn ? j : 0; /* compute flag mapping */
216     for (i = 256; i--; ) {
217     wmap[i] = 0;
218     for (j = no; j--; )
219     if (vmap[j] >= 0 && i & 1<<j)
220     wmap[i] |= 1<<vmap[j];
221     }
222     /* fix cbeam flags */
223     for (i = ncbeams; i--; )
224     cbeam[i].wants = wmap[cbeam[i].wants];
225     /* update our voxel list */
226     bcopy((char *)vl, (char *)voxel, n*sizeof(VOXL));
227     for (j = n; j < 8; j++)
228     voxel[j].hd = -1;
229     return(comn); /* return bit array of common voxels */
230     }
231    
232    
233     int
234     get_voxels(vl, vp) /* find voxels corresponding to view point */
235     VOXL vl[8];
236     FVECT vp;
237     {
238     int n = 0;
239     FVECT gp;
240     double d;
241     int dist, bestd = 0x7fff;
242     VOXL vox;
243     register int i, j, k;
244     /* find closest voxels */
245     for (i = 0; n < 8 && hdlist[i]; i++) {
246     hdgrid(gp, hdlist[i], vp);
247     for (j = 0; n < 8 && j < 8; j++) {
248     dist = 0;
249     for (k = 0; k < 3; k++) {
250     d = gp[k] - .5 + (j>>k & 1);
251     if (d < 0.)
252     dist += -(vox.i[k] = (int)d - 1);
253     else if ((vox.i[k] = d) >= hdlist[i]->grid[k])
254     dist += vox.i[k] -
255     hdlist[i]->grid[k] + 1;
256     }
257     if (dist > bestd) /* others were closer */
258     continue;
259     if (dist < bestd) { /* start closer list */
260     n = 0;
261     bestd = dist;
262     }
263     vox.hd = i; /* add this voxel */
264     copystruct(&vl[n], &vox);
265     n++;
266     }
267     }
268 gregl 3.9 /* check for really stupid move */
269     if (bestd > MAXDIST) {
270 gregl 3.10 error(COMMAND, "move past outer limits");
271 gregl 3.9 return(0);
272     }
273 gregl 3.17 return(n);
274 gregl 3.1 }
275    
276    
277     int
278     dobeam(gcp, bp) /* express interest or disintrest in a beam */
279     GCOORD *gcp;
280     register struct beamact *bp;
281     {
282     GCOORD gc[2];
283     int bi, i;
284     /* compute beam index */
285 gregl 3.5 if (bp->ca.rev) {
286     copystruct(gc, &bp->gc);
287     copystruct(gc+1, gcp);
288     } else {
289     copystruct(gc, gcp);
290     copystruct(gc+1, &bp->gc);
291     }
292 gregl 3.1 if ((bi = hdbindex(hdlist[voxel[bp->ca.vi].hd], gc)) <= 0)
293 gregl 3.2 error(CONSISTENCY, "bad grid coordinate in dobeam");
294 gregl 3.1 if (bp->ca.add) { /* add it in */
295     i = getcbeam(voxel[bp->ca.vi].hd, bi);
296     cbeam[i].wants |= 1<<bp->ca.vi; /* say we want it */
297     return(i == ncbeams+xcbeams-1); /* return 1 if totally new */
298     }
299     /* else delete it */
300     i = findcbeam(voxel[bp->ca.vi].hd, bi);
301     if (i >= 0 && cbeam[i].wants & 1<<bp->ca.vi) {
302     cbeam[i].wants &= ~(1<<bp->ca.vi); /* we don't want it */
303     return(1); /* indicate change */
304     }
305     return(0);
306     }
307    
308    
309    
310     int
311     docell(gcp, cap) /* find beams corresponding to cell and voxel */
312     GCOORD *gcp;
313     register struct cellact *cap;
314     {
315 gregl 3.10 register HOLO *hp = hdlist[voxel[cap->vi].hd];
316 gregl 3.1 FVECT org, dir[4];
317 gregl 3.10 FVECT vgp, cgp, vc;
318     FVECT v1, v2;
319 gregl 3.1 struct beamact bo;
320 gregl 3.10 int axmax, j;
321     double d, avmax;
322 gregl 3.1 register int i;
323 gregl 3.10 /* compute cell center */
324     cgp[gcp->w>>1] = gcp->w&1 ? hp->grid[gcp->w>>1] : 0 ;
325     cgp[((gcp->w>>1)+1)%3] = gcp->i[0] + .5;
326     cgp[((gcp->w>>1)+2)%3] = gcp->i[1] + .5;
327     hdworld(org, hp, cgp);
328     /* compute direction to voxel center */
329     for (i = 3; i--; )
330 gregl 3.11 vgp[i] = voxel[cap->vi].i[i] + .5;
331 gregl 3.10 hdworld(vc, hp, vgp);
332     for (i = 3; i--; )
333     vc[i] -= org[i];
334     /* compute maximum area axis */
335     axmax = -1; avmax = 0;
336     for (i = 3; i--; ) {
337     d = vgp[i] - cgp[i];
338 gregl 3.12 if (d < 0.) d = -d;
339 gregl 3.10 if (d > avmax) {
340     avmax = d;
341     axmax = i;
342 gregl 3.1 }
343     }
344 gregl 3.10 #ifdef DEBUG
345 gregl 3.12 if (axmax < 0.)
346 gregl 3.10 error(CONSISTENCY, "botched axis computation in docell");
347     #endif
348     /* compute offset vectors */
349     d = 0.5/hp->grid[j=(axmax+1)%3];
350     for (i = 3; i--; )
351     v1[i] = hp->xv[j][i] * d;
352     d = 0.5/hp->grid[j=(axmax+2)%3];
353 gregl 3.12 if (DOT(hp->wn[axmax], vc) < 0.)
354 gregl 3.10 d = -d; /* reverse vertex ordering */
355     for (i = 3; i--; )
356     v2[i] = hp->xv[j][i] * d;
357     /* compute voxel pyramid */
358     for (i = 3; i--; ) {
359     dir[0][i] = vc[i] - v1[i] - v2[i];
360     dir[1][i] = vc[i] + v1[i] - v2[i];
361     dir[2][i] = vc[i] + v1[i] + v2[i];
362     dir[3][i] = vc[i] - v1[i] + v2[i];
363     }
364 gregl 3.1 /* visit beams for opposite cells */
365     copystruct(&bo.ca, cap);
366     copystruct(&bo.gc, gcp);
367 gregl 3.10 return(visit_cells(org, dir, hp, dobeam, &bo));
368 gregl 3.1 }
369    
370    
371     int
372     doview(cap, vp) /* visit cells for a given view */
373     struct cellact *cap;
374     VIEW *vp;
375     {
376 gregl 3.5 int orient;
377 gregl 3.1 FVECT org, dir[4];
378     /* compute view pyramid */
379 gregl 3.5 orient = viewpyramid(org, dir, hdlist[voxel[cap->vi].hd], vp);
380     if (!orient)
381     error(INTERNAL, "unusable view in doview");
382     cap->rev = orient < 0;
383 gregl 3.1 /* visit cells within pyramid */
384     return(visit_cells(org, dir, hdlist[voxel[cap->vi].hd], docell, cap));
385     }
386    
387    
388     mvview(voxi, vold, vnew) /* move view for a voxel */
389     int voxi;
390     VIEW *vold, *vnew;
391     {
392     int netchange = 0;
393 gregl 3.5 struct cellact oca, nca;
394 gregl 3.1 int ocnt, ncnt;
395     int c;
396 gregl 3.7 GCOORD *ogcl, *ngcl;
397 gregl 3.1 register GCOORD *ogcp, *ngcp;
398     /* get old and new cell lists */
399 gregl 3.7 ogcp = ogcl = getviewcells(&ocnt, hdlist[voxel[voxi].hd], vold);
400     ngcp = ngcl = getviewcells(&ncnt, hdlist[voxel[voxi].hd], vnew);
401 gregl 3.5 /* set up actions */
402     oca.vi = nca.vi = voxi;
403     oca.add = 0; nca.add = 1;
404     if ((oca.rev = ocnt < 0))
405     ocnt = -ocnt;
406     if ((nca.rev = ncnt < 0))
407     ncnt = -ncnt;
408 gregl 3.6 if (nca.rev == oca.rev) /* add and delete cells in order */
409     while (ocnt > 0 & ncnt > 0)
410     if ((c = cellcmp(ogcp, ngcp)) > 0) { /* new cell */
411     netchange += docell(ngcp++, &nca);
412     ncnt--;
413     } else if (c < 0) { /* old cell */
414     netchange -= docell(ogcp++, &oca);
415     ocnt--;
416     } else { /* same cell */
417     ogcp++; ocnt--;
418     ngcp++; ncnt--;
419     }
420 gregl 3.1 /* take care of list tails */
421 gregl 3.5 for ( ; ncnt > 0; ncnt--)
422     netchange += docell(ngcp++, &nca);
423     for ( ; ocnt > 0; ocnt--)
424     netchange -= docell(ogcp++, &oca);
425 gregl 3.1 /* clean up */
426 gregl 3.7 if (ogcl != NULL) free((char *)ogcl);
427     if (ngcl != NULL) free((char *)ngcl);
428 gregl 3.1 return(netchange);
429     }
430    
431    
432 gregl 3.12 int
433 gregl 3.4 beam_sync() /* synchronize beams on server */
434     {
435     cbeamop(DR_NEWSET, cbeam, ncbeams, &odev.v, odev.hres, odev.vres);
436 gregl 3.12 return(ncbeams);
437 gregl 3.4 }
438    
439    
440 gregl 3.9 beam_view(vn) /* change beam view (if advisable) */
441 gregl 3.7 VIEW *vn;
442 gregl 3.1 {
443     struct cellact ca;
444     VOXL vlnew[8];
445     int n, comn;
446    
447 gregl 3.13 if (vn == NULL || !vn->type) { /* clear our beam list */
448 gregl 3.1 set_voxels(vlnew, 0);
449 gregl 3.4 cbeamop(DR_DELSET, cbeam, ncbeams, NULL, 0, 0);
450 gregl 3.1 ncbeams = 0;
451 gregl 3.13 dvw.type = 0;
452 gregl 3.9 return(1);
453 gregl 3.1 }
454     /* find our new voxels */
455     n = get_voxels(vlnew, vn->vp);
456 gregl 3.9 if (dvw.type && !n) {
457     copystruct(vn, &dvw); /* cancel move */
458     return(0);
459     }
460 gregl 3.1 /* set the new voxels */
461     comn = set_voxels(vlnew, n);
462 gregl 3.7 if (!dvw.type)
463 gregl 3.1 comn = 0;
464     ca.add = 1; /* update our beam list */
465     for (ca.vi = n; ca.vi--; )
466     if (comn & 1<<ca.vi) /* change which cells we see */
467 gregl 3.7 mvview(ca.vi, &dvw, vn);
468 gregl 3.1 else /* else add all new cells */
469     doview(&ca, vn);
470     /* inform server of new beams */
471 gregl 3.4 cbeamop(DR_ADDSET, cbeam+ncbeams, xcbeams, vn, odev.hres, odev.vres);
472 gregl 3.1 /* sort list to put orphans at end */
473     cbeamsort(0);
474     /* tell server to delete orphans */
475 gregl 3.4 cbeamop(DR_DELSET, cbeam+ncbeams, xcbeams, NULL, 0, 0);
476 gregl 3.1 xcbeams = 0; /* truncate our list */
477 gregl 3.7 copystruct(&dvw, vn); /* record new view */
478 gregl 3.9 return(1);
479 gregl 3.1 }