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, 5 months ago) by gregl
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 gregl 3.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     }