ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/holo.c
Revision: 3.1
Committed: Fri Oct 31 10:23:29 1997 UTC (26 years, 6 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 * Routines for converting holodeck coordinates, etc.
9 *
10 * 10/22/97 GWLarson
11 */
12
13 #include "holo.h"
14
15 float hd_depthmap[DCINF-DCLIN];
16
17 static double logstep;
18
19
20 hdcompgrid(hp) /* compute derived grid vector and index */
21 register HOLO *hp;
22 {
23 FVECT AxB;
24 double d;
25 register FLOAT *v;
26 register int i, j;
27 /* initialize depth map */
28 if (hd_depthmap[0] < 1.) {
29 d = 1. + .5/DCLIN;
30 for (i = 0; i < DCINF-DCLIN; i++) {
31 hd_depthmap[i] = d;
32 d *= 1. + 1./DCLIN;
33 }
34 logstep = log(1. + 1./DCLIN);
35 }
36 /* compute grid coordinate vectors */
37 for (i = 0; i < 3; i++) {
38 fcross(AxB, hp->xv[(i+1)%3], v=hp->xv[(i+2)%3]);
39 VCOPY(hp->wn[i], AxB);
40 if (normalize(hp->wn[i]) == 0.)
41 error(USER, "degenerate holodeck section");
42 hp->wo[i<<1] = DOT(hp->wn[i],hp->orig);
43 hp->wo[i<<1|1] = hp->wo[i<<1] + DOT(hp->wn[i],hp->xv[i]);
44 fcross(hp->gv[i][0], v, AxB);
45 d = DOT(v,v) / DOT(hp->gv[i][0],hp->gv[i][0]) *
46 hp->grid[(i+1)%3];
47 for (j = 0; j < 3; j++)
48 hp->gv[i][0][j] *= d;
49 fcross(hp->gv[i][1], AxB, v=hp->xv[(i+1)%3]);
50 d = DOT(v,v) / DOT(hp->gv[i][1],hp->gv[i][1]) *
51 hp->grid[(i+2)%3];
52 for (j = 0; j < 3; j++)
53 hp->gv[i][1][j] *= d;
54 }
55 /* compute linear depth range */
56 hp->tlin = VLEN(hp->xv[0]) + VLEN(hp->xv[1]) + VLEN(hp->xv[2]);
57 /* compute wall super-indices from grid */
58 hp->wi[0] = 1; /**** index values begin at 1 ****/
59 for (i = 1; i < 6; i++) {
60 hp->wi[i] = 0;
61 for (j = i; j < 6; j++)
62 hp->wi[i] += hp->grid[((j>>1)+1)%3] *
63 hp->grid[((j>>1)+2)%3];
64 hp->wi[i] *= hp->grid[(((i-1)>>1)+1)%3] *
65 hp->grid[(((i-1)>>1)+2)%3];
66 hp->wi[i] += hp->wi[i-1];
67 }
68 }
69
70
71 HOLO *
72 hdalloc(hproto) /* allocate and set holodeck section based on grid */
73 HDGRID *hproto;
74 {
75 HOLO hdhead;
76 register HOLO *hp;
77 int n;
78 /* copy grid to temporary header */
79 bcopy((char *)hproto, (char *)&hdhead, sizeof(HDGRID));
80 /* compute grid vectors and sizes */
81 hdcompgrid(&hdhead);
82 /* allocate header with directory */
83 n = sizeof(HOLO)+nbeams(&hdhead)*sizeof(BEAMI);
84 if ((hp = (HOLO *)malloc(n)) == NULL)
85 return(NULL);
86 /* copy header information */
87 copystruct(hp, &hdhead);
88 /* allocate and clear beam list */
89 hp->bl = (BEAM **)malloc((nbeams(hp)+1)*sizeof(BEAM *)+sizeof(BEAM));
90 if (hp->bl == NULL) {
91 free((char *)hp);
92 return(NULL);
93 }
94 bzero((char *)hp->bl, (nbeams(hp)+1)*sizeof(BEAM *)+sizeof(BEAM));
95 hp->bl[0] = (BEAM *)(hp->bl+nbeams(hp)+1); /* set blglob(hp) */
96 hp->fd = -1;
97 hp->dirty = 0;
98 hp->priv = NULL;
99 /* clear beam directory */
100 bzero((char *)hp->bi, (nbeams(hp)+1)*sizeof(BEAMI));
101 return(hp); /* all is well */
102 }
103
104
105 hdbcoord(gc, hp, i) /* compute beam coordinates from index */
106 BCOORD gc; /* returned */
107 register HOLO *hp;
108 register int i;
109 {
110 register int j, n;
111 int n2, reverse;
112 BCOORD g2;
113 /* check range */
114 if (i < 1 | i > nbeams(hp))
115 return(0);
116 if (reverse = i >= hp->wi[5])
117 i -= hp->wi[5] - 1;
118 for (j = 0; j < 5; j++) /* find w0 */
119 if (hp->wi[j+1] > i)
120 break;
121 i -= hp->wi[gc[0].w=j];
122 /* find w1 */
123 n2 = hp->grid[((j>>1)+1)%3] * hp->grid[((j>>1)+2)%3];
124 while (++j < 5) {
125 n = n2 * hp->grid[((j>>1)+1)%3] * hp->grid[((j>>1)+2)%3];
126 if (n > i)
127 break;
128 i -= n;
129 }
130 gc[1].w = j;
131 /* find position on w0 */
132 n2 = hp->grid[((j>>1)+1)%3] * hp->grid[((j>>1)+2)%3];
133 n = i / n2;
134 gc[0].i[1] = n / hp->grid[((gc[0].w>>1)+1)%3];
135 gc[0].i[0] = n - gc[0].i[1]*hp->grid[((gc[0].w>>1)+1)%3];
136 i -= n*n2;
137 /* find position on w1 */
138 gc[1].i[1] = i / hp->grid[((gc[1].w>>1)+1)%3];
139 gc[1].i[0] = i - gc[1].i[1]*hp->grid[((gc[1].w>>1)+1)%3];
140 if (reverse) {
141 copystruct(g2, gc+1);
142 copystruct(gc+1, gc);
143 copystruct(gc, g2);
144 }
145 return(1); /* we're done */
146 }
147
148
149 int
150 hdbindex(hp, gc) /* compute index from beam coordinates */
151 register HOLO *hp;
152 register BCOORD gc;
153 {
154 BCOORD g2;
155 int reverse;
156 register int i, j;
157 /* check ordering and limits */
158 if (reverse = gc[0].w > gc[1].w) {
159 copystruct(g2, gc+1);
160 copystruct(g2+1, gc);
161 gc = g2;
162 } else if (gc[0].w == gc[1].w)
163 return(0);
164 if (gc[0].w < 0 | gc[1].w > 5)
165 return(0);
166 i = 0; /* compute index */
167 for (j = gc[0].w+1; j < gc[1].w; j++)
168 i += hp->grid[((j>>1)+1)%3] * hp->grid[((j>>1)+2)%3];
169 i *= hp->grid[((gc[0].w>>1)+1)%3] * hp->grid[((gc[0].w>>1)+2)%3];
170 i += hp->wi[gc[0].w];
171 i += (hp->grid[((gc[0].w>>1)+1)%3]*gc[0].i[1] + gc[0].i[0]) *
172 hp->grid[((gc[1].w>>1)+1)%3] *
173 hp->grid[((gc[1].w>>1)+2)%3] ;
174 i += hp->grid[((gc[1].w>>1)+1)%3]*gc[1].i[1] + gc[1].i[0];
175 if (reverse)
176 i += hp->wi[5] - 1;
177 return(i);
178 }
179
180
181 hdlseg(lseg, hp, i) /* compute line segment for beam */
182 int lseg[2][3];
183 register HOLO *hp;
184 int i;
185 {
186 BCOORD gc;
187 register int k;
188
189 if (!hdbcoord(gc, hp, i))
190 return(0);
191 for (k = 0; k < 2; k++) /* compute line segment */
192 switch (gc[k].w>>1) {
193 case 0:
194 lseg[k][0] = (gc[k].w & 1) * (hp->grid[0]-1);
195 lseg[k][1] = gc[k].i[0];
196 lseg[k][2] = gc[k].i[1];
197 break;
198 case 1:
199 lseg[k][0] = gc[k].i[1];
200 lseg[k][1] = (gc[k].w & 1) * (hp->grid[1]-1);
201 lseg[k][2] = gc[k].i[0];
202 break;
203 case 2:
204 lseg[k][0] = gc[k].i[0];
205 lseg[k][1] = gc[k].i[1];
206 lseg[k][2] = (gc[k].w & 1) * (hp->grid[2]-1);
207 break;
208 }
209 return(1);
210 }
211
212
213 unsigned
214 hdcode(hp, d) /* compute depth code for d */
215 HOLO *hp;
216 double d;
217 {
218 double tl = hp->tlin;
219 register unsigned c;
220
221 if (d <= 0.)
222 return(0);
223 if (d >= .99*FHUGE)
224 return(DCINF);
225 if (d < tl)
226 return((unsigned)(d*DCLIN/tl));
227 c = (unsigned)(log(d/tl)/logstep) + DCLIN;
228 return(c > DCINF ? DCINF : c);
229 }
230
231
232 double
233 hdray(ro, rd, hp, gc, r) /* compute ray within a beam */
234 FVECT ro, rd; /* returned */
235 register HOLO *hp;
236 register BCOORD gc;
237 BYTE r[2][2];
238 {
239 FVECT p[2];
240 register int i;
241 register FLOAT *v;
242 double d;
243 /* compute entry and exit points */
244 for (i = 0; i < 2; i++) {
245 VCOPY(p[i], hp->orig);
246 if (gc[i].w & 1) {
247 v = hp->xv[gc[i].w>>1];
248 p[i][0] += *v++; p[i][1] += *v++; p[i][2] += *v;
249 }
250 d = ( gc[i].i[0] + (1./256.)*(r[i][0]+.5) ) /
251 hp->grid[((gc[i].w>>1)+1)%3];
252 v = hp->xv[((gc[i].w>>1)+1)%3];
253 p[i][0] += d * *v++; p[i][1] += d * *v++; p[i][2] += d * *v;
254 d = (gc[i].i[1] + (1./256.)*(r[i][1]+.5)) /
255 hp->grid[((gc[i].w>>1)+2)%3];
256 v = hp->xv[((gc[i].w>>1)+2)%3];
257 p[i][0] += d * *v++; p[i][1] += d * *v++; p[i][2] += d * *v;
258 }
259 VCOPY(ro, p[0]); /* assign ray origin and direction */
260 rd[0] = p[1][0] - p[0][0];
261 rd[1] = p[1][1] - p[0][1];
262 rd[2] = p[1][2] - p[0][2];
263 return(normalize(rd)); /* return maximum inside distance */
264 }
265
266
267 double
268 hdinter(gc, r, hp, ro, rd) /* compute ray intersection with section */
269 register BCOORD gc; /* returned */
270 BYTE r[2][2]; /* returned */
271 register HOLO *hp;
272 FVECT ro, rd; /* rd should be normalized */
273 {
274 FVECT p[2], vt;
275 double d, t0, t1, d0, d1;
276 register FLOAT *v;
277 register int i;
278 /* first, intersect walls */
279 gc[0].w = gc[1].w = -1;
280 t0 = -FHUGE; t1 = FHUGE;
281 for (i = 0; i < 3; i++) { /* for each wall pair */
282 d = -DOT(rd, hp->wn[i]); /* plane distance */
283 if (d <= FTINY && d >= -FTINY) /* check for parallel */
284 continue;
285 d1 = DOT(ro, hp->wn[i]); /* ray distances */
286 d0 = (d1 - hp->wo[i<<1]) / d;
287 d1 = (d1 - hp->wo[i<<1|1]) / d;
288 if (d0 < d1) { /* check against best */
289 if (d0 > t0) {
290 t0 = d0;
291 gc[0].w = i<<1;
292 }
293 if (d1 < t1) {
294 t1 = d1;
295 gc[1].w = i<<1 | 1;
296 }
297 } else {
298 if (d1 > t0) {
299 t0 = d1;
300 gc[0].w = i<<1 | 1;
301 }
302 if (d0 < t1) {
303 t1 = d0;
304 gc[1].w = i<<1;
305 }
306 }
307 }
308 if (gc[0].w < 0 | gc[1].w < 0) /* paranoid check */
309 return(FHUGE);
310 /* compute intersections */
311 for (i = 0; i < 3; i++) {
312 p[0][i] = ro[i] + rd[i]*t0;
313 p[1][i] = ro[i] + rd[i]*t1;
314 }
315 /* now, compute grid coordinates */
316 for (i = 0; i < 2; i++) {
317 vt[0] = p[i][0] - hp->orig[0];
318 vt[1] = p[i][1] - hp->orig[1];
319 vt[2] = p[i][2] - hp->orig[2];
320 if (gc[i].w & 1) {
321 v = hp->xv[gc[i].w>>1];
322 vt[0] -= *v++; vt[1] -= *v++; vt[2] -= *v;
323 }
324 v = hp->gv[gc[i].w>>1][0];
325 d = DOT(vt, v);
326 if (d < 0. || (gc[i].i[0] = d) >= hp->grid[((gc[i].w>>1)+1)%3])
327 return(FHUGE); /* outside wall */
328 r[i][0] = 256. * (d - gc[i].i[0]);
329 v = hp->gv[gc[i].w>>1][1];
330 d = DOT(vt, v);
331 if (d < 0. || (gc[i].i[1] = d) >= hp->grid[((gc[i].w>>1)+2)%3])
332 return(FHUGE); /* outside wall */
333 r[i][1] = 256. * (d - gc[i].i[1]);
334 }
335 /* return distance from entry point */
336 vt[0] = ro[0] - p[0][0];
337 vt[1] = ro[1] - p[0][1];
338 vt[2] = ro[2] - p[0][2];
339 return(DOT(vt,rd));
340 }