ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.6
Committed: Mon Nov 24 15:17:28 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.5: +12 -15 lines
Log Message:
fixed bug in mvview()

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