ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.21
Committed: Thu May 14 13:23:00 1998 UTC (25 years, 11 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.20: +66 -171 lines
Log Message:
added multiple device view capability

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 #define MAXVOXEL 16 /* maximum number of active voxels */
20
21 typedef struct {
22 int hd; /* holodeck section number (-1 if inactive) */
23 int i[3]; /* voxel index (may be outside section) */
24 } VOXL; /* a voxel */
25
26 static VOXL voxel[MAXVOXEL] = {{-1}}; /* current voxel list */
27
28 #define CBEAMBLK 1024 /* cbeam allocation block size */
29
30 static struct beamcomp {
31 unsigned int2 wants; /* flags telling which voxels want us */
32 unsigned int2 hd; /* holodeck section number */
33 int4 bi; /* beam index */
34 int4 nr; /* number of samples desired */
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 short rev; /* reverse ray direction? */
45 VIEW *vp; /* view for image */
46 short hr, vr; /* image resolution */
47 }; /* action for cell */
48
49 struct beamact {
50 struct cellact ca; /* cell action */
51 GCOORD gc; /* grid coordinate */
52 }; /* beam origin and action */
53
54
55 int
56 newcbeam() /* allocate new entry at end of cbeam array */
57 {
58 int i;
59
60 if ((i = ncbeams + xcbeams++) >= maxcbeam) { /* grow array */
61 maxcbeam += CBEAMBLK;
62 if (cbeam == NULL)
63 cbeam = (struct beamcomp *)malloc(
64 maxcbeam*sizeof(struct beamcomp) );
65 else
66 cbeam = (struct beamcomp *)realloc( (char *)cbeam,
67 maxcbeam*sizeof(struct beamcomp) );
68 if (cbeam == NULL)
69 error(SYSTEM, "out of memory in newcbeam");
70 }
71 return(i);
72 }
73
74
75 int
76 cbeamcmp(cb1, cb2) /* compare two cbeam entries for sort: keep orphans */
77 register struct beamcomp *cb1, *cb2;
78 {
79 register int c;
80
81 if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
82 return(c);
83 return(cb1->hd - cb2->hd); /* use hd to resolve matches */
84 }
85
86
87 int
88 cbeamcmp2(cb1, cb2) /* compare two cbeam entries for sort: no orphans */
89 register struct beamcomp *cb1, *cb2;
90 {
91 register int c;
92
93 if (!cb1->wants) /* put orphans at the end, unsorted */
94 return(cb2->wants);
95 if (!cb2->wants)
96 return(-1);
97 if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
98 return(c);
99 return(cb1->hd - cb2->hd); /* use hd to resolve matches */
100 }
101
102
103 int
104 findcbeam(hd, bi) /* find the specified beam in our sorted list */
105 int hd, bi;
106 {
107 struct beamcomp cb;
108 register struct beamcomp *p;
109
110 if (ncbeams <= 0)
111 return(-1);
112 cb.wants = 0; cb.hd = hd; cb.bi = bi; cb.nr = 0;
113 p = (struct beamcomp *)bsearch((char *)&cb, (char *)cbeam, ncbeams,
114 sizeof(struct beamcomp), cbeamcmp);
115 if (p == NULL)
116 return(-1);
117 return(p - cbeam);
118 }
119
120
121 int
122 getcbeam(hd, bi) /* get the specified beam, allocating as necessary */
123 register int hd;
124 int bi;
125 {
126 register int n;
127 /* first, look in sorted list */
128 if ((n = findcbeam(hd, bi)) >= 0)
129 return(n);
130 /* linear search through xcbeams to be sure */
131 for (n = ncbeams+xcbeams; n-- > ncbeams; )
132 if (cbeam[n].bi == bi && cbeam[n].hd == hd)
133 return(n);
134 /* check legality */
135 if (hd < 0 | hd >= HDMAX || hdlist[hd] == NULL)
136 error(INTERNAL, "illegal holodeck number in getcbeam");
137 if (bi < 1 | bi > nbeams(hdlist[hd]))
138 error(INTERNAL, "illegal beam index in getcbeam");
139 n = newcbeam(); /* allocate and assign */
140 cbeam[n].wants = cbeam[n].nr = 0; cbeam[n].hd = hd; cbeam[n].bi = bi;
141 return(n);
142 }
143
144
145 cbeamsort(adopt) /* sort our beam list, possibly turning out orphans */
146 int adopt;
147 {
148 register int i;
149
150 if (!(ncbeams += xcbeams))
151 return;
152 xcbeams = 0;
153 qsort((char *)cbeam, ncbeams, sizeof(struct beamcomp),
154 adopt ? cbeamcmp : cbeamcmp2);
155 if (adopt)
156 return;
157 for (i = ncbeams; i--; ) /* identify orphans */
158 if (cbeam[i].wants)
159 break;
160 xcbeams = ncbeams - ++i; /* put orphans after ncbeams */
161 ncbeams = i;
162 }
163
164
165 cbeamop(op, bl, n) /* update beams on server list */
166 int op;
167 register struct beamcomp *bl;
168 int n;
169 {
170 register PACKHEAD *pa;
171 register int i;
172
173 if (n <= 0)
174 return;
175 pa = (PACKHEAD *)malloc(n*sizeof(PACKHEAD));
176 if (pa == NULL)
177 error(SYSTEM, "out of memory in cbeamop");
178 for (i = 0; i < n; i++) {
179 pa[i].hd = bl[i].hd;
180 pa[i].bi = bl[i].bi;
181 pa[i].nr = bl[i].nr;
182 pa[i].nc = 0;
183 }
184 serv_request(op, n*sizeof(PACKHEAD), (char *)pa);
185 free((char *)pa);
186 }
187
188
189 add_voxels(vp) /* add voxels corresponding to view point */
190 FVECT vp;
191 {
192 int first, n, rfl = 0;
193 FVECT gp;
194 double d;
195 int dist, bestd = 0x7fff;
196 VOXL vox;
197 register int i, j, k;
198 /* count voxels in list already */
199 for (first = 0; first < MAXVOXEL && voxel[first].hd >= 0; first++)
200 ;
201 /* find closest voxels */
202 for (n = first, i = 0; n < MAXVOXEL && hdlist[i]; i++) {
203 hdgrid(gp, hdlist[i], vp);
204 for (j = 0; n < MAXVOXEL && j < 8; j++) {
205 dist = 0;
206 for (k = 0; k < 3; k++) {
207 d = gp[k] - .5 + (j>>k & 1);
208 if (d < 0.)
209 dist += -(vox.i[k] = (int)d - 1);
210 else if ((vox.i[k] = d) >= hdlist[i]->grid[k])
211 dist += vox.i[k] -
212 hdlist[i]->grid[k] + 1;
213 }
214 if (dist > bestd) /* others were closer */
215 continue;
216 if (dist < bestd) { /* start closer list */
217 n = first;
218 bestd = dist;
219 rfl = 0;
220 }
221 /* check if already in list */
222 for (k = first; k--; )
223 if (voxel[k].hd == i &&
224 voxel[k].i[0] == vox.i[0] &&
225 voxel[k].i[1] == vox.i[1] &&
226 voxel[k].i[2] == vox.i[2])
227 break;
228 if (k >= 0) {
229 rfl |= 1<<k;
230 continue;
231 }
232 vox.hd = i; /* add this voxel */
233 copystruct(&voxel[n], &vox);
234 rfl |= 1<<n++;
235 }
236 }
237 /* check for really stupid move */
238 if (bestd > MAXDIST) {
239 error(COMMAND, "move past outer limits");
240 return(0);
241 }
242 if (n < MAXVOXEL)
243 voxel[n].hd = -1;
244 return(rfl);
245 }
246
247
248 int
249 dobeam(gcp, bp) /* express interest or disintrest in a beam */
250 GCOORD *gcp;
251 register struct beamact *bp;
252 {
253 GCOORD gc[2];
254 int bi, i, n;
255 /* compute beam index */
256 if (bp->ca.rev) {
257 copystruct(gc, &bp->gc);
258 copystruct(gc+1, gcp);
259 } else {
260 copystruct(gc, gcp);
261 copystruct(gc+1, &bp->gc);
262 }
263 if ((bi = hdbindex(hdlist[voxel[bp->ca.vi].hd], gc)) <= 0)
264 error(CONSISTENCY, "bad grid coordinate in dobeam");
265 if (bp->ca.add) { /* add it in */
266 i = getcbeam(voxel[bp->ca.vi].hd, bi);
267 cbeam[i].wants |= 1<<bp->ca.vi; /* say we want it */
268 n = npixels(bp->ca.vp, bp->ca.hr, bp->ca.vr,
269 hdlist[cbeam[i].hd], cbeam[i].bi);
270 if (n > cbeam[i].nr)
271 cbeam[i].nr = n;
272 return(i == ncbeams+xcbeams-1); /* return 1 if totally new */
273 }
274 /* else delete it */
275 i = findcbeam(voxel[bp->ca.vi].hd, bi);
276 if (i >= 0 && cbeam[i].wants & 1<<bp->ca.vi) {
277 cbeam[i].wants &= ~(1<<bp->ca.vi); /* we don't want it */
278 if (!cbeam[i].wants)
279 cbeam[i].nr = 0;
280 return(1); /* indicate change */
281 }
282 return(0);
283 }
284
285
286
287 int
288 docell(gcp, cap) /* find beams corresponding to cell and voxel */
289 GCOORD *gcp;
290 register struct cellact *cap;
291 {
292 register HOLO *hp = hdlist[voxel[cap->vi].hd];
293 FVECT org, dir[4];
294 FVECT vgp, cgp, vc;
295 FVECT v1, v2;
296 struct beamact bo;
297 int axmax, j;
298 double d, avmax;
299 register int i;
300 /* compute cell center */
301 cgp[gcp->w>>1] = gcp->w&1 ? hp->grid[gcp->w>>1] : 0 ;
302 cgp[hdwg0[gcp->w]] = gcp->i[0] + .5;
303 cgp[hdwg1[gcp->w]] = gcp->i[1] + .5;
304 hdworld(org, hp, cgp);
305 /* compute direction to voxel center */
306 for (i = 3; i--; )
307 vgp[i] = voxel[cap->vi].i[i] + .5;
308 hdworld(vc, hp, vgp);
309 for (i = 3; i--; )
310 vc[i] -= org[i];
311 /* compute maximum area axis */
312 axmax = -1; avmax = 0;
313 for (i = 3; i--; ) {
314 d = vgp[i] - cgp[i];
315 if (d < 0.) d = -d;
316 if (d > avmax) {
317 avmax = d;
318 axmax = i;
319 }
320 }
321 #ifdef DEBUG
322 if (axmax < 0.)
323 error(CONSISTENCY, "botched axis computation in docell");
324 #endif
325 /* compute offset vectors */
326 d = 0.5/hp->grid[j=(axmax+1)%3];
327 for (i = 3; i--; )
328 v1[i] = hp->xv[j][i] * d;
329 d = 0.5/hp->grid[j=(axmax+2)%3];
330 if (DOT(hp->wg[axmax], vc) < 0.)
331 d = -d; /* reverse vertex order */
332 for (i = 3; i--; )
333 v2[i] = hp->xv[j][i] * d;
334 /* compute voxel pyramid */
335 for (i = 3; i--; ) {
336 dir[0][i] = vc[i] - v1[i] - v2[i];
337 dir[1][i] = vc[i] + v1[i] - v2[i];
338 dir[2][i] = vc[i] + v1[i] + v2[i];
339 dir[3][i] = vc[i] - v1[i] + v2[i];
340 }
341 /* visit beams for opposite cells */
342 copystruct(&bo.ca, cap);
343 copystruct(&bo.gc, gcp);
344 return(visit_cells(org, dir, hp, dobeam, &bo));
345 }
346
347
348 int
349 doview(cap) /* visit cells for a given view */
350 struct cellact *cap;
351 {
352 int orient;
353 FVECT org, dir[4];
354 /* compute view pyramid */
355 orient = viewpyramid(org, dir, hdlist[voxel[cap->vi].hd], cap->vp);
356 if (!orient)
357 error(INTERNAL, "unusable view in doview");
358 cap->rev = orient < 0;
359 /* visit cells within pyramid */
360 return(visit_cells(org, dir, hdlist[voxel[cap->vi].hd], docell, cap));
361 }
362
363
364 beam_init() /* clear beam list for new view(s) */
365 {
366 register int i;
367 /* clear desire flags */
368 for (i = ncbeams+xcbeams; i--; )
369 cbeam[i].wants = cbeam[i].nr = 0;
370 voxel[0].hd = -1; /* clear voxel list */
371 }
372
373
374 beam_view(vn, hr, vr) /* add beam view (if advisable) */
375 VIEW *vn;
376 int hr, vr;
377 {
378 struct cellact ca;
379 int vfl;
380 /* sort our list */
381 cbeamsort(1);
382 /* add new voxels */
383 vfl = add_voxels(vn->vp);
384 if (!vfl)
385 return(0);
386 ca.vp = vn; ca.hr = hr; ca.vr = vr;
387 ca.add = 1; /* update our beam list */
388 for (ca.vi = 0; vfl; vfl >>= 1, ca.vi++)
389 if (vfl & 1)
390 doview(&ca);
391 return(1);
392 }
393
394
395 int
396 beam_sync(all) /* update beam list on server */
397 int all;
398 {
399 /* sort list to put orphans at end */
400 cbeamsort(0);
401 if (all)
402 cbeamop(DR_NEWSET, cbeam, ncbeams);
403 else
404 cbeamop(DR_ADJSET, cbeam, ncbeams+xcbeams);
405 xcbeams = 0; /* truncate our list */
406 return(ncbeams);
407 }