ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.19
Committed: Wed Jan 7 16:04:14 1998 UTC (26 years, 3 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.18: +32 -12 lines
Log Message:
added code to mvview() to count number of matches for better
performance when the overlap is small or empty

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 gregl 3.18 cgp[hdwg0[gcp->w]] = gcp->i[0] + .5;
326     cgp[hdwg1[gcp->w]] = gcp->i[1] + .5;
327 gregl 3.10 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.18 if (DOT(hp->wg[axmax], vc) < 0.)
354     d = -d; /* reverse vertex order */
355 gregl 3.10 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 gregl 3.19 int nmatch = 0;
396 gregl 3.7 GCOORD *ogcl, *ngcl;
397 gregl 3.19 register int c;
398 gregl 3.1 register GCOORD *ogcp, *ngcp;
399     /* get old and new cell lists */
400 gregl 3.7 ogcp = ogcl = getviewcells(&ocnt, hdlist[voxel[voxi].hd], vold);
401     ngcp = ngcl = getviewcells(&ncnt, hdlist[voxel[voxi].hd], vnew);
402 gregl 3.5 /* set up actions */
403     oca.vi = nca.vi = voxi;
404     oca.add = 0; nca.add = 1;
405     if ((oca.rev = ocnt < 0))
406     ocnt = -ocnt;
407     if ((nca.rev = ncnt < 0))
408     ncnt = -ncnt;
409 gregl 3.19 if (oca.rev == nca.rev) { /* count matches */
410     int oc = ocnt, nc = ncnt;
411     while (oc > 0 & nc > 0) {
412     c = cellcmp(ogcp, ngcp);
413     if (c >= 0) { ngcp++; nc--; }
414     if (c <= 0) { ogcp++; oc--; }
415     nmatch += c==0;
416     }
417     ogcp = ogcl; ngcp = ngcl;
418     }
419     if (nmatch < ocnt>>1) { /* faster to just delete old cells? */
420     for (c = ncbeams; c--; )
421     if (cbeam[c].wants & 1<<voxi) {
422     cbeam[c].wants &= ~(1<<voxi);
423     netchange--;
424 gregl 3.6 }
425 gregl 3.19 free((char *)ogcl);
426     ogcl = NULL; ocnt = 0;
427     }
428     /* add and delete cells in order */
429     while (ocnt > 0 & ncnt > 0)
430     if ((c = cellcmp(ogcp, ngcp)) > 0) { /* new cell */
431     netchange += docell(ngcp++, &nca);
432     ncnt--;
433     } else if (c < 0) { /* old cell */
434     netchange -= docell(ogcp++, &oca);
435     ocnt--;
436     } else { /* same cell */
437     ogcp++; ocnt--;
438     ngcp++; ncnt--;
439     }
440 gregl 3.1 /* take care of list tails */
441 gregl 3.5 for ( ; ncnt > 0; ncnt--)
442     netchange += docell(ngcp++, &nca);
443     for ( ; ocnt > 0; ocnt--)
444     netchange -= docell(ogcp++, &oca);
445 gregl 3.1 /* clean up */
446 gregl 3.7 if (ogcl != NULL) free((char *)ogcl);
447     if (ngcl != NULL) free((char *)ngcl);
448 gregl 3.1 return(netchange);
449     }
450    
451    
452 gregl 3.12 int
453 gregl 3.4 beam_sync() /* synchronize beams on server */
454     {
455     cbeamop(DR_NEWSET, cbeam, ncbeams, &odev.v, odev.hres, odev.vres);
456 gregl 3.12 return(ncbeams);
457 gregl 3.4 }
458    
459    
460 gregl 3.9 beam_view(vn) /* change beam view (if advisable) */
461 gregl 3.7 VIEW *vn;
462 gregl 3.1 {
463     struct cellact ca;
464     VOXL vlnew[8];
465     int n, comn;
466    
467 gregl 3.13 if (vn == NULL || !vn->type) { /* clear our beam list */
468 gregl 3.1 set_voxels(vlnew, 0);
469 gregl 3.4 cbeamop(DR_DELSET, cbeam, ncbeams, NULL, 0, 0);
470 gregl 3.1 ncbeams = 0;
471 gregl 3.13 dvw.type = 0;
472 gregl 3.9 return(1);
473 gregl 3.1 }
474     /* find our new voxels */
475     n = get_voxels(vlnew, vn->vp);
476 gregl 3.9 if (dvw.type && !n) {
477     copystruct(vn, &dvw); /* cancel move */
478     return(0);
479     }
480 gregl 3.1 /* set the new voxels */
481     comn = set_voxels(vlnew, n);
482 gregl 3.7 if (!dvw.type)
483 gregl 3.1 comn = 0;
484     ca.add = 1; /* update our beam list */
485     for (ca.vi = n; ca.vi--; )
486     if (comn & 1<<ca.vi) /* change which cells we see */
487 gregl 3.7 mvview(ca.vi, &dvw, vn);
488 gregl 3.1 else /* else add all new cells */
489     doview(&ca, vn);
490     /* inform server of new beams */
491 gregl 3.4 cbeamop(DR_ADDSET, cbeam+ncbeams, xcbeams, vn, odev.hres, odev.vres);
492 gregl 3.1 /* sort list to put orphans at end */
493     cbeamsort(0);
494     /* tell server to delete orphans */
495 gregl 3.4 cbeamop(DR_DELSET, cbeam+ncbeams, xcbeams, NULL, 0, 0);
496 gregl 3.1 xcbeams = 0; /* truncate our list */
497 gregl 3.7 copystruct(&dvw, vn); /* record new view */
498 gregl 3.9 return(1);
499 gregl 3.1 }