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, 5 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

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Holodeck beam support for display process
9 */
10
11 #include "rholo.h"
12 #include "rhdisp.h"
13 #include "view.h"
14
15 struct cellist {
16 GCOORD *cl;
17 int n;
18 };
19
20
21 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 static VIEW vdo, vlast;
29 static HOLO *hplast;
30 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 /* 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 for (i = 0; i < 4; i++) {
52 viewloc(ip[i], &vdo, cp[i]);
53 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 ld[0] -= lo[0]; ld[1] -= lo[1]; ld[2] -= lo[2];
113 /* 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 if (d > FTINY) { /* <- plane */
119 if ((t /= d) < lend)
120 lend = t;
121 } else if (d < -FTINY) { /* plane -> */
122 if ((t /= d) > lbeg)
123 lbeg = t;
124 } else if (t < 0) { /* outside */
125 lend = -1;
126 break;
127 }
128 }
129 if (lbeg >= lend)
130 continue;
131 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 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 int
194 addcell(gcp, cl) /* add a cell to a list */
195 GCOORD *gcp;
196 register struct cellist *cl;
197 {
198 copystruct(cl->cl+cl->n, gcp);
199 cl->n++;
200 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 GCOORD *
219 getviewcells(np, hp, vp) /* get ordered cell list for section view */
220 int *np; /* returned number of cells (negative if reversed) */
221 register HOLO *hp;
222 VIEW *vp;
223 {
224 FVECT org, dir[4];
225 int orient;
226 struct cellist cl;
227 /* compute view pyramid */
228 *np = 0;
229 orient = viewpyramid(org, dir, hp, vp);
230 if (!orient)
231 return(NULL);
232 /* allocate enough list space */
233 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 goto memerr;
239 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 return(NULL);
244 }
245 *np = cl.n * orient;
246 #if 0
247 /* 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 /* optimize memory use */
251 cl.cl = (GCOORD *)realloc((char *)cl.cl, cl.n*sizeof(GCOORD));
252 if (cl.cl == NULL)
253 goto memerr;
254 /* sort the list */
255 qsort((char *)cl.cl, cl.n, sizeof(GCOORD), cellcmp);
256 #endif
257 return(cl.cl);
258 memerr:
259 error(SYSTEM, "out of memory in getviewcells");
260 }