ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp3.c
Revision: 3.4
Committed: Fri Nov 21 18:17:37 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.3: +102 -34 lines
Log Message:
added check for holodeck behind viewpoint for more robust beam selection

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 gregl 3.2 * Holodeck beam support for display process
9 gregl 3.1 */
10    
11     #include "rholo.h"
12     #include "rhdisp.h"
13     #include "view.h"
14    
15 gregl 3.4 struct cellist {
16     GCOORD *cl;
17     int n;
18     };
19 gregl 3.1
20 gregl 3.4
21 gregl 3.1 int
22     npixels(vp, hr, vr, hp, bi) /* compute appropriate number to evaluate */
23     VIEW *vp;
24     int hr, vr;
25     HOLO *hp;
26     int bi;
27     {
28 gregl 3.4 static VIEW vdo, vlast;
29     static HOLO *hplast;
30 gregl 3.1 GCOORD gc[2];
31     FVECT cp[4];
32     FVECT ip[4];
33     double d;
34     register int i;
35     /* compute cell corners in image */
36     if (!hdbcoord(gc, hp, bi))
37     error(CONSISTENCY, "bad beam index in npixels");
38 gregl 3.4 /* has holodeck or view changed? */
39     if (hp != hplast || bcmp((char *)vp, (char *)&vlast, sizeof(VIEW))) {
40     copystruct(&vdo, vp);
41     if (sect_behind(hp, &vdo)) { /* reverse view sense */
42     vdo.vdir[0] = -vdo.vdir[0];
43     vdo.vdir[1] = -vdo.vdir[1];
44     vdo.vdir[2] = -vdo.vdir[2];
45     setview(&vdo);
46     }
47     hplast = hp;
48     copystruct(&vlast, vp);
49     }
50     hdcell(cp, hp, gc+1); /* find cell on image */
51 gregl 3.1 for (i = 0; i < 4; i++) {
52 gregl 3.4 viewloc(ip[i], &vdo, cp[i]);
53 gregl 3.1 if (ip[i][2] < 0.)
54     return(0);
55     ip[i][0] *= (double)hr; /* scale by resolution */
56     ip[i][1] *= (double)vr;
57     }
58     /* compute quad area */
59     d = (ip[1][0]-ip[0][0])*(ip[2][1]-ip[0][1]) -
60     (ip[2][0]-ip[0][0])*(ip[1][1]-ip[0][1]);
61     d += (ip[2][0]-ip[3][0])*(ip[1][1]-ip[3][1]) -
62     (ip[1][0]-ip[3][0])*(ip[2][1]-ip[3][1]);
63     if (d < 0)
64     d = -d;
65     /* round off result */
66     return((int)(.5*d+.5));
67     }
68    
69    
70     /*
71     * The ray directions that define the pyramid in visit_cells() needn't
72     * be normalized, but they must be given in clockwise order as seen
73     * from the pyramid's apex (origin).
74     */
75     int
76     visit_cells(orig, pyrd, hp, vf, dp) /* visit cells within a pyramid */
77     FVECT orig, pyrd[4]; /* pyramid ray directions in clockwise order */
78     HOLO *hp;
79     int (*vf)();
80     char *dp;
81     {
82     int n = 0;
83     int inflags = 0;
84     FVECT gp, pn[4], lo, ld;
85     double po[4], lbeg, lend, d, t;
86     GCOORD gc;
87     register int i;
88     /* figure out whose side we're on */
89     hdgrid(gp, hp, orig);
90     for (i = 0; i < 3; i++) {
91     inflags |= (gp[i] > FTINY) << (i<<1);
92     inflags |= (gp[i] < hp->grid[i]-FTINY) << (i<<1 | 1);
93     }
94     /* compute pyramid planes */
95     for (i = 0; i < 4; i++) {
96     fcross(pn[i], pyrd[i], pyrd[(i+1)&03]);
97     po[i] = DOT(pn[i], orig);
98     }
99     /* traverse each wall */
100     for (gc.w = 0; gc.w < 6; gc.w++) {
101     if (!(inflags & 1<<gc.w)) /* origin on wrong side */
102     continue;
103     /* scanline algorithm */
104     for (gc.i[1] = hp->grid[((gc.w>>1)+2)%3]; gc.i[1]--; ) {
105     /* compute scanline */
106     gp[gc.w>>1] = gc.w&1 ? hp->grid[gc.w>>1] : 0;
107     gp[((gc.w>>1)+1)%3] = 0;
108     gp[((gc.w>>1)+2)%3] = gc.i[1] + 0.5;
109     hdworld(lo, hp, gp);
110     gp[((gc.w>>1)+1)%3] = 1;
111     hdworld(ld, hp, gp);
112 gregl 3.2 ld[0] -= lo[0]; ld[1] -= lo[1]; ld[2] -= lo[2];
113 gregl 3.1 /* find scanline limits */
114     lbeg = 0; lend = hp->grid[((gc.w>>1)+1)%3];
115     for (i = 0; i < 4; i++) {
116     t = DOT(pn[i], lo) - po[i];
117     d = -DOT(pn[i], ld);
118 gregl 3.2 if (d > FTINY) { /* <- plane */
119 gregl 3.1 if ((t /= d) < lend)
120     lend = t;
121 gregl 3.2 } else if (d < -FTINY) { /* plane -> */
122 gregl 3.1 if ((t /= d) > lbeg)
123     lbeg = t;
124 gregl 3.3 } else if (t < 0) { /* outside */
125     lend = -1;
126     break;
127     }
128 gregl 3.1 }
129 gregl 3.3 if (lbeg >= lend)
130     continue;
131 gregl 3.1 i = lend + .5; /* visit cells on this scan */
132     for (gc.i[0] = lbeg + .5; gc.i[0] < i; gc.i[0]++)
133     n += (*vf)(&gc, dp);
134     }
135     }
136     return(n);
137     }
138    
139    
140 gregl 3.4 sect_behind(hp, vp) /* check if section is "behind" viewpoint */
141     register HOLO *hp;
142     register VIEW *vp;
143     {
144     FVECT hcent;
145     /* compute holodeck section center */
146     VSUM(hcent, hp->orig, hp->xv[0], 0.5);
147     VSUM(hcent, hcent, hp->xv[1], 0.5);
148     VSUM(hcent, hcent, hp->xv[2], 0.5);
149     /* behind if center is behind */
150     return(DOT(vp->vdir,hcent) < DOT(vp->vdir,vp->vp));
151     }
152    
153    
154     viewpyramid(org, dir, hp, vp) /* compute view pyramid */
155     FVECT org, dir[4];
156     HOLO *hp;
157     VIEW *vp;
158     {
159     register int i;
160     /* check view type */
161     if (vp->type == VT_PAR)
162     return(0);
163     /* in front or behind? */
164     if (!sect_behind(hp, vp)) {
165     if (viewray(org, dir[0], vp, 0., 0.) < -FTINY)
166     return(0);
167     if (viewray(org, dir[1], vp, 0., 1.) < -FTINY)
168     return(0);
169     if (viewray(org, dir[2], vp, 1., 1.) < -FTINY)
170     return(0);
171     if (viewray(org, dir[3], vp, 1., 0.) < -FTINY)
172     return(0);
173     return(1);
174     } /* reverse pyramid */
175     if (viewray(org, dir[3], vp, 0., 0.) < -FTINY)
176     return(0);
177     if (viewray(org, dir[2], vp, 0., 1.) < -FTINY)
178     return(0);
179     if (viewray(org, dir[1], vp, 1., 1.) < -FTINY)
180     return(0);
181     if (viewray(org, dir[0], vp, 1., 0.) < -FTINY)
182     return(0);
183     for (i = 0; i < 3; i++) {
184     dir[0][i] = -dir[0][i];
185     dir[1][i] = -dir[1][i];
186     dir[2][i] = -dir[2][i];
187     dir[3][i] = -dir[3][i];
188     }
189     return(-1);
190     }
191    
192    
193 gregl 3.1 int
194     addcell(gcp, cl) /* add a cell to a list */
195     GCOORD *gcp;
196 gregl 3.4 register struct cellist *cl;
197 gregl 3.1 {
198 gregl 3.4 copystruct(cl->cl+cl->n, gcp);
199     cl->n++;
200 gregl 3.1 return(1);
201     }
202    
203    
204     int
205     cellcmp(gcp1, gcp2) /* visit_cells() cell ordering */
206     register GCOORD *gcp1, *gcp2;
207     {
208     register int c;
209    
210     if ((c = gcp1->w - gcp2->w))
211     return(c);
212     if ((c = gcp2->i[1] - gcp1->i[1])) /* wg1 is reverse-ordered */
213     return(c);
214     return(gcp1->i[0] - gcp2->i[0]);
215     }
216    
217    
218 gregl 3.4 GCOORD *
219     getviewcells(np, hp, vp) /* get ordered cell list for section view */
220     int *np; /* returned number of cells (negative if reversed) */
221 gregl 3.1 register HOLO *hp;
222     VIEW *vp;
223     {
224     FVECT org, dir[4];
225 gregl 3.4 int orient;
226     struct cellist cl;
227 gregl 3.1 /* compute view pyramid */
228 gregl 3.4 *np = 0;
229     orient = viewpyramid(org, dir, hp, vp);
230     if (!orient)
231     return(NULL);
232 gregl 3.1 /* allocate enough list space */
233 gregl 3.4 cl.n = 2*( hp->grid[0]*hp->grid[1] +
234     hp->grid[0]*hp->grid[2] +
235     hp->grid[1]*hp->grid[2] );
236     cl.cl = (GCOORD *)malloc(cl.n*sizeof(GCOORD));
237     if (cl.cl == NULL)
238 gregl 3.1 goto memerr;
239 gregl 3.4 cl.n = 0; /* add cells within pyramid */
240     visit_cells(org, dir, hp, addcell, &cl);
241     if (!cl.n) {
242     free((char *)cl.cl);
243 gregl 3.1 return(NULL);
244     }
245 gregl 3.4 *np = cl.n * orient;
246 gregl 3.1 #if 0
247 gregl 3.2 /* We're just going to free this memory in a moment, and list is
248     * sorted automatically by visit_cells(), so we don't need this.
249     */
250 gregl 3.4 /* optimize memory use */
251     cl.cl = (GCOORD *)realloc((char *)cl.cl, cl.n*sizeof(GCOORD));
252     if (cl.cl == NULL)
253     goto memerr;
254 gregl 3.1 /* sort the list */
255 gregl 3.4 qsort((char *)cl.cl, cl.n, sizeof(GCOORD), cellcmp);
256 gregl 3.1 #endif
257 gregl 3.4 return(cl.cl);
258 gregl 3.1 memerr:
259     error(SYSTEM, "out of memory in getviewcells");
260     }