ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.7
Committed: Tue Nov 25 10:48:38 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.6: +13 -8 lines
Log Message:
bug fixes and minor improvements

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