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

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Holodeck beam tracking for display process
9 */
10
11 #include "rholo.h"
12 #include "rhdisp.h"
13 #include "rhdriver.h"
14
15 #ifndef MAXDIST
16 #define MAXDIST 42 /* maximum distance outside section */
17 #endif
18
19 extern GCOORD *getviewcells();
20
21 static VIEW dvw; /* current view corresponding to beam list */
22
23 typedef struct {
24 int hd; /* holodeck section number (-1 if inactive) */
25 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 short rev; /* reverse ray direction? */
49 }; /* 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 (!cb2->wants)
98 return(-1);
99 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 cbeamop(op, bl, n, v, hr, vr) /* update beams on server list */
168 int op;
169 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 pa[i].nr = v==NULL ? 0 :
186 npixels(v, hr, vr, hdlist[bl[i].hd], bl[i].bi);
187 pa[i].nc = 0;
188 }
189 serv_request(op, n*sizeof(PACKHEAD), (char *)pa);
190 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 /* check for really stupid move */
269 if (bestd > MAXDIST) {
270 error(COMMAND, "move past outer limits");
271 return(0);
272 }
273 return(n);
274 }
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 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 if ((bi = hdbindex(hdlist[voxel[bp->ca.vi].hd], gc)) <= 0)
293 error(CONSISTENCY, "bad grid coordinate in dobeam");
294 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 register HOLO *hp = hdlist[voxel[cap->vi].hd];
316 FVECT org, dir[4];
317 FVECT vgp, cgp, vc;
318 FVECT v1, v2;
319 struct beamact bo;
320 int axmax, j;
321 double d, avmax;
322 register int i;
323 /* 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 vgp[i] = voxel[cap->vi].i[i] + .5;
331 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 if (d < 0.) d = -d;
339 if (d > avmax) {
340 avmax = d;
341 axmax = i;
342 }
343 }
344 #ifdef DEBUG
345 if (axmax < 0.)
346 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 if (DOT(hp->wn[axmax], vc) < 0.)
354 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 /* visit beams for opposite cells */
365 copystruct(&bo.ca, cap);
366 copystruct(&bo.gc, gcp);
367 return(visit_cells(org, dir, hp, dobeam, &bo));
368 }
369
370
371 int
372 doview(cap, vp) /* visit cells for a given view */
373 struct cellact *cap;
374 VIEW *vp;
375 {
376 int orient;
377 FVECT org, dir[4];
378 /* compute view pyramid */
379 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 /* 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 struct cellact oca, nca;
394 int ocnt, ncnt;
395 int c;
396 GCOORD *ogcl, *ngcl;
397 register GCOORD *ogcp, *ngcp;
398 /* get old and new cell lists */
399 ogcp = ogcl = getviewcells(&ocnt, hdlist[voxel[voxi].hd], vold);
400 ngcp = ngcl = getviewcells(&ncnt, hdlist[voxel[voxi].hd], vnew);
401 /* 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 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 /* take care of list tails */
421 for ( ; ncnt > 0; ncnt--)
422 netchange += docell(ngcp++, &nca);
423 for ( ; ocnt > 0; ocnt--)
424 netchange -= docell(ogcp++, &oca);
425 /* clean up */
426 if (ogcl != NULL) free((char *)ogcl);
427 if (ngcl != NULL) free((char *)ngcl);
428 return(netchange);
429 }
430
431
432 int
433 beam_sync() /* synchronize beams on server */
434 {
435 cbeamop(DR_NEWSET, cbeam, ncbeams, &odev.v, odev.hres, odev.vres);
436 return(ncbeams);
437 }
438
439
440 beam_view(vn) /* change beam view (if advisable) */
441 VIEW *vn;
442 {
443 struct cellact ca;
444 VOXL vlnew[8];
445 int n, comn;
446
447 if (vn == NULL || !vn->type) { /* clear our beam list */
448 set_voxels(vlnew, 0);
449 cbeamop(DR_DELSET, cbeam, ncbeams, NULL, 0, 0);
450 ncbeams = 0;
451 dvw.type = 0;
452 return(1);
453 }
454 /* find our new voxels */
455 n = get_voxels(vlnew, vn->vp);
456 if (dvw.type && !n) {
457 copystruct(vn, &dvw); /* cancel move */
458 return(0);
459 }
460 /* set the new voxels */
461 comn = set_voxels(vlnew, n);
462 if (!dvw.type)
463 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 mvview(ca.vi, &dvw, vn);
468 else /* else add all new cells */
469 doview(&ca, vn);
470 /* inform server of new beams */
471 cbeamop(DR_ADDSET, cbeam+ncbeams, xcbeams, vn, odev.hres, odev.vres);
472 /* sort list to put orphans at end */
473 cbeamsort(0);
474 /* tell server to delete orphans */
475 cbeamop(DR_DELSET, cbeam+ncbeams, xcbeams, NULL, 0, 0);
476 xcbeams = 0; /* truncate our list */
477 copystruct(&dvw, vn); /* record new view */
478 return(1);
479 }