ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp2.c
Revision: 3.25
Committed: Tue Nov 24 12:01:17 1998 UTC (25 years, 5 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.24: +71 -179 lines
Log Message:
simplified beam calculation using view ray samples
took out a lot of old, hard-won code!

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