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.1 by gregl, Tue Dec 23 18:31:00 1997 UTC vs.
Revision 3.2 by gregl, Wed Dec 24 14:06:40 1997 UTC

# Line 6 | Line 6 | static char SCCSid[] = "$SunId$ SGI";
6  
7   /*
8   * OpenGL GLX driver for holodeck display.
9 < * Based on rview driver.
9 > * Based on x11 driver.
10   */
11  
12   #include "standard.h"
# Line 26 | Line 26 | static char SCCSid[] = "$SunId$ SGI";
26   #endif
27  
28   #ifndef FREEPCT
29 < #define FREEPCT         25              /* percentage of values to free */
29 > #define FREEPCT         10              /* percentage of values to free */
30   #endif
31  
32   #ifndef NCONEV
33   #define NCONEV          7               /* number of cone base vertices */
34   #endif
35   #ifndef CONEH
36 < #define CONEH           0.25            /* cone height (fraction of depth) */
36 > #define CONEH           5.              /* cone height (fraction of depth) */
37   #endif
38   #ifndef CONEW
39 < #define CONEW           0.035           /* cone width (fraction of screen) */
39 > #define CONEW           0.07            /* cone width (fraction of screen) */
40   #endif
41 + #ifndef DIRPEN
42 + #define DIRPEN          0.001           /* direction penalty factor */
43 + #endif
44  
45 < #define GAMMA           2.2             /* default gamma correction */
45 > #define GAMMA           1.4             /* default gamma correction */
46  
47   #define MOVPCT          7               /* percent distance to move /frame */
48   #define MOVDIR(b)       ((b)==Button1 ? 1 : (b)==Button2 ? 0 : -1)
# Line 65 | Line 68 | struct driver  odev;                   /* global device driver structur
68   static XEvent  currentevent;            /* current event */
69  
70   static int  mapped = 0;                 /* window is mapped? */
68 static unsigned long  *pixval = NULL;   /* allocated pixels */
71   static unsigned long  ourblack=0, ourwhite=~0;
72  
73   static Display  *ourdisplay = NULL;     /* our display */
# Line 74 | Line 76 | static Window  gwind = 0;              /* our graphics window */
76   static GLXContext       gctx;           /* our GLX context */
77  
78   static double   mindepth = FHUGE;       /* minimum depth value so far */
79 < static double   maxdepth = 0.;          /* maximum depth value */
79 > static double   maxdepth = 0.;          /* maximum depth value so far */
80  
81   static double   pwidth, pheight;        /* pixel dimensions (mm) */
82  
# Line 99 | Line 101 | static struct {
101          char            *base;          /* base of allocated memory */
102   }       rV;                     /* our collection of values */
103  
104 + static int      *valmap = NULL;         /* sorted map of screen values */
105 + static int      vmaplen = 0;            /* value map length */
106 +
107   #define redraw()        (rV.drl = rV.bl)
108  
109   static int  resizewindow(), getevent(), getkey(), moveview(),
110                  setGLview(), getmove(), fixwindow(), mytmflags(),
111 <                newvalue(), drawvalue(), Compost(),
112 <                FindValue(), AllocValues(), TMapValues(), FreeValues();
111 >                drawvalue(), valcmp(), clralphas(), setalphas(), mergalphas(),
112 >                IndexValue(), Compost(), FindValue(), TMapValues(),
113 >                AllocValues(), FreeValues();
114  
115 + extern int4     encodedir();
116 + extern double   fdir2diff(), dir2diff();
117  
118 +
119   dev_open(id)                    /* initialize X11 driver */
120   char  *id;
121   {
122          extern char     *getenv();
123          static int      atlBest[] = {GLX_RGBA, GLX_RED_SIZE,8,
124                                  GLX_GREEN_SIZE,8, GLX_BLUE_SIZE,8,
125 <                                GLX_ALPHA_SIZE,8, GLX_DEPTH_SIZE,23,
126 <                                /*GLX_DOUBLEBUFFER,*/ None};
118 <        static int      atlOK[] = {GLX_RGBA, GLX_RED_SIZE,4,
119 <                                GLX_GREEN_SIZE,4, GLX_BLUE_SIZE,4,
120 <                                GLX_ALPHA_SIZE,4, GLX_DEPTH_SIZE,15,
121 <                                /*GLX_DOUBLEBUFFER,*/ None};
125 >                                GLX_ALPHA_SIZE,8, GLX_DEPTH_SIZE,15,
126 >                                None};
127          char    *gv;
128          double  gamval = GAMMA;
129          XSetWindowAttributes    ourwinattr;
# Line 131 | Line 136 | char  *id;
136                                          /* find a usable visual */
137          ourvinf = glXChooseVisual(ourdisplay, ourscreen, atlBest);
138          if (ourvinf == NULL)
134                ourvinf = glXChooseVisual(ourdisplay, ourscreen, atlOK);
135        if (ourvinf == NULL)
139                  error(USER, "no suitable visuals available");
140                                          /* get a context */
141          gctx = glXCreateContext(ourdisplay, ourvinf, NULL, GL_TRUE);
# Line 167 | Line 170 | char  *id;
170          oursizhints.min_height = MINHEIGHT;
171          oursizhints.flags = PMinSize;
172          XSetNormalHints(ourdisplay, gwind, &oursizhints);
173 <                                        /* map the window and get its size */
174 <        XMapWindow(ourdisplay, gwind);
175 <        dev_input();
176 <                                        /* allocate our value list */
177 <        if (!AllocValues(DisplayWidth(ourdisplay,ourscreen) *
178 <                        DisplayHeight(ourdisplay,ourscreen) / 4))
176 <                error(SYSTEM, "insufficient memory for value storage");
173 >                                        /* set GLX context */
174 >        glXMakeCurrent(ourdisplay, gwind, gctx);
175 >        glEnable(GL_DEPTH_TEST);
176 >        glDepthFunc(GL_LEQUAL);
177 >        glShadeModel(GL_FLAT);
178 >        glDisable(GL_DITHER);
179                                          /* figure out sensible view */
180          pwidth = (double)DisplayWidthMM(ourdisplay, ourscreen) /
181                          DisplayWidth(ourdisplay, ourscreen);
# Line 181 | Line 183 | char  *id;
183                          DisplayHeight(ourdisplay, ourscreen);
184          copystruct(&odev.v, &stdview);
185          odev.v.type = VT_PER;
186 <        odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres);
187 <        odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres);
186 >                                        /* map the window */
187 >        XMapWindow(ourdisplay, gwind);
188 >        dev_input();                    /* sets size and view angles */
189 >        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
190 >                                        /* allocate our value list */
191 >        if (!AllocValues(DisplayWidth(ourdisplay,ourscreen) *
192 >                        DisplayHeight(ourdisplay,ourscreen) / 4))
193 >                error(SYSTEM, "insufficient memory for value storage");
194          odev.name = id;
195          odev.ifd = ConnectionNumber(ourdisplay);
188                                        /* set GLX context and clear buffers */
189        glXMakeCurrent(ourdisplay, gwind, gctx);
190        glEnable(GL_DEPTH_TEST);
191        glDepthFunc(GL_LEQUAL);
192        glShadeModel(GL_FLAT);
193        glDisable(GL_DITHER);
194        glDrawBuffer(GL_FRONT_AND_BACK);
195        glReadBuffer(GL_BACK);
196        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
197        setGLview();                    /* initialize view */
196   }
197  
198  
# Line 247 | Line 245 | register VIEW  *nv;
245                                  odev.vres = dh;
246                          }
247                          XResizeWindow(ourdisplay, gwind, odev.hres, odev.vres);
248 +                        dev_input();    /* get resize event */
249                  }
250                  copystruct(&odev.v, nv);
251                  setGLview();
252 +                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
253 +                redraw();
254          }
254        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
255        redraw();
255          return(1);
256   }
257  
# Line 277 | Line 276 | FVECT  p, v;
276   {
277          register int    li;
278  
279 <        li = newvalue();
279 >        li = rV.tl++;
280 >        if (rV.tl >= rV.nl)     /* get next leaf in ring */
281 >                rV.tl = 0;
282 >        if (rV.tl == rV.bl)     /* need to shake some free */
283 >                Compost(FREEPCT);
284          VCOPY(rV.wp[li], p);
285          rV.wd[li] = encodedir(v);
286          tmCvColrs(&rV.brt[li], rV.chr[li], c, 1);
# Line 331 | Line 334 | setGLview()                    /* set our GL view */
334                  return;
335          if (mindepth < maxdepth) {
336                  zmin = 0.25*mindepth;
337 <                zmax = 8.0*maxdepth;
337 >                zmax = 4.0*(1.+CONEH)*maxdepth;
338          } else {
339                  zmin = 0.01;
340                  zmax = 1000.;
# Line 379 | Line 382 | setGLview()                    /* set our GL view */
382   }
383  
384  
382 static int
383 newvalue()                      /* allocate a leaf from our pile */
384 {
385        int     li;
386        
387        li = rV.tl++;
388        if (rV.tl >= rV.nl)     /* get next leaf in ring */
389                rV.tl = 0;
390        if (rV.tl == rV.bl)     /* need to shake some free */
391                Compost(FREEPCT);
392        return(li);
393 }
394
395
385   static
386   drawvalue(li)                   /* draw a pixel value as a cone */
387   register int    li;
388   {
389 <        static FVECT    apex, disp;
390 <        double  d, h, v;
389 >        static FVECT    disp;
390 >        FVECT   apex;
391 >        double  d, dorg, dnew, h, v;
392          register int    i;
393 <                                        /* compute cone's base displacement */
394 <        VCOPY(apex, rV.wp[li]);
395 <        disp[0] = apex[0] - odev.v.vp[0];
396 <        disp[1] = apex[1] - odev.v.vp[1];
397 <        disp[2] = apex[2] - odev.v.vp[2];
398 <        if ((d = DOT(disp,odev.v.vdir)) <= odev.v.vfore || d <= FTINY)
399 <                return;
400 <        if (d > 1e5) {          /* background region */
401 <                if (odev.v.vaft > FTINY)
402 <                        return;
403 <                h = maxdepth/d;
404 <                disp[0] *= h; disp[1] *= h; disp[2] *= h;
405 <                apex[0] = odev.v.vp[0] + disp[0];
406 <                apex[1] = odev.v.vp[1] + disp[1];
407 <                apex[2] = odev.v.vp[2] + disp[2];
408 <                d = maxdepth;
409 <        } else if (d > maxdepth)
410 <                maxdepth = d;
411 <        h = DOT(disp,odev.v.hvec)/(d*odev.v.hn2);
412 <        v = DOT(disp,odev.v.vvec)/(d*odev.v.vn2);
413 <        if (fabs(h - odev.v.hoff) < 0.5 && fabs(v - odev.v.voff) < 0.5 &&
414 <                        d < mindepth)
415 < {
416 < fprintf(stderr, "min depth now %lf (%lf,%lf,%lf)\n", d, apex[0], apex[1], apex[2]);
417 <                mindepth = d;
418 < }
393 >                                /* compute cone coordinates */
394 >        disp[0] = rV.wp[li][0] - odev.v.vp[0];
395 >        disp[1] = rV.wp[li][1] - odev.v.vp[1];
396 >        disp[2] = rV.wp[li][2] - odev.v.vp[2];
397 >        dorg = DOT(disp,odev.v.vdir);
398 >        if (dorg <= odev.v.vfore)
399 >                return;         /* clipped too near */
400 >        if (odev.v.vaft > FTINY && dorg > odev.v.vaft)
401 >                return;         /* clipped too far */
402 >        if (dorg > 1e5) {       /* background pixel */
403 >                dnew = maxdepth;
404 >                d = dnew/dorg;
405 >        } else {                /* foreground pixel, compute penalty */
406 >                normalize(disp);
407 >                d = dnew = dorg + coneh*fdir2diff(rV.wd[li],disp)*DIRPEN;
408 >        }
409 >                                /* compute adjusted apex position */
410 >        disp[0] *= d; disp[1] *= d; disp[2] *= d;
411 >        apex[0] = odev.v.vp[0] + disp[0];
412 >        apex[1] = odev.v.vp[1] + disp[1];
413 >        apex[2] = odev.v.vp[2] + disp[2];
414 >                                /* compute view position and base offset */
415 >        h = DOT(disp,odev.v.hvec)/(dnew*odev.v.hn2);
416 >        v = DOT(disp,odev.v.vvec)/(dnew*odev.v.vn2);
417 >        if (fabs(h - odev.v.hoff) > 0.5 || fabs(v - odev.v.voff) > 0.5)
418 >                return;         /* clipped off screen */
419 >        if (dorg < mindepth)
420 >                mindepth = dorg;
421 >        if (dorg > maxdepth)
422 >                maxdepth = dorg;
423          for (i = 0; i < 3; i++)
424                  disp[i] = apex[i] + coneh*(h*odev.v.hvec[i] + v*odev.v.vvec[i]);
425 <                                        /* draw pyramid (cone approx.) */
425 >                                /* draw cone (pyramid approx.) */
426          glColor4ub(rV.rgb[li][0], rV.rgb[li][1], rV.rgb[li][2], rV.alpha[li]);
427          glBegin(GL_TRIANGLE_FAN);
428          glVertex3f(apex[0], apex[1], apex[2]);
429          for (i = 0; i < NCONEV; i++)
430                  glVertex3d(conev[i][0] + disp[0], conev[i][1] + disp[1],
431                                  conev[i][2] + disp[2]);
432 <                                        /* connect last side to first */
432 >                                /* connect last face to first */
433          glVertex3d(conev[0][0] + disp[0], conev[0][1] + disp[1],
434                          conev[0][2] + disp[2]);
435 <        glEnd();                        /* done */
435 >        glEnd();                /* done */
436   }
437  
438  
# Line 493 | Line 487 | FreeValues()                   /* free our allocated values */
487  
488  
489   static
490 + clralphas()                     /* prepare for new alpha values */
491 + {
492 +        if (!vmaplen)
493 +                return;
494 +        free((char *)valmap);
495 +        valmap = NULL;
496 +        vmaplen = 0;
497 + }
498 +
499 +
500 + static int
501 + valcmp(v1p, v2p)                /* compare two pixel values */
502 + int     *v1p, *v2p;
503 + {
504 +        register int    v1 = *v1p, v2 = *v2p;
505 +        register int    c;
506 +
507 +        if ((c = rV.rgb[v1][0] - rV.rgb[v2][0])) return(c);
508 +        if ((c = rV.rgb[v1][1] - rV.rgb[v2][1])) return(c);
509 +        if ((c = rV.rgb[v1][2] - rV.rgb[v2][2])) return(c);
510 +        return(rV.alpha[v1] - rV.alpha[v2]);
511 + }
512 +
513 +
514 + static
515 + mergalphas(adest, al1, n1, al2, n2)     /* merge two sorted alpha lists */
516 + register int    *adest, *al1, *al2;
517 + int     n1, n2;
518 + {
519 +        register int    cmp;
520 +
521 +        while (n1 | n2) {
522 +                if (!n1) cmp = 1;
523 +                else if (!n2) cmp = -1;
524 +                else cmp = valcmp(al1, al2);
525 +                if (cmp > 0) {
526 +                        *adest++ = *al2++;
527 +                        n2--;
528 +                } else {
529 +                        *adest++ = *al1++;
530 +                        n1--;
531 +                }
532 +        }
533 + }
534 +
535 +
536 + static
537 + setalphas(vbeg, nvals)          /* add values to our map and set alphas */
538 + int     vbeg, nvals;
539 + {
540 +        register int    *newmap;
541 +        short   ccmp[3], lastalpha;
542 +        int     newmaplen;
543 +
544 +        if (nvals <= 0)
545 +                return;
546 +        newmaplen = vmaplen + nvals;    /* allocate new map */
547 +        newmap = (int *)malloc(newmaplen*sizeof(int));
548 +        if (newmap == NULL)
549 +                error(SYSTEM, "out of memory in setalphas");
550 +        while (nvals--) {               /* add new values to end */
551 +                rV.alpha[vbeg] = 255;
552 +                newmap[vmaplen+nvals] = vbeg++;
553 +        }
554 +        if (nvals >= 3*vmaplen) {       /* resort the combined array */
555 +                while (vmaplen--)
556 +                        newmap[vmaplen] = valmap[vmaplen];
557 +                qsort((char *)newmap, newmaplen, sizeof(int), valcmp);
558 +        } else {                        /* perform merge sort */
559 +                qsort((char *)(newmap+vmaplen), newmaplen-vmaplen,
560 +                                sizeof(int), valcmp);
561 +                mergalphas(newmap, valmap, vmaplen,
562 +                                newmap+vmaplen, newmaplen-vmaplen);
563 +        }
564 +        if (valmap != NULL)             /* free old map and assign new one */
565 +                free((char *)valmap);
566 +        valmap = newmap;
567 +        vmaplen = newmaplen;
568 +        lastalpha = 0;                  /* set new alpha values */
569 +        ccmp[0] = ccmp[1] = ccmp[2] = 256;
570 +        while (newmaplen--)
571 +                if (rV.rgb[*newmap][0] == ccmp[0] &&
572 +                                rV.rgb[*newmap][1] == ccmp[1] &&
573 +                                rV.rgb[*newmap][2] == ccmp[2]) {
574 +                        if (lastalpha >= 255)
575 +                                newmap++;
576 +                        else if (rV.alpha[*newmap] < 255)
577 +                                lastalpha = rV.alpha[*newmap++];
578 +                        else
579 +                                rV.alpha[*newmap++] = ++lastalpha;
580 +                } else {
581 +                        ccmp[0] = rV.rgb[*newmap][0];
582 +                        ccmp[1] = rV.rgb[*newmap][1];
583 +                        ccmp[2] = rV.rgb[*newmap][2];
584 +                        if (rV.alpha[*newmap] < 255)
585 +                                lastalpha = rV.alpha[*newmap++];
586 +                        else
587 +                                rV.alpha[*newmap++] = lastalpha = 1;
588 +                }
589 + }
590 +
591 +
592 + static
593   TMapValues(redo)                /* map our values to RGB */
594   int     redo;
595   {
# Line 521 | Line 618 | int    redo;
618                          tmAddHisto(rV.brt+borg, blen, 1);
619                  if (tmComputeMapping(0., 0., 0.) != TM_E_OK)
620                          return(0);
621 <                rV.drl = rV.bl;
621 >                clralphas();            /* restart value list */
622 >                rV.drl = rV.bl;         /* need to redraw */
623          }
624          if (tmMapPixels(rV.rgb+aorg, rV.brt+aorg,
625                          rV.chr+aorg, alen) != TM_E_OK)
# Line 529 | Line 627 | int    redo;
627          if (blen > 0)
628                  tmMapPixels(rV.rgb+borg, rV.brt+borg,
629                                  rV.chr+borg, blen);
630 <                                        /* compute unique alpha values */
631 <        rV.tml = rV.tl;
630 >        setalphas(aorg, alen);          /* compute add'l alpha values */
631 >        if (blen > 0)
632 >                setalphas(borg, blen);
633 >        rV.tml = rV.tl;                 /* we're all up to date */
634          return(1);
635   }
636  
# Line 547 | Line 647 | int    pct;
647          nclear -= rV.nl - nused;
648          if (nclear <= 0)
649                  return(0);
650 <        if (nclear >= nused) {  /* clear them all */
650 >        if (nclear >= nused) {  /* clear them all? */
651                  rV.drl = rV.tml = rV.bl = rV.tl = 0;
652                  return(nused);
653          }
# Line 603 | Line 703 | register FVECT wp[2];
703   static
704   draw_grids()                    /* draw holodeck section grids */
705   {
706 <        static GLubyte  gridrgba[4] = {0x0, 0xff, 0xff, 0x00};
706 >        static BYTE     gridrgba[4] = {0x0, 0xff, 0xff, 0x00};
707  
708          if (!mapped)
709                  return;
# Line 616 | Line 716 | draw_grids()                   /* draw holodeck section grids */
716  
717  
718   static int
719 + IndexValue(rgba)                /* locate a pixel by it's framebuffer value */
720 + register BYTE   rgba[4];
721 + {
722 +        register int    *vp;
723 +                                        /* check legality */
724 +        if (rgba[3] == 0 || rgba[3] == 255)
725 +                return(-1);
726 +                                        /* borrow a value slot */
727 +        rV.rgb[rV.tl][0] = rgba[0];
728 +        rV.rgb[rV.tl][1] = rgba[1];
729 +        rV.rgb[rV.tl][2] = rgba[2];
730 +        rV.alpha[rV.tl] = rgba[3];
731 +                                        /* find it */
732 +        vp = (int *)bsearch((char *)&rV.tl, (char *)valmap, vmaplen,
733 +                        sizeof(int), valcmp);
734 +        if (vp == NULL)
735 +                return(-1);
736 +        return(*vp);
737 + }
738 +
739 +
740 + static int
741   FindValue(dx, dy)               /* find a value on the display */
742   int     dx, dy;
743   {
744 <        return(-1);             /* not found */
744 >        BYTE    rgba[4];
745 >
746 >        if (dx < 0 || dy < 0 || dx >= odev.hres || dy >= odev.vres)
747 >                return(-1);
748 >        glReadPixels(dx, dy, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
749 >        return(IndexValue(rgba));
750   }
751  
752  
# Line 702 | Line 829 | XButtonPressedEvent    *ebut;
829                  wx = levptr(XButtonReleasedEvent)->x;
830                  wy = levptr(XButtonReleasedEvent)->y;
831                  moveview(wx, odev.vres-1-wy, movdir, movorb);
832 +        } else {
833 +                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
834 +                redraw();
835          }
836          dev_flush();
837   }
# Line 739 | Line 869 | register XKeyPressedEvent  *ekey;
869                  return;
870          case CTRL('R'):                 /* redraw screen */
871                  TMapValues(1);
872 +                glClear(GL_DEPTH_BUFFER_BIT);
873                  redraw();
874                  return;
875          case CTRL('L'):                 /* refresh from server */
876                  if (inpresflags & DFL(DC_REDRAW))
877                          return;
878                  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
748                glDrawBuffer(GL_FRONT);
879                  glDisable(GL_DEPTH_TEST);
880                  draw_grids();
881                  glEnable(GL_DEPTH_TEST);
752                glDrawBuffer(GL_FRONT_AND_BACK);
882                  glFlush();
883                  Compost(100);                   /* get rid of old values */
884                  inpresflags |= DFL(DC_REDRAW);  /* resend values from server */
# Line 777 | Line 906 | static
906   fixwindow(eexp)                         /* repair damage to window */
907   register XExposeEvent  *eexp;
908   {
909 <        if (odev.hres == 0 || odev.vres == 0) { /* first exposure */
910 <                odev.hres = eexp->width;
782 <                odev.vres = eexp->height;
783 <        }
909 >        if (odev.hres == 0 || odev.vres == 0)   /* first exposure */
910 >                resizewindow((XConfigureEvent *)eexp);
911          if (eexp->width == odev.hres && eexp->height == odev.vres)
912                  TMapValues(1);
913 <        if (!eexp->count)
913 >        if (!eexp->count) {
914 >                glClear(GL_DEPTH_BUFFER_BIT);
915                  redraw();
916 +        }
917   }
918  
919  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines