ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp3.c
(Generate patch)

Comparing ray/src/hd/rhdisp3.c (file contents):
Revision 3.2 by gregl, Thu Nov 20 14:21:41 1997 UTC vs.
Revision 3.8 by gregl, Fri Dec 19 11:54:16 1997 UTC

# Line 12 | Line 12 | static char SCCSid[] = "$SunId$ SGI";
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;
23 > register VIEW   *vp;
24   int     hr, vr;
25   HOLO    *hp;
26   int     bi;
27   {
28 +        VIEW    vrev;
29          GCOORD  gc[2];
30 <        FVECT   cp[4];
31 <        FVECT   ip[4];
26 <        double  d;
30 >        FVECT   cp[4], ip[4];
31 >        double  af, ab;
32          register int    i;
33                                          /* compute cell corners in image */
34          if (!hdbcoord(gc, hp, bi))
35                  error(CONSISTENCY, "bad beam index in npixels");
36 <        hdcell(cp, hp, gc+1);
36 >        hdcell(cp, hp, gc+1);           /* find cell on front image */
37          for (i = 0; i < 4; i++) {
38                  viewloc(ip[i], vp, cp[i]);
39 +                if (ip[i][2] < 0.) {
40 +                        af = 0;
41 +                        goto getback;
42 +                }
43 +                ip[i][0] *= (double)hr; /* scale by resolution */
44 +                ip[i][1] *= (double)vr;
45 +        }
46 +                                        /* compute front area */
47 +        af = (ip[1][0]-ip[0][0])*(ip[2][1]-ip[0][1]) -
48 +                (ip[2][0]-ip[0][0])*(ip[1][1]-ip[0][1]);
49 +        af += (ip[2][0]-ip[3][0])*(ip[1][1]-ip[3][1]) -
50 +                (ip[1][0]-ip[3][0])*(ip[2][1]-ip[3][1]);
51 +        if (af >= 0) af *= 0.5;
52 +        else af *= -0.5;
53 + getback:
54 +        copystruct(&vrev, vp);          /* compute reverse view */
55 +        for (i = 0; i < 3; i++) {
56 +                vrev.vdir[i] = -vp->vdir[i];
57 +                vrev.vup[i] = -vp->vup[i];
58 +                vrev.hvec[i] = -vp->hvec[i];
59 +                vrev.vvec[i] = -vp->vvec[i];
60 +        }
61 +        hdcell(cp, hp, gc);             /* find cell on back image */
62 +        for (i = 0; i < 4; i++) {
63 +                viewloc(ip[i], &vrev, cp[i]);
64                  if (ip[i][2] < 0.)
65 <                        return(0);
65 >                        return((int)(af + 0.5));
66                  ip[i][0] *= (double)hr; /* scale by resolution */
67                  ip[i][1] *= (double)vr;
68          }
69 <                                        /* compute quad area */
70 <        d = (ip[1][0]-ip[0][0])*(ip[2][1]-ip[0][1]) -
69 >                                        /* compute back area */
70 >        ab = (ip[1][0]-ip[0][0])*(ip[2][1]-ip[0][1]) -
71                  (ip[2][0]-ip[0][0])*(ip[1][1]-ip[0][1]);
72 <        d += (ip[2][0]-ip[3][0])*(ip[1][1]-ip[3][1]) -
72 >        ab += (ip[2][0]-ip[3][0])*(ip[1][1]-ip[3][1]) -
73                  (ip[1][0]-ip[3][0])*(ip[2][1]-ip[3][1]);
74 <        if (d < 0)
75 <                d = -d;
76 <                                        /* round off result */
77 <        return((int)(.5*d+.5));
74 >        if (ab >= 0) ab *= 0.5;
75 >        else ab *= -0.5;
76 >                                        /* round off smaller area */
77 >        if (af <= ab)
78 >                return((int)(af + 0.5));
79 >        return((int)(ab + 0.5));
80   }
81  
82  
# Line 52 | Line 84 | int    bi;
84   * The ray directions that define the pyramid in visit_cells() needn't
85   * be normalized, but they must be given in clockwise order as seen
86   * from the pyramid's apex (origin).
87 + * If no cell centers fall within the domain, the closest cell is visited.
88   */
89   int
90   visit_cells(orig, pyrd, hp, vf, dp)     /* visit cells within a pyramid */
91   FVECT   orig, pyrd[4];          /* pyramid ray directions in clockwise order */
92 < HOLO    *hp;
92 > register HOLO   *hp;
93   int     (*vf)();
94   char    *dp;
95   {
96 <        int     n = 0;
96 >        int     ncalls = 0, n = 0;
97          int     inflags = 0;
98          FVECT   gp, pn[4], lo, ld;
99          double  po[4], lbeg, lend, d, t;
100 <        GCOORD  gc;
100 >        GCOORD  gc, gc2[2];
101          register int    i;
102                                          /* figure out whose side we're on */
103          hdgrid(gp, hp, orig);
# Line 102 | Line 135 | char   *dp;
135                                  } else if (d < -FTINY) {        /* plane -> */
136                                          if ((t /= d) > lbeg)
137                                                  lbeg = t;
138 <                                } else if (t < 0)               /* outside */
139 <                                        goto nextscan;
138 >                                } else if (t < 0) {             /* outside */
139 >                                        lend = -1;
140 >                                        break;
141 >                                }
142                          }
143 +                        if (lbeg >= lend)
144 +                                continue;
145                          i = lend + .5;          /* visit cells on this scan */
146 <                        for (gc.i[0] = lbeg + .5; gc.i[0] < i; gc.i[0]++)
146 >                        for (gc.i[0] = lbeg + .5; gc.i[0] < i; gc.i[0]++) {
147                                  n += (*vf)(&gc, dp);
148 <                nextscan:;
148 >                                ncalls++;
149 >                        }
150                  }
151          }
152 <        return(n);
152 >        if (ncalls)                     /* got one at least */
153 >                return(n);
154 >                                        /* else find closest cell */
155 >        VSUM(ld, pyrd[0], pyrd[1], 1.);
156 >        VSUM(ld, ld, pyrd[2], 1.);
157 >        VSUM(ld, ld, pyrd[3], 1.);
158 > #if 0
159 >        if (normalize(ld) == 0.0)       /* technically not necessary */
160 >                return(0);
161 > #endif
162 >        d = hdinter(gc2, NULL, &t, hp, orig, ld);
163 >        if (d >= FHUGE || t <= 0.)
164 >                return(0);
165 >        return((*vf)(gc2+1, dp));       /* visit it */
166   }
167  
168  
169 + sect_behind(hp, vp)             /* check if section is "behind" viewpoint */
170 + register HOLO   *hp;
171 + register VIEW   *vp;
172 + {
173 +        FVECT   hcent;
174 +                                        /* compute holodeck section center */
175 +        VSUM(hcent, hp->orig, hp->xv[0], 0.5);
176 +        VSUM(hcent, hcent, hp->xv[1], 0.5);
177 +        VSUM(hcent, hcent, hp->xv[2], 0.5);
178 +                                        /* behind if center is behind */
179 +        return(DOT(vp->vdir,hcent) < DOT(vp->vdir,vp->vp));
180 + }
181 +
182 +
183 + viewpyramid(org, dir, hp, vp)   /* compute view pyramid */
184 + FVECT   org, dir[4];
185 + HOLO    *hp;
186 + VIEW    *vp;
187 + {
188 +        register int    i;
189 +                                        /* check view type */
190 +        if (vp->type == VT_PAR)
191 +                return(0);
192 +                                        /* in front or behind? */
193 +        if (!sect_behind(hp, vp)) {
194 +                if (viewray(org, dir[0], vp, 0., 0.) < -FTINY)
195 +                        return(0);
196 +                if (viewray(org, dir[1], vp, 0., 1.) < -FTINY)
197 +                        return(0);
198 +                if (viewray(org, dir[2], vp, 1., 1.) < -FTINY)
199 +                        return(0);
200 +                if (viewray(org, dir[3], vp, 1., 0.) < -FTINY)
201 +                        return(0);
202 +                return(1);
203 +        }                               /* reverse pyramid */
204 +        if (viewray(org, dir[3], vp, 0., 0.) < -FTINY)
205 +                return(0);
206 +        if (viewray(org, dir[2], vp, 0., 1.) < -FTINY)
207 +                return(0);
208 +        if (viewray(org, dir[1], vp, 1., 1.) < -FTINY)
209 +                return(0);
210 +        if (viewray(org, dir[0], vp, 1., 0.) < -FTINY)
211 +                return(0);
212 +        for (i = 0; i < 3; i++) {
213 +                dir[0][i] = -dir[0][i];
214 +                dir[1][i] = -dir[1][i];
215 +                dir[2][i] = -dir[2][i];
216 +                dir[3][i] = -dir[3][i];
217 +        }
218 +        return(-1);
219 + }
220 +
221 +
222   int
223   addcell(gcp, cl)                /* add a cell to a list */
224   GCOORD  *gcp;
225 < register int    *cl;
225 > register struct cellist *cl;
226   {
227 <        copystruct((GCOORD *)(cl+1) + *cl, gcp);
228 <        (*cl)++;
227 >        copystruct(cl->cl+cl->n, gcp);
228 >        cl->n++;
229          return(1);
230   }
231  
# Line 140 | Line 244 | register GCOORD        *gcp1, *gcp2;
244   }
245  
246  
247 < int *
248 < getviewcells(hp, vp)            /* get ordered cell list for section view */
247 > GCOORD *
248 > getviewcells(np, hp, vp)        /* get ordered cell list for section view */
249 > int     *np;            /* returned number of cells (negative if reversed) */
250   register HOLO   *hp;
251   VIEW    *vp;
252   {
253          FVECT   org, dir[4];
254 <        int     n;
255 <        register int    *cl;
254 >        int     orient;
255 >        struct cellist  cl;
256                                          /* compute view pyramid */
257 <        if (vp->type == VT_PAR) goto viewerr;
258 <        if (viewray(org, dir[0], vp, 0., 0.) < -FTINY) goto viewerr;
259 <        if (viewray(org, dir[1], vp, 0., 1.) < -FTINY) goto viewerr;
260 <        if (viewray(org, dir[2], vp, 1., 1.) < -FTINY) goto viewerr;
156 <        if (viewray(org, dir[3], vp, 1., 0.) < -FTINY) goto viewerr;
257 >        *np = 0;
258 >        orient = viewpyramid(org, dir, hp, vp);
259 >        if (!orient)
260 >                return(NULL);
261                                          /* allocate enough list space */
262 <        n = 2*( hp->grid[0]*hp->grid[1] +
263 <                hp->grid[0]*hp->grid[2] +
264 <                hp->grid[1]*hp->grid[2] );
265 <        cl = (int *)malloc(sizeof(int) + n*sizeof(GCOORD));
266 <        if (cl == NULL)
262 >        cl.n = 2*(      hp->grid[0]*hp->grid[1] +
263 >                        hp->grid[0]*hp->grid[2] +
264 >                        hp->grid[1]*hp->grid[2] );
265 >        cl.cl = (GCOORD *)malloc(cl.n*sizeof(GCOORD));
266 >        if (cl.cl == NULL)
267                  goto memerr;
268 <        *cl = 0;
269 <                                        /* add cells within pyramid */
270 <        visit_cells(org, dir, hp, addcell, cl);
271 <        if (!*cl) {
168 <                free((char *)cl);
268 >        cl.n = 0;                       /* add cells within pyramid */
269 >        visit_cells(org, dir, hp, addcell, &cl);
270 >        if (!cl.n) {
271 >                free((char *)cl.cl);
272                  return(NULL);
273          }
274 +        *np = cl.n * orient;
275   #if 0
276          /* We're just going to free this memory in a moment, and list is
277           * sorted automatically by visit_cells(), so we don't need this.
278           */
279 <        if (*cl < n) {                  /* optimize memory use */
280 <                cl = (int *)realloc((char *)cl,
281 <                                sizeof(int) + *cl*sizeof(GCOORD));
282 <                if (cl == NULL)
179 <                        goto memerr;
180 <        }
279 >                                        /* optimize memory use */
280 >        cl.cl = (GCOORD *)realloc((char *)cl.cl, cl.n*sizeof(GCOORD));
281 >        if (cl.cl == NULL)
282 >                goto memerr;
283                                          /* sort the list */
284 <        qsort((char *)(cl+1), *cl, sizeof(GCOORD), cellcmp);
284 >        qsort((char *)cl.cl, cl.n, sizeof(GCOORD), cellcmp);
285   #endif
286 <        return(cl);
185 < viewerr:
186 <        error(INTERNAL, "unusable view in getviewcells");
286 >        return(cl.cl);
287   memerr:
288          error(SYSTEM, "out of memory in getviewcells");
289 + }
290 +
291 +
292 + gridlines(f)                    /* run through holodeck section grid lines */
293 + int     (*f)();
294 + {
295 +        register int    hd, w, i;
296 +        int     g0, g1;
297 +        FVECT   wp[2], mov;
298 +        double  d;
299 +                                        /* do each wall on each section */
300 +        for (hd = 0; hdlist[hd] != NULL; hd++)
301 +                for (w = 0; w < 6; w++) {
302 +                        g0 = ((w>>1)+1)%3;
303 +                        g1 = ((w>>1)+2)%3;
304 +                        d = 1.0/hdlist[hd]->grid[g0];
305 +                        mov[0] = d * hdlist[hd]->xv[g0][0];
306 +                        mov[1] = d * hdlist[hd]->xv[g0][1];
307 +                        mov[2] = d * hdlist[hd]->xv[g0][2];
308 +                        if (w & 1) {
309 +                                VSUM(wp[0], hdlist[hd]->orig,
310 +                                                hdlist[hd]->xv[w>>1], 1.);
311 +                                VSUM(wp[0], wp[0], mov, 1.);
312 +                        } else
313 +                                VCOPY(wp[0], hdlist[hd]->orig);
314 +                        VSUM(wp[1], wp[0], hdlist[hd]->xv[g1], 1.);
315 +                        for (i = hdlist[hd]->grid[g0]; ; ) {    /* g0 lines */
316 +                                (*f)(wp);
317 +                                if (!--i) break;
318 +                                wp[0][0] += mov[0]; wp[0][1] += mov[1];
319 +                                wp[0][2] += mov[2]; wp[1][0] += mov[0];
320 +                                wp[1][1] += mov[1]; wp[1][2] += mov[2];
321 +                        }
322 +                        d = 1.0/hdlist[hd]->grid[g1];
323 +                        mov[0] = d * hdlist[hd]->xv[g1][0];
324 +                        mov[1] = d * hdlist[hd]->xv[g1][1];
325 +                        mov[2] = d * hdlist[hd]->xv[g1][2];
326 +                        if (w & 1)
327 +                                VSUM(wp[0], hdlist[hd]->orig,
328 +                                                hdlist[hd]->xv[w>>1], 1.);
329 +                        else
330 +                                VSUM(wp[0], hdlist[hd]->orig, mov, 1.);
331 +                        VSUM(wp[1], wp[0], hdlist[hd]->xv[g0], 1.);
332 +                        for (i = hdlist[hd]->grid[g1]; ; ) {    /* g1 lines */
333 +                                (*f)(wp);
334 +                                if (!--i) break;
335 +                                wp[0][0] += mov[0]; wp[0][1] += mov[1];
336 +                                wp[0][2] += mov[2]; wp[1][0] += mov[0];
337 +                                wp[1][1] += mov[1]; wp[1][2] += mov[2];
338 +                        }
339 +                }
340   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines