ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.1
Committed: Wed Nov 19 18:01:03 1997 UTC (26 years, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

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