ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.22
Committed: Fri May 22 15:12:36 1998 UTC (25 years, 11 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.21: +19 -31 lines
Log Message:
got rid of unnecessary "wants" field

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