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

Comparing ray/src/hd/rhd_glx.c (file contents):
Revision 3.5 by gregl, Fri Dec 26 14:46:21 1997 UTC vs.
Revision 3.23 by gwlarson, Thu Aug 27 19:33:05 1998 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1997 Silicon Graphics, Inc. */
1 > /* Copyright (c) 1998 Silicon Graphics, Inc. */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ SGI";
# Line 6 | Line 6 | static char SCCSid[] = "$SunId$ SGI";
6  
7   /*
8   * OpenGL GLX driver for holodeck display.
9 < * Based on x11 driver.
9 > * Based on old GLX driver using cones.
10 > *
11 > * Define symbol STEREO for stereo viewing.
12 > * Define symbol DOBJ for display object viewing.
13   */
14  
15 + #ifdef NOSTEREO
16 + #ifdef STEREO
17 + #undef STEREO
18 + #else
19 + #undef NOSTEREO
20 + #endif
21 + #endif
22 +
23   #include "standard.h"
24 < #include "rhd_qtree.h"
24 > #include "rhd_sample.h"
25  
26 < #include  <GL/glx.h>
26 > #include <sys/types.h>
27 > #include <GL/glx.h>
28 > #include <GL/glu.h>
29 > #ifdef STEREO
30 > #include <X11/extensions/SGIStereo.h>
31 > #endif
32 > #ifdef DOBJ
33 > #include "rhdobj.h"
34 > #endif
35  
36 < #include  "x11icon.h"
36 > #include "x11icon.h"
37  
38 + #ifndef RAYQLEN
39 + #define RAYQLEN         250             /* max. rays to queue before flush */
40 + #endif
41 +
42   #ifndef FEQ
43   #define FEQ(a,b)        ((a)-(b) <= FTINY && (a)-(b) >= -FTINY)
44   #endif
45  
23 #ifndef MAXCONE
24 #define MAXCONE         16              /* number of different cone sizes */
25 #endif
26 #ifndef MAXVERT
27 #define MAXVERT         32              /* maximum number of cone vertices */
28 #endif
29 #ifndef MINVERT
30 #define MINVERT         4               /* minimum number of cone vertices */
31 #endif
32 #ifndef DEPTHFACT
33 #define DEPTHFACT       16.             /* multiplier for depth tests */
34 #endif
35
46   #define GAMMA           1.4             /* default gamma correction */
47  
48   #define MOVPCT          7               /* percent distance to move /frame */
# Line 40 | Line 50 | static char SCCSid[] = "$SunId$ SGI";
50   #define MOVDEG          (-5)            /* degrees to orbit CW/down /frame */
51   #define MOVORB(s)       ((s)&ShiftMask ? 1 : (s)&ControlMask ? -1 : 0)
52  
53 + #ifndef TARGETFPS
54 + #define TARGETFPS       4.0             /* target frames/sec during motion */
55 + #endif
56 +
57   #define MINWIDTH        480             /* minimum graphics window width */
58   #define MINHEIGHT       400             /* minimum graphics window height */
59  
# Line 47 | Line 61 | static char SCCSid[] = "$SunId$ SGI";
61  
62   #define BORWIDTH        5               /* border width */
63  
64 + #define setstereobuf(bid)       (glXWaitGL(), \
65 +                                XSGISetStereoBuffer(ourdisplay, gwind, bid), \
66 +                                glXWaitX())
67 +
68   #define  ourscreen      DefaultScreen(ourdisplay)
69   #define  ourroot        RootWindow(ourdisplay,ourscreen)
70   #define  ourmask        (StructureNotifyMask|ExposureMask|KeyPressMask|\
# Line 56 | Line 74 | static char SCCSid[] = "$SunId$ SGI";
74  
75   struct driver   odev;                   /* global device driver structure */
76  
77 + #ifdef STEREO
78 + static VIEW     vwright;                /* right eye view */
79 + #endif
80 +
81 + static int      rayqleft = 0;           /* rays left to queue before flush */
82 +
83   static XEvent  currentevent;            /* current event */
84  
85   static int  mapped = 0;                 /* window is mapped? */
# Line 68 | Line 92 | static GLXContext      gctx;           /* our GLX context */
92  
93   static double   pwidth, pheight;        /* pixel dimensions (mm) */
94  
95 < static double   curzmax = 1e4;          /* current depth upper limit */
72 < static double   nxtzmax = 0.;           /* maximum (finite) depth so far */
95 > static double   mindpth, maxdpth;       /* min. and max. depth */
96  
97 < static struct {
75 <        double  rad;            /* cone radius */
76 <        int     nverts;         /* number of vertices */
77 <        FVECT   *va;            /* allocated vertex array */
78 < } cone[MAXCONE];        /* precomputed cones for drawing */
97 > double  dev_zmin, dev_zmax;             /* fore and aft clipping plane dist. */
98  
99   static int      inpresflags;            /* input result flags */
100  
101   static int      headlocked = 0;         /* lock vertical motion */
102  
103 < static int  resizewindow(), getevent(), getkey(), moveview(),
104 <                initcones(), freecones(),
86 <                getmove(), fixwindow(), mytmflags();
103 > static int  resizewindow(), getevent(), getkey(), moveview(), wipeclean(),
104 >                setglpersp(), getmove(), fixwindow(), mytmflags();
105  
106 + #ifdef STEREO
107 + static int  pushright(), popright();
108 + #endif
109  
110 < dev_open(id)                    /* initialize X11 driver */
110 > extern time_t   time();
111 >
112 >
113 > dev_open(id)                    /* initialize GLX driver */
114   char  *id;
115   {
116          extern char     *getenv();
117 +        static RGBPRIMS myprims = STDPRIMS;
118          static int      atlBest[] = {GLX_RGBA, GLX_RED_SIZE,8,
119                                  GLX_GREEN_SIZE,8, GLX_BLUE_SIZE,8,
120                                  GLX_DEPTH_SIZE,15, None};
121 <        char    *gv;
121 >        char    *ev;
122          double  gamval = GAMMA;
123 +        RGBPRIMP        dpri = stdprims;
124          XSetWindowAttributes    ourwinattr;
125          XWMHints        ourxwmhints;
126          XSizeHints      oursizhints;
127 <                                        /* set quadtree globals */
128 <        qtMinNodesiz = 3;
127 >                                        /* check for unsupported stereo */
128 > #ifdef NOSTEREO
129 >        error(INTERNAL, "stereo display driver unavailable");
130 > #endif
131                                          /* open display server */
132          ourdisplay = XOpenDisplay(NULL);
133          if (ourdisplay == NULL)
134                  error(USER, "cannot open X-windows; DISPLAY variable set?\n");
135 + #ifdef STEREO
136 +        switch (XSGIQueryStereoMode(ourdisplay, ourroot)) {
137 +        case STEREO_TOP:
138 +        case STEREO_BOTTOM:
139 +                break;
140 +        case STEREO_OFF:
141 +                error(USER,
142 +        "wrong video mode: run \"/usr/gfx/setmon -n STR_TOP\" first");
143 +        case X_STEREO_UNSUPPORTED:
144 +                error(USER, "stereo mode not supported on this screen");
145 +        default:
146 +                error(INTERNAL, "unknown stereo mode");
147 +        }
148 + #endif
149                                          /* find a usable visual */
150          ourvinf = glXChooseVisual(ourdisplay, ourscreen, atlBest);
151          if (ourvinf == NULL)
# Line 111 | Line 153 | char  *id;
153                                          /* get a context */
154          gctx = glXCreateContext(ourdisplay, ourvinf, NULL, GL_TRUE);
155                                          /* set gamma and tone mapping */
156 <        if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL
157 <                        || (gv = getenv("DISPLAY_GAMMA")) != NULL)
158 <                gamval = atof(gv);
159 <        if (tmInit(mytmflags(), stdprims, gamval) == NULL)
156 >        if ((ev = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL
157 >                        || (ev = getenv("DISPLAY_GAMMA")) != NULL)
158 >                gamval = atof(ev);
159 >        if ((ev = getenv("DISPLAY_PRIMARIES")) != NULL &&
160 >                        sscanf(ev, "%f %f %f %f %f %f %f %f",
161 >                                &myprims[RED][CIEX],&myprims[RED][CIEY],
162 >                                &myprims[GRN][CIEX],&myprims[GRN][CIEY],
163 >                                &myprims[BLU][CIEX],&myprims[BLU][CIEY],
164 >                                &myprims[WHT][CIEX],&myprims[WHT][CIEY]) >= 6)
165 >                dpri = myprims;
166 >        if (tmInit(mytmflags(), dpri, gamval) == NULL)
167                  error(SYSTEM, "not enough memory in dev_open");
168                                          /* open window */
169          ourwinattr.background_pixel = ourblack;
# Line 125 | Line 174 | char  *id;
174                                  ourvinf->visual, AllocNone);
175          gwind = XCreateWindow(ourdisplay, ourroot, 0, 0,
176                  DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH,
177 + #ifdef STEREO
178 +                (DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH)/2,
179 + #else
180                  DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH,
181 + #endif
182                  BORWIDTH, ourvinf->depth, InputOutput, ourvinf->visual,
183                  CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &ourwinattr);
184          if (gwind == 0)
# Line 138 | Line 191 | char  *id;
191                          gwind, x11icon_bits, x11icon_width, x11icon_height);
192          XSetWMHints(ourdisplay, gwind, &ourxwmhints);
193          oursizhints.min_width = MINWIDTH;
194 + #ifdef STEREO
195 +        oursizhints.min_height = MINHEIGHT/2;
196 +        oursizhints.max_width = DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH;
197 +        oursizhints.max_height = (DisplayHeight(ourdisplay,ourscreen) -
198 +                                        2*BORWIDTH)/2;
199 +        oursizhints.flags = PMinSize|PMaxSize;
200 + #else
201          oursizhints.min_height = MINHEIGHT;
202          oursizhints.flags = PMinSize;
203 + #endif
204          XSetNormalHints(ourdisplay, gwind, &oursizhints);
205                                          /* set GLX context */
206          glXMakeCurrent(ourdisplay, gwind, gctx);
207          glEnable(GL_DEPTH_TEST);
208          glDepthFunc(GL_LEQUAL);
209 <        glShadeModel(GL_FLAT);
209 >        glShadeModel(GL_SMOOTH);
210          glDisable(GL_DITHER);
211          glDisable(GL_CULL_FACE);
151        glMatrixMode(GL_PROJECTION);
152        glOrtho(0., 1., 0., 1., -.01, 1.01);
153        glTranslated(0., 0., -1.01);
212                                          /* figure out sensible view */
213          pwidth = (double)DisplayWidthMM(ourdisplay, ourscreen) /
214                          DisplayWidth(ourdisplay, ourscreen);
215          pheight = (double)DisplayHeightMM(ourdisplay, ourscreen) /
216                          DisplayHeight(ourdisplay, ourscreen);
217 + #ifdef STEREO
218 +        pheight *= 2.;
219 +        setstereobuf(STEREO_BUFFER_LEFT);
220 + #endif
221 +        checkglerr("setting rendering parameters");
222          copystruct(&odev.v, &stdview);
223          odev.v.type = VT_PER;
224                                          /* map the window */
225          XMapWindow(ourdisplay, gwind);
226          dev_input();                    /* sets size and view angles */
227 <        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
228 <                                        /* allocate our leaf pile */
229 <        if (!qtAllocLeaves(2 * DisplayWidth(ourdisplay,ourscreen) *
167 <                        DisplayHeight(ourdisplay,ourscreen) /
168 <                        (qtMinNodesiz*qtMinNodesiz)))
227 >                                        /* allocate our samples */
228 >        if (!smInit(DisplayWidth(ourdisplay,ourscreen) *
229 >                        DisplayHeight(ourdisplay,ourscreen) / 10))
230                  error(SYSTEM, "insufficient memory for value storage");
231 +        mindpth = FHUGE; maxdpth = FTINY;
232          odev.name = id;
233          odev.ifd = ConnectionNumber(ourdisplay);
172                                        /* initialize cone array */
173        initcones();
234   }
235  
236  
237   dev_close()                     /* close our display and free resources */
238   {
239 +        smInit(0);
240 + #ifdef DOBJ
241 +        dobj_cleanup();
242 + #endif
243          glXMakeCurrent(ourdisplay, None, NULL);
244          glXDestroyContext(ourdisplay, gctx);
245          XDestroyWindow(ourdisplay, gwind);
246          gwind = 0;
247          XCloseDisplay(ourdisplay);
248          ourdisplay = NULL;
185        qtFreeLeaves();
249          tmDone(NULL);
187        freecones();
250          odev.v.type = 0;
251          odev.hres = odev.vres = 0;
252          odev.ifd = -1;
253   }
254  
255  
256 + dev_clear()                     /* clear our representation */
257 + {
258 +        smInit(rsL.max_samp);
259 +        wipeclean();
260 +        rayqleft = 0;                   /* hold off update */
261 + }
262 +
263 +
264   int
265   dev_view(nv)                    /* assign new driver view */
266   register VIEW   *nv;
267   {
268 <        if (nv->type == VT_PAR ||               /* check view legality */
268 >        double  d;
269 >
270 >        if (nv->type != VT_PER ||               /* check view legality */
271                          nv->horiz > 160. || nv->vert > 160.) {
272                  error(COMMAND, "illegal view type/angle");
273                  nv->type = odev.v.type;
# Line 203 | Line 275 | register VIEW  *nv;
275                  nv->vert = odev.v.vert;
276                  return(0);
277          }
206        if (nv->vfore > FTINY) {
207                error(COMMAND, "cannot handle fore clipping");
208                nv->vfore = 0.;
209                return(0);
210        }
278          if (nv != &odev.v) {
279 <                if (!FEQ(nv->horiz,odev.v.horiz) ||     /* resize window? */
279 >                                                /* resize window? */
280 >                if (!FEQ(nv->horiz,odev.v.horiz) ||
281                                  !FEQ(nv->vert,odev.v.vert)) {
282                          int     dw = DisplayWidth(ourdisplay,ourscreen);
283                          int     dh = DisplayHeight(ourdisplay,ourscreen);
284  
285                          dw -= 25;       /* for window frame */
286                          dh -= 50;
287 + #ifdef STEREO
288 +                        dh /= 2;
289 + #endif
290                          odev.hres = 2.*VIEWDIST/pwidth *
291                                          tan(PI/180./2.*nv->horiz);
292                          odev.vres = 2.*VIEWDIST/pheight *
# Line 231 | Line 302 | register VIEW  *nv;
302                          XResizeWindow(ourdisplay, gwind, odev.hres, odev.vres);
303                          dev_input();    /* get resize event */
304                  }
305 <                copystruct(&odev.v, nv);
305 >                copystruct(&odev.v, nv);        /* setview() already called */
306 > #ifdef STEREO
307 >                copystruct(&vwright, nv);
308 >                d = eyesepdist / sqrt(nv->hn2);
309 >                VSUM(vwright.vp, nv->vp, nv->hvec, d);
310 >                /* setview(&vwright);   -- Unnecessary */
311 > #endif
312          }
313 <        if (nxtzmax > FTINY) {
237 <                curzmax = nxtzmax;
238 <                nxtzmax = 0.;
239 <        }
240 <        glClear(GL_DEPTH_BUFFER_BIT);
241 <        qtReplant();
313 >        wipeclean();
314          return(1);
315   }
316  
317  
318 + dev_auxcom(cmd, args)           /* process an auxiliary command */
319 + char    *cmd, *args;
320 + {
321 + #ifdef DOBJ
322 +        if (dobj_command(cmd, args) >= 0)
323 +                return;
324 + #endif
325 +        sprintf(errmsg, "%s: unknown command", cmd);
326 +        error(COMMAND, errmsg);
327 + }
328 +
329 +
330 + VIEW *
331 + dev_auxview(n, hvres)           /* return nth auxiliary view */
332 + int     n;
333 + int     hvres[2];
334 + {
335 +        hvres[0] = odev.hres; hvres[1] = odev.vres;
336 +        if (n == 0)
337 +                return(&odev.v);
338 + #ifdef STEREO
339 +        if (n == 1)
340 +                return(&vwright);
341 + #endif
342 +        return(NULL);
343 + }
344 +
345 +
346   int
347   dev_input()                     /* get X11 input */
348   {
# Line 251 | Line 351 | dev_input()                    /* get X11 input */
351          do
352                  getevent();
353  
354 <        while (XQLength(ourdisplay) > 0);
354 >        while (XPending(ourdisplay) > 0);
355  
356 +        odev.inpready = 0;
357 +
358          return(inpresflags);
359   }
360  
361  
362 + dev_value(c, d, p)              /* add a pixel value to our mesh */
363 + COLR    c;
364 + FVECT   d, p;
365 + {
366 +        double  depth;
367 + #ifdef DOBJ
368 +        if (dobj_lightsamp != NULL) {   /* in light source sampling */
369 +                (*dobj_lightsamp)(c, d, p);
370 +                return;
371 +        }
372 + #endif
373 +        if (p != NULL) {                /* add depth to our range */
374 +                depth = (p[0] - odev.v.vp[0])*d[0] +
375 +                        (p[1] - odev.v.vp[1])*d[1] +
376 +                        (p[2] - odev.v.vp[2])*d[2];
377 +                if (depth > FTINY) {
378 +                        if (depth < mindpth)
379 +                                mindpth = depth;
380 +                        if (depth > maxdpth)
381 +                                maxdpth = depth;
382 +                }
383 +        }
384 +        smNewSamp(c, d, p);             /* add to display representation */
385 +        if (!--rayqleft)
386 +                dev_flush();            /* flush output */
387 + }
388 +
389 +
390   int
391   dev_flush()                     /* flush output */
392   {
393 <        qtUpdate();
394 <        glFlush();
395 <        return(XPending(ourdisplay));
393 >        if (mapped) {
394 > #ifdef STEREO
395 >                pushright();                    /* update right eye */
396 >                smUpdate(&vwright, 100);
397 > #ifdef DOBJ
398 >                dobj_render();                  /* usually in foreground */
399 > #endif
400 >                popright();                     /* update left eye */
401 > #endif
402 >                smUpdate(&odev.v, 100);
403 >                checkglerr("rendering mesh");
404 > #ifdef DOBJ
405 >                dobj_render();
406 > #endif
407 >                glFlush();                      /* flush OGL */
408 >        }
409 >        rayqleft = RAYQLEN;
410 >                                        /* flush X11 and return # pending */
411 >        return(odev.inpready = XPending(ourdisplay));
412   }
413  
414  
415 < dev_cone(rgb, ip, rad)          /* render a cone in view coordinates */
416 < BYTE    rgb[3];
271 < FVECT   ip;
272 < double  rad;
415 > checkglerr(where)               /* check for GL or GLU error */
416 > char    *where;
417   {
418 <        register int    ci, j;
419 <        double  apexh, basez;
420 <                                        /* compute apex height (0. to 1.) */
421 <        if (ip[2] > 1e6)
422 <                apexh = 1. - 1./DEPTHFACT;
423 <        else {
280 <                if (ip[2] > nxtzmax)
281 <                        nxtzmax = ip[2];
282 <                if (ip[2] >= curzmax)
283 <                        apexh = 1. - 1./DEPTHFACT;
284 <                else
285 <                        apexh = 1. - ip[2]/(curzmax*DEPTHFACT);
418 >        register GLenum errcode;
419 >
420 >        while ((errcode = glGetError()) != GL_NO_ERROR) {
421 >                sprintf(errmsg, "OpenGL error %s: %s",
422 >                                where, gluErrorString(errcode));
423 >                error(WARNING, errmsg);
424          }
287        rad *= 1.25;                    /* find conservative cone match */
288        for (ci = 0; ci < MAXCONE-1; ci++)
289                if (cone[ci].rad >= rad)
290                        break;
291                                        /* draw it */
292        glColor3ub(rgb[0], rgb[1], rgb[2]);
293        glBegin(GL_TRIANGLE_FAN);
294        glVertex3d(ip[0], ip[1], apexh);        /* start with apex */
295        basez = apexh*cone[ci].va[0][2];        /* base z's all the same */
296        for (j = 0; j < cone[ci].nverts; j++)   /* draw each face */
297                glVertex3d(ip[0]+cone[ci].va[j][0], ip[1]+cone[ci].va[j][1],
298                                basez);
299                                                /* connect last to first */
300        glVertex3d(ip[0]+cone[ci].va[0][0], ip[1]+cone[ci].va[0][1], basez);
301        glEnd();                                /* all done */
425   }
426  
427  
428 + #ifdef STEREO
429 + static
430 + pushright()                     /* push on right view */
431 + {
432 +        double  d;
433 +
434 +        setstereobuf(STEREO_BUFFER_RIGHT);
435 +        glMatrixMode(GL_MODELVIEW);
436 +        glPushMatrix();
437 +        d = -eyesepdist / sqrt(odev.v.hn2);
438 +        glTranslated(d*odev.v.hvec[0], d*odev.v.hvec[1], d*odev.v.hvec[2]);
439 +        checkglerr("setting right view");
440 + }
441 +
442 +
443 + static
444 + popright()                      /* pop off right view */
445 + {
446 +        glMatrixMode(GL_MODELVIEW);
447 +        glPopMatrix();
448 +        setstereobuf(STEREO_BUFFER_LEFT);
449 + }
450 + #endif
451 +
452 +
453   static int
454   mytmflags()                     /* figure out tone mapping flags */
455   {
# Line 313 | Line 461 | mytmflags()                    /* figure out tone mapping flags */
461                          tail = cp+1;
462          for (cp = tail; *cp && *cp != '.'; cp++)
463                  ;
464 <        if (cp-tail == 3 && !strncmp(tail, "glx", 3))
465 <                return(TM_F_CAMERA);
466 <        if (cp-tail == 4 && !strncmp(tail, "glxh", 4))
467 <                return(TM_F_HUMAN);
320 <        error(USER, "illegal driver name");
464 >        if (cp > tail && cp[-1] == 'h')
465 >                return(TM_F_HUMAN|TM_F_NOSTDERR);
466 >        else
467 >                return(TM_F_CAMERA|TM_F_NOSTDERR);
468   }
469  
470  
471   static
325 initcones()                     /* initialize cone vertices */
326 {
327        register int    i, j;
328        double  minrad, d;
329
330        if (cone[0].nverts)
331                freecones();
332        minrad = 2.*qtMinNodesiz/(double)(DisplayWidth(ourdisplay,ourscreen) +
333                                        DisplayHeight(ourdisplay,ourscreen));
334        for (i = 0; i < MAXCONE; i++) {
335                d = (double)i/(MAXCONE-1); d *= d;      /* x^2 distribution */
336                cone[i].rad = minrad + (1.-minrad)*d;
337                cone[i].nverts = MINVERT + (MAXVERT-MINVERT)*d;
338                cone[i].va = (FVECT *)malloc(cone[i].nverts*sizeof(FVECT));
339                if (cone[i].va == NULL)
340                        error(SYSTEM, "out of memory in initcones");
341                for (j = cone[i].nverts; j--; ) {
342                        d = 2.*PI * (j+.5) / (cone[i].nverts);
343                        cone[i].va[j][0] = cos(d) * cone[i].rad;
344                        cone[i].va[j][1] = sin(d) * cone[i].rad;
345                        cone[i].va[j][2] = 1. - cone[i].rad;
346                }
347        }
348 }
349
350
351 static
352 freecones()                     /* free cone vertices */
353 {
354        register int    i;
355
356        for (i = MAXCONE; i--; )
357                if (cone[i].nverts) {
358                        free((char *)cone[i].va);
359                        cone[i].va = NULL;
360                        cone[i].nverts = 0;
361                }
362 }
363
364
365 static
472   getevent()                      /* get next event */
473   {
474          XNextEvent(ourdisplay, levptr(XEvent));
# Line 399 | Line 505 | register FVECT wp[2];
505  
506  
507   static
508 < draw_grids()                    /* draw holodeck section grids */
508 > draw_grids(fore)                /* draw holodeck section grids */
509 > int     fore;
510   {
511 <        static BYTE     gridrgba[4] = {0x0, 0xff, 0xff, 0x00};
512 <        double  xmin, xmax, ymin, ymax, zmin, zmax;
513 <        double  d, cx, sx, crad;
514 <        FVECT   vx, vy;
408 <        register int    i, j;
409 <                                        /* can we even do it? */
410 <        if (!mapped || odev.v.type != VT_PER)
411 <                return;
412 <                                        /* compute view frustum */
413 <        if (normalize(odev.v.vdir) == 0.0)
414 <                return;
415 <        zmin = 0.01;
416 <        zmax = 10000.;
417 <        if (odev.v.vfore > FTINY)
418 <                zmin = odev.v.vfore;
419 <        if (odev.v.vaft > FTINY)
420 <                zmax = odev.v.vaft;
421 <        xmax = zmin * tan(PI/180./2. * odev.v.horiz);
422 <        xmin = -xmax;
423 <        d = odev.v.hoff * (xmax - xmin);
424 <        xmin += d; xmax += d;
425 <        ymax = zmin * tan(PI/180./2. * odev.v.vert);
426 <        ymin = -ymax;
427 <        d = odev.v.voff * (ymax - ymin);
428 <        ymin += d; ymax += d;
429 <                                        /* set view matrix */
430 <        glMatrixMode(GL_PROJECTION);
431 <        glPushMatrix();
432 <        glLoadIdentity();
433 <        glFrustum(xmin, xmax, ymin, ymax, zmin, zmax);
434 <        gluLookAt(odev.v.vp[0], odev.v.vp[1], odev.v.vp[2],
435 <                odev.v.vp[0] + odev.v.vdir[0],
436 <                odev.v.vp[1] + odev.v.vdir[1],
437 <                odev.v.vp[2] + odev.v.vdir[2],
438 <                odev.v.vup[0], odev.v.vup[1], odev.v.vup[2]);
439 <        glDisable(GL_DEPTH_TEST);       /* write no depth values */
440 <        glColor4ub(gridrgba[0], gridrgba[1], gridrgba[2], gridrgba[3]);
511 >        if (fore)
512 >                glColor4ub(0, 255, 255, 0);
513 >        else
514 >                glColor4ub(0, 0, 0, 0);
515          glBegin(GL_LINES);              /* draw each grid line */
516          gridlines(draw3dline);
517          glEnd();
518 <        glEnable(GL_DEPTH_TEST);        /* restore rendering params */
445 <        glPopMatrix();
518 >        checkglerr("drawing grid lines");
519   }
520  
521  
# Line 451 | Line 524 | moveview(dx, dy, mov, orb)     /* move our view */
524   int     dx, dy, mov, orb;
525   {
526          VIEW    nv;
527 <        FVECT   odir, v1;
527 >        FVECT   odir, v1, wip;
528          double  d;
529          register int    li;
530                                  /* start with old view */
531          copystruct(&nv, &odev.v);
532 <                                /* change view direction */
533 <        if (mov | orb) {
534 <                if ((li = qtFindLeaf(dx, dy)) < 0)
532 >                                /* orient our motion */
533 >        if (viewray(v1, odir, &odev.v,
534 >                        (dx+.5)/odev.hres, (dy+.5)/odev.vres) < -FTINY)
535 >                return(0);              /* outside view */
536 >        if (mov | orb) {        /* moving relative to geometry */
537 > #ifdef DOBJ
538 >                d = dobj_trace(NULL, v1, odir); /* check objects */
539 >                                                /* check holodeck */
540 >                if ((li = smFindSamp(v1, odir)) >= 0) {
541 >                        VCOPY(wip, rsL.wp[li]);
542 >                        if (d < .99*FHUGE && d*d <= dist2(v1, wip))
543 >                                li = -1;        /* object is closer */
544 >                } else if (d >= .99*FHUGE)
545 >                        return(0);              /* nothing visible */
546 >                if (li < 0)
547 >                        VSUM(wip, v1, odir, d); /* else get object point */
548 > #else
549 >                if ((li = smFindSamp(v1, odir)) < 0)
550                          return(0);      /* not on window */
551 <                VSUM(odir, qtL.wp[li], nv.vp, -1.);
552 <        } else {
553 <                if (viewray(nv.vp, nv.vdir, &odev.v,
554 <                                (dx+.5)/odev.hres, (dy+.5)/odev.vres) < -FTINY)
555 <                        return(0);      /* outside view */
468 <        }
551 >                VCOPY(wip, rsL.wp[li]);
552 > #endif
553 >                VSUM(odir, wip, odev.v.vp, -1.);
554 >        } else                  /* panning with constant viewpoint */
555 >                VCOPY(nv.vdir, odir);
556          if (orb && mov) {               /* orbit left/right */
557                  spinvector(odir, odir, nv.vup, d=MOVDEG*PI/180.*mov);
558 <                VSUM(nv.vp, qtL.wp[li], odir, -1.);
558 >                VSUM(nv.vp, wip, odir, -1.);
559                  spinvector(nv.vdir, nv.vdir, nv.vup, d);
560          } else if (orb) {               /* orbit up/down */
561                  fcross(v1, odir, nv.vup);
562                  if (normalize(v1) == 0.)
563                          return(0);
564                  spinvector(odir, odir, v1, d=MOVDEG*PI/180.*orb);
565 <                VSUM(nv.vp, qtL.wp[li], odir, -1.);
565 >                VSUM(nv.vp, wip, odir, -1.);
566                  spinvector(nv.vdir, nv.vdir, v1, d);
567          } else if (mov) {               /* move forward/backward */
568                  d = MOVPCT/100. * mov;
# Line 483 | Line 570 | int    dx, dy, mov, orb;
570          }
571          if (!mov ^ !orb && headlocked) {        /* restore head height */
572                  VSUM(v1, odev.v.vp, nv.vp, -1.);
573 <                d = DOT(v1, odev.v.vup);
573 >                d = DOT(v1, nv.vup);
574                  VSUM(nv.vp, nv.vp, odev.v.vup, d);
575          }
576          if (setview(&nv) != NULL)
# Line 500 | Line 587 | XButtonPressedEvent    *ebut;
587   {
588          int     movdir = MOVDIR(ebut->button);
589          int     movorb = MOVORB(ebut->state);
590 <        int     oldnodesiz = qtMinNodesiz;
590 >        int     qlevel = 99;
591 >        time_t  lasttime, thistime;
592 >        int     nframes;
593          Window  rootw, childw;
594          int     rootx, rooty, wx, wy;
595          unsigned int    statemask;
596  
597 <        qtMinNodesiz = 24;              /* accelerate update rate */
509 <        XNoOp(ourdisplay);
597 >        XNoOp(ourdisplay);              /* makes sure we're not idle */
598  
599 +        lasttime = time(0); nframes = 0;
600          while (!XCheckMaskEvent(ourdisplay,
601                          ButtonReleaseMask, levptr(XEvent))) {
602 <
602 >                                        /* get cursor position */
603                  if (!XQueryPointer(ourdisplay, gwind, &rootw, &childw,
604                                  &rootx, &rooty, &wx, &wy, &statemask))
605                          break;          /* on another screen */
606  
607 +                draw_grids(0);          /* clear old grid lines */
608 + #ifdef STEREO
609 +                pushright(); draw_grids(0); popright();
610 + #endif
611 +                                        /* compute view motion */
612                  if (!moveview(wx, odev.vres-1-wy, movdir, movorb)) {
613                          sleep(1);
614 <                        continue;
614 >                        lasttime++;
615 >                        continue;       /* cursor in bad place */
616                  }
617 <                glClear(GL_COLOR_BUFFER_BIT);
618 <                qtUpdate();
619 <                draw_grids();
617 >                draw_grids(1);          /* redraw grid */
618 > #ifdef STEREO
619 >                pushright();
620 >                draw_grids(1);
621 >                smUpdate(&vwright, qlevel);
622 > #ifdef DOBJ
623 >                dobj_render();
624 > #endif
625 >                popright();
626 > #endif
627 >                                        /* redraw mesh */
628 >                smUpdate(&odev.v, qlevel);
629 > #ifdef DOBJ
630 >                dobj_render();          /* redraw object */
631 > #endif
632                  glFlush();
633 +                nframes++;              /* figure out good quality level */
634 +                thistime = time(0);
635 +                if (thistime - lasttime >= 3 ||
636 +                                nframes > (int)(3*3*TARGETFPS)) {
637 +                        qlevel = thistime<=lasttime ? 1000 :
638 +                                (int)((double)nframes/(thistime-lasttime)
639 +                                        / TARGETFPS * qlevel + 0.5);
640 +                        lasttime = thistime; nframes = 0;
641 +                        if (qlevel > 99) {
642 +                                if (qlevel > 300) {     /* put on the brakes */
643 +                                        sleep(1);
644 +                                        lasttime++;
645 +                                }
646 +                                qlevel = 99;
647 +                        } else if (qlevel < 1)
648 +                                qlevel = 1;
649 +                }
650          }
651          if (!(inpresflags & DFL(DC_SETVIEW))) { /* do final motion */
652                  movdir = MOVDIR(levptr(XButtonReleasedEvent)->button);
# Line 530 | Line 654 | XButtonPressedEvent    *ebut;
654                  wy = levptr(XButtonReleasedEvent)->y;
655                  moveview(wx, odev.vres-1-wy, movdir, movorb);
656          }
657 <        dev_flush();
657 > }
658  
659 <        qtMinNodesiz = oldnodesiz;      /* restore quadtree resolution */
659 >
660 > static
661 > setglpersp(vp)                  /* set perspective view in GL */
662 > register VIEW   *vp;
663 > {
664 >        double  d, xmin, xmax, ymin, ymax;
665 >
666 >        if (mindpth >= maxdpth) {
667 >                dev_zmin = 0.1;
668 >                dev_zmax = 100.;
669 >        } else {
670 >                dev_zmin = 0.5*mindpth;
671 >                dev_zmax = 1.5*maxdpth;
672 >                if (dev_zmin > dev_zmax/100.)
673 >                        dev_zmin = dev_zmax/100.;
674 >        }
675 >        if (odev.v.vfore > FTINY)
676 >                dev_zmin = odev.v.vfore;
677 >        if (odev.v.vaft > FTINY)
678 >                dev_zmax = odev.v.vaft;
679 >        if (dev_zmin < dev_zmax/5000.)
680 >                dev_zmin = dev_zmax/5000.;
681 >        xmax = dev_zmin * tan(PI/180./2. * odev.v.horiz);
682 >        xmin = -xmax;
683 >        d = odev.v.hoff * (xmax - xmin);
684 >        xmin += d; xmax += d;
685 >        ymax = dev_zmin * tan(PI/180./2. * odev.v.vert);
686 >        ymin = -ymax;
687 >        d = odev.v.voff * (ymax - ymin);
688 >        ymin += d; ymax += d;
689 >                                        /* set view matrix */
690 >        glMatrixMode(GL_PROJECTION);
691 >        glLoadIdentity();
692 >        glFrustum(xmin, xmax, ymin, ymax, dev_zmin, dev_zmax);
693 >        gluLookAt(odev.v.vp[0], odev.v.vp[1], odev.v.vp[2],
694 >                odev.v.vp[0] + odev.v.vdir[0],
695 >                odev.v.vp[1] + odev.v.vdir[1],
696 >                odev.v.vp[2] + odev.v.vdir[2],
697 >                odev.v.vup[0], odev.v.vup[1], odev.v.vup[2]);
698 >        checkglerr("setting perspective view");
699   }
700  
701  
702   static
703 + wipeclean()                     /* prepare for redraw */
704 + {
705 +                                        /* clear depth buffer */
706 + #ifdef STEREO
707 +        setstereobuf(STEREO_BUFFER_RIGHT);
708 +        glClear(GL_DEPTH_BUFFER_BIT);
709 +        setstereobuf(STEREO_BUFFER_LEFT);
710 + #endif
711 +        glClear(GL_DEPTH_BUFFER_BIT);
712 +        smClean();                      /* reset drawing routines */
713 +        setglpersp(&odev.v);            /* reset view & clipping planes */
714 + }
715 +
716 +
717 + static
718   getkey(ekey)                            /* get input key */
719   register XKeyPressedEvent  *ekey;
720   {
# Line 567 | Line 745 | register XKeyPressedEvent  *ekey;
745                  inpresflags |= DFL(DC_RESUME);
746                  return;
747          case CTRL('R'):                 /* redraw screen */
748 <                glClear(GL_DEPTH_BUFFER_BIT);
571 <                qtRedraw(0, 0, odev.hres, odev.vres);
748 >                wipeclean();
749                  return;
750          case CTRL('L'):                 /* refresh from server */
751                  if (inpresflags & DFL(DC_REDRAW))
752                          return;
753 +                setglpersp(&odev.v);            /* reset clipping planes */
754                  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
755 <                draw_grids();
755 >                glDisable(GL_DEPTH_TEST);       /* so grids will clear */
756 >                draw_grids(1);
757 > #ifdef STEREO
758 >                pushright();
759 >                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
760 >                draw_grids(1);
761 >                popright();
762 > #endif
763 >                glEnable(GL_DEPTH_TEST);
764                  glFlush();
765 <                qtCompost(100);                 /* get rid of old values */
765 >                smInit(rsL.max_samp);           /* get rid of old values */
766                  inpresflags |= DFL(DC_REDRAW);  /* resend values from server */
767 +                rayqleft = 0;                   /* hold off update */
768                  return;
769          case 'K':                       /* kill rtrace process(es) */
770                  inpresflags |= DFL(DC_KILL);
# Line 602 | Line 789 | static
789   fixwindow(eexp)                         /* repair damage to window */
790   register XExposeEvent  *eexp;
791   {
792 <        int     xmin, xmax, ymin, ymax;
606 <
607 <        if (odev.hres == 0 || odev.vres == 0)   /* first exposure */
792 >        if (odev.hres == 0 | odev.vres == 0) {  /* first exposure */
793                  resizewindow((XConfigureEvent *)eexp);
794 <        xmin = eexp->x; xmax = eexp->x + eexp->width;
795 <        ymin = odev.vres - eexp->y - eexp->height; ymax = odev.vres - eexp->y;
796 <                                                /* clear portion of depth */
797 <        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
798 <        glDepthFunc(GL_ALWAYS);
614 <        glBegin(GL_POLYGON);
615 <        glVertex3d((double)xmin/odev.hres, (double)ymin/odev.vres, 0.);
616 <        glVertex3d((double)xmax/odev.hres, (double)ymin/odev.vres, 0.);
617 <        glVertex3d((double)xmax/odev.hres, (double)ymax/odev.vres, 0.);
618 <        glVertex3d((double)xmin/odev.hres, (double)ymax/odev.vres, 0.);
619 <        glEnd();
620 <        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
621 <        glDepthFunc(GL_LEQUAL);
622 <        qtRedraw(xmin, ymin, xmax, ymax);
794 >                return;
795 >        }
796 >        if (eexp->count)                /* wait for final exposure */
797 >                return;
798 >        wipeclean();                    /* clear depth */
799   }
800  
801  
# Line 627 | Line 803 | static
803   resizewindow(ersz)                      /* resize window */
804   register XConfigureEvent  *ersz;
805   {
806 +        glViewport(0, 0, ersz->width, ersz->height);
807 +
808          if (ersz->width == odev.hres && ersz->height == odev.vres)
809                  return;
810  
# Line 635 | Line 813 | register XConfigureEvent  *ersz;
813  
814          odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres);
815          odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres);
638
639        glViewport(0, 0, odev.hres, odev.vres);
816  
817          inpresflags |= DFL(DC_SETVIEW);
818   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines