ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.30
Committed: Tue Dec 22 15:57:20 1998 UTC (25 years, 4 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.29: +32 -23 lines
Log Message:
added jittering around viewpoint for better beam selection

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 #include "random.h"
15
16 #ifndef MAXDIST
17 #define MAXDIST 42 /* maximum distance outside section */
18 #endif
19 #ifndef NVSAMPS
20 #define NVSAMPS 16384 /* number of ray samples per view */
21 #endif
22 #ifndef MEYERNG
23 #define MEYERNG 0.2 /* target mean eye range (rel. to grid) */
24 #endif
25 #ifndef MAXTODO
26 #define MAXTODO 3 /* maximum sections to look at */
27 #endif
28 #ifndef MAXDRAT
29 #define MAXDRAT 3.0 /* maximum distance ratio btwn. cand. sect. */
30 #endif
31
32 #define CBEAMBLK 1024 /* cbeam allocation block size */
33
34 static struct beamcomp {
35 int hd; /* holodeck section number */
36 int bi; /* beam index */
37 int4 nr; /* number of samples desired */
38 } *cbeam = NULL; /* current beam list */
39
40 VIEWPOINT cureye; /* current eye position */
41
42 static int ncbeams = 0; /* number of sorted beams in cbeam */
43 static int xcbeams = 0; /* extra (unregistered) beams past ncbeams */
44 static int maxcbeam = 0; /* size of cbeam array */
45
46
47 int
48 newcbeam() /* allocate new entry at end of cbeam array */
49 {
50 int i;
51
52 if ((i = ncbeams + xcbeams++) >= maxcbeam) { /* grow array */
53 maxcbeam += CBEAMBLK;
54 if (cbeam == NULL)
55 cbeam = (struct beamcomp *)malloc(
56 maxcbeam*sizeof(struct beamcomp) );
57 else
58 cbeam = (struct beamcomp *)realloc( (char *)cbeam,
59 maxcbeam*sizeof(struct beamcomp) );
60 if (cbeam == NULL)
61 error(SYSTEM, "out of memory in newcbeam");
62 }
63 return(i);
64 }
65
66
67 int
68 cbeamcmp(cb1, cb2) /* compare two cbeam entries for sort: keep orphans */
69 register struct beamcomp *cb1, *cb2;
70 {
71 register int c;
72
73 if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
74 return(c);
75 return(cb1->hd - cb2->hd); /* use hd to resolve matches */
76 }
77
78
79 int
80 cbeamcmp2(cb1, cb2) /* compare two cbeam entries for sort: no orphans */
81 register struct beamcomp *cb1, *cb2;
82 {
83 register int c;
84
85 if (!cb1->nr) /* put orphans at the end, unsorted */
86 return(cb2->nr);
87 if (!cb2->nr)
88 return(-1);
89 if ((c = cb1->bi - cb2->bi)) /* sort on beam index first */
90 return(c);
91 return(cb1->hd - cb2->hd); /* use hd to resolve matches */
92 }
93
94
95 int
96 findcbeam(hd, bi) /* find the specified beam in our sorted list */
97 int hd, bi;
98 {
99 struct beamcomp cb;
100 register struct beamcomp *p;
101
102 if (ncbeams <= 0)
103 return(-1);
104 cb.hd = hd; cb.bi = bi; cb.nr = 0;
105 p = (struct beamcomp *)bsearch((char *)&cb, (char *)cbeam, ncbeams,
106 sizeof(struct beamcomp), cbeamcmp);
107 if (p == NULL)
108 return(-1);
109 return(p - cbeam);
110 }
111
112
113 int
114 getcbeam(hd, bi) /* get the specified beam, allocating as necessary */
115 register int hd;
116 int bi;
117 {
118 register int n;
119 /* first, look in sorted list */
120 if ((n = findcbeam(hd, bi)) >= 0)
121 return(n);
122 /* linear search through xcbeams to be sure */
123 for (n = ncbeams+xcbeams; n-- > ncbeams; )
124 if (cbeam[n].bi == bi && cbeam[n].hd == hd)
125 return(n);
126 /* check legality */
127 if (hd < 0 | hd >= HDMAX || hdlist[hd] == NULL)
128 error(INTERNAL, "illegal holodeck number in getcbeam");
129 if (bi < 1 | bi > nbeams(hdlist[hd]))
130 error(INTERNAL, "illegal beam index in getcbeam");
131 n = newcbeam(); /* allocate and assign */
132 cbeam[n].nr = 0; cbeam[n].hd = hd; cbeam[n].bi = bi;
133 return(n);
134 }
135
136
137 cbeamsort(adopt) /* sort our beam list, possibly turning out orphans */
138 int adopt;
139 {
140 register int i;
141
142 if (!(ncbeams += xcbeams))
143 return;
144 xcbeams = 0;
145 qsort((char *)cbeam, ncbeams, sizeof(struct beamcomp),
146 adopt ? cbeamcmp : cbeamcmp2);
147 if (adopt)
148 return;
149 for (i = ncbeams; i--; ) /* identify orphans */
150 if (cbeam[i].nr)
151 break;
152 xcbeams = ncbeams - ++i; /* put orphans after ncbeams */
153 ncbeams = i;
154 }
155
156
157 cbeamop(op, bl, n) /* update beams on server list */
158 int op;
159 register struct beamcomp *bl;
160 int n;
161 {
162 register PACKHEAD *pa;
163 register int i;
164
165 if (n <= 0)
166 return;
167 pa = (PACKHEAD *)malloc(n*sizeof(PACKHEAD));
168 if (pa == NULL)
169 error(SYSTEM, "out of memory in cbeamop");
170 for (i = 0; i < n; i++) {
171 pa[i].hd = bl[i].hd;
172 pa[i].bi = bl[i].bi;
173 pa[i].nr = bl[i].nr;
174 pa[i].nc = 0;
175 }
176 serv_request(op, n*sizeof(PACKHEAD), (char *)pa);
177 free((char *)pa);
178 }
179
180
181 static int
182 comptodo(tdl, vw) /* compute holodeck sections in view */
183 int tdl[MAXTODO+1];
184 VIEW *vw;
185 {
186 int n = 0;
187 FVECT gp, dv;
188 double dist2[MAXTODO+1], thisdist2;
189 register int i, j;
190 /* find closest MAXTODO sections */
191 for (i = 0; hdlist[i]; i++) {
192 hdgrid(gp, hdlist[i], vw->vp);
193 for (j = 0; j < 3; j++)
194 if (gp[j] < 0.)
195 dv[j] = -gp[j];
196 else if (gp[j] > hdlist[i]->grid[j])
197 dv[j] = gp[j] - hdlist[i]->grid[j];
198 else
199 dv[j] = 0.;
200 thisdist2 = DOT(dv,dv);
201 for (j = n; j > 0 && thisdist2 < dist2[j-1]; j--) {
202 tdl[j] = tdl[j-1];
203 dist2[j] = dist2[j-1];
204 }
205 tdl[j] = i;
206 dist2[j] = thisdist2;
207 if (n < MAXTODO)
208 n++;
209 }
210 /* watch for bad move */
211 if (n && dist2[0] > MAXDIST*MAXDIST) {
212 error(COMMAND, "move past outer limits");
213 return(0);
214 }
215 /* avoid big differences */
216 for (j = 1; j < n; j++)
217 if (dist2[j] > MAXDRAT*MAXDRAT*dist2[j-1])
218 n = j;
219 tdl[n] = -1;
220 return(n);
221 }
222
223
224 int
225 addview(hd, vw, rad, hres, vres) /* add view for section */
226 int hd;
227 VIEW *vw;
228 double rad;
229 int hres, vres;
230 {
231 int sampquant, samptot = 0;
232 int h, v, shr, svr;
233 GCOORD gc[2];
234 FVECT rorg, rdir;
235 /* compute sampling grid */
236 if (hres|vres && hres*vres <= NVSAMPS) {
237 shr = hres; svr = vres;
238 sampquant = 1;
239 } else {
240 shr = sqrt(NVSAMPS/viewaspect(vw)) + .5;
241 svr = (NVSAMPS + shr/2)/shr;
242 sampquant = (hres*vres + shr*svr/2)/(shr*svr);
243 }
244 /* intersect sample rays with section */
245 for (v = svr; v--; )
246 for (h = shr; h--; ) {
247 if (viewray(rorg, rdir, vw, (v+frandom())/svr,
248 (h+frandom())/shr) < -FTINY)
249 continue;
250 if (rad > FTINY) {
251 rorg[0] += (1.-2.*frandom())*rad;
252 rorg[1] += (1.-2.*frandom())*rad;
253 rorg[2] += (1.-2.*frandom())*rad;
254 }
255 if (hdinter(gc, NULL, NULL, hdlist[hd], rorg, rdir)
256 >= 0.99*FHUGE)
257 continue;
258 cbeam[getcbeam(hd,hdbindex(hdlist[hd],gc))].nr +=
259 sampquant;
260 samptot += sampquant;
261 }
262 return(samptot);
263 }
264
265
266 beam_init(fresh) /* clear beam list for new view(s) */
267 int fresh;
268 {
269 register int i;
270
271 if (fresh) /* discard old beams? */
272 ncbeams = xcbeams = 0;
273 else /* else clear sample requests */
274 for (i = ncbeams+xcbeams; i--; )
275 cbeam[i].nr = 0;
276 cureye.rng = 0.;
277 }
278
279
280 int *
281 beam_view(vn, hr, vr) /* add beam view (if advisable) */
282 VIEW *vn;
283 int hr, vr;
284 {
285 static int todo[MAXTODO+1];
286 int n;
287 double er, eravg, d;
288 register HOLO *hp;
289 register int i;
290 /* find nearby sections */
291 if (!(n = comptodo(todo, vn)))
292 return(NULL);
293 /* sort current beam list */
294 cbeamsort(1);
295 /* add view to nearby sections */
296 eravg = 0.;
297 for (i = 0; i < n; i++) {
298 hp = hdlist[todo[i]];
299 if (MEYERNG > FTINY)
300 er = MEYERNG/3. / VLEN(hp->wg[0]) +
301 MEYERNG/3. / VLEN(hp->wg[1]) +
302 MEYERNG/3. / VLEN(hp->wg[2]) ;
303 else
304 er = 0.;
305 if (!addview(todo[i], vn, 0.25*er, hr, vr)) {
306 register int j; /* whoops! */
307 n--; /* delete from list */
308 for (j = i--; j <= n; j++)
309 todo[j] = todo[j+1];
310 } else
311 eravg += er;
312 }
313 if (eravg <= FTINY)
314 return(todo);
315 /* compute average eye range */
316 eravg /= (double)n;
317 /* add to current eye position */
318 if (cureye.rng <= FTINY) {
319 VCOPY(cureye.vpt, vn->vp);
320 cureye.rng = eravg;
321 } else if ((d = sqrt(dist2(vn->vp,cureye.vpt))) + eravg > cureye.rng) {
322 for (i = 3; i--; )
323 cureye.vpt[i] = 0.5*(cureye.vpt[i] + vn->vp[i]);
324 cureye.rng = 0.5*(cureye.rng + eravg + d);
325 }
326 return(todo);
327 }
328
329
330 int
331 beam_sync(all) /* update beam list on server */
332 int all;
333 {
334 /* set new eye position */
335 serv_request(DR_VIEWPOINT, sizeof(VIEWPOINT), (char *)&cureye);
336 /* sort list (put orphans at end) */
337 cbeamsort(all < 0);
338 /* send beam request */
339 if (all)
340 cbeamop(DR_NEWSET, cbeam, ncbeams);
341 else
342 cbeamop(DR_ADJSET, cbeam, ncbeams+xcbeams);
343 xcbeams = 0; /* truncate our list */
344 return(ncbeams);
345 }