// set up the graphics on the seperate CAVE displays
void CaveDisplayDevice::cave_gl_init_fn(void) {
  setup_initial_opengl_state();     // do all OpenGL setup/initialization now

  // follow up with mode settings
  aaAvailable = TRUE;               // enable antialiasing
  cueingAvailable = FALSE;          // disable depth cueing
  cullingAvailable = FALSE;         // disable culling 
  // XXX need to test this still
  // ext->hasstereo = CAVEInStereo();  // stereo availability test
  ext->hasstereo = TRUE;            // stereo is on initially
  ext->stereodrawforced = FALSE;    // no need for forced stereo draws
 
  glClearColor(0.0, 0.0, 0.0, 0.0); // set clear color to black

  aa_on();                          // force antialiasing on if possible
  cueing_off();                     // force depth cueing off

  // set default settings 
  set_sphere_mode(sphereMode);
  set_sphere_res(sphereRes);
  set_line_width(lineWidth);
  set_line_style(lineStyle);

  clear();                          // clear screen
  update();                         // swap buffers

  // we want the CAVE to be centered at the origin, and in the range -1, +1
  (transMat.top()).translate(0.0, 3.0, -2.0);
  (transMat.top()).scale(VMD_PI);

  doneGLInit = TRUE;                // only do this once
}
// init ... open a window and set initial default values
int OpenGLDisplayDevice::init(int argc, char **argv, VMDApp *app, int *size, int *loc) {
  vmdapp = app; // save VMDApp handle for use by drag-and-drop handlers

  // open the window
  if (open_window(name, size, loc, argc, argv) != 0) return FALSE;
  if (!have_window) return FALSE;

  // get screen size 
  // XXX There's no Win32 API to get the full multi-monitor desktop,
  //     so this code doesn't correctly handle multi-monitor systems yet.
  //     To correctly handle multiple monitors, we'd have to 
  //     walk the device tree, take into account monitor layout/positioning, 
  //     and compute the desktop dimensions from that.  Since these values
  //     are currently only used by do_reposition_window() method, we can
  //     live with primary-monitor values for the time being.
  screenX = GetSystemMetrics(SM_CXSCREEN);
  screenY = GetSystemMetrics(SM_CYSCREEN);

  // set flags for the capabilities of this display
  ext->hasmultisample = FALSE;      // no code for this extension yet
  ext->nummultisamples = 0;
  aaAvailable = FALSE;

  // set default settings
  if (ext->hasmultisample) {
    aa_on();  // enable fast multisample based antialiasing by default
              // other antialiasing techniques are slow, so only multisample
              // makes sense to enable by default.
  }

  cueingAvailable = TRUE;
  cueing_on(); // leave depth cueing on by default, despite the speed hit.

  cullingAvailable = TRUE;
  culling_off();

  set_sphere_mode(sphereMode);
  set_sphere_res(sphereRes);
  set_line_width(lineWidth);
  set_line_style(lineStyle);

  // reshape and clear the display, which initializes some other variables
  reshape();
  normal();
  clear();
  update();

  // successfully created window
  return TRUE;
}
int OpenGLPbufferDisplayDevice::init(int argc, char **argv, VMDApp *app, int *size, int *loc) {
  vmdapp = app; // save VMDApp handle for use by drag-and-drop handlers
                // and GPU memory management routines

  // open the window
  glxsrv.windowID = open_window(name, size, loc, argc, argv);
  if (!have_window) return FALSE;

  // set flags for the capabilities of this display
  // whether we can do antialiasing or not.
  if (ext->hasmultisample) 
    aaAvailable = TRUE;  // we use multisampling over other methods
  else
    aaAvailable = FALSE; // no non-multisample implementation yet

  // set default settings
  if (ext->hasmultisample) {
    aa_on();  // enable fast multisample based antialiasing by default
              // other antialiasing techniques are slow, so only multisample
              // makes sense to enable by default.
  } 

  cueingAvailable = TRUE;
  cueing_on(); // leave depth cueing on by default, despite the speed hit.

  cullingAvailable = TRUE;
  culling_off();

  set_sphere_mode(sphereMode);
  set_sphere_res(sphereRes);
  set_line_width(lineWidth);
  set_line_style(lineStyle);

  // reshape and clear the display, which initializes some other variables
  reshape();
  normal();
  clear();
  update();

  // We have a window, return success.
  return TRUE;
}
int OpenGLDisplayDevice::init(int argc, char **argv, VMDApp* app, int *size, int *loc) {

  // open the window
  sdlsrv.windowID = open_window(name, size, loc, argc, argv);
  if (!have_window) return FALSE;

  // set flags for the capabilities of this display
  // whether we can do antialiasing or not.
  if (ext->hasmultisample) 
    aaAvailable = TRUE;  // we use multisampling over other methods
  else
    aaAvailable = FALSE; // no non-multisample implementation yet

  cueingAvailable = TRUE;
  cullingAvailable = TRUE;
  cullingEnabled = FALSE;

  // set default settings
  if (ext->hasmultisample) {
    aa_on();  // enable fast multisample based antialiasing by default
              // other antialiasing techniques are slow, so only multisample
              // makes sense to enable by default.
  } 
  cueing_off(); // leave depth cueing off by default, since its a speed hit.

  set_sphere_mode(sphereMode);
  set_sphere_res(sphereRes);
  set_line_width(lineWidth);
  set_line_style(lineStyle);

  // reshape and clear the display, which initializes some other variables
  reshape();
  normal();
  clear();
  update();

  // successfully opened window.
  return TRUE;
}
Example #5
0
void PSDisplayDevice::render(const VMDDisplayList *display_list) {
   DepthSortObject depth_obj;
   char *cmd_ptr;
   int draw;
   int tok;
   int nc;
   float a[3], b[3], c[3], d[3];
   float cent[3];
   float r;
   Matrix4 ident;
   float textsize=1.0f; // default text size

   // first we want to clear the transformation matrix stack
   while (transMat.num())
      transMat.pop();

   // push on the identity matrix
   transMat.push(ident);

   // load the display list's transformation matrix
   super_multmatrix(display_list->mat.mat);

   // Now we need to calculate the normalized position of the light
   // so we can compute angles of surfaces to that light for shading
   norm_light[0] = lightState[0].pos[0];
   norm_light[1] = lightState[0].pos[1];
   norm_light[2] = lightState[0].pos[2];
   if (norm_light[0] || norm_light[1] || norm_light[2])
      vec_normalize(norm_light);

   // Computer periodic images
   ResizeArray<Matrix4> pbcImages;
   find_pbc_images(display_list, pbcImages);
   int nimages = pbcImages.num();

   for (int pbcimage = 0; pbcimage < nimages; pbcimage++) {
     transMat.dup();
     super_multmatrix(pbcImages[pbcimage].mat);

   // Loop through the display list and add each object to our
   // depth-sort list for final rendering.
   VMDDisplayList::VMDLinkIter cmditer;
   display_list->first(&cmditer);
   while ((tok = display_list->next(&cmditer, cmd_ptr)) != DLASTCOMMAND) {
      draw = 0;
      nc = -1;

      switch (tok) {
         case DPOINT:
            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 2);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 1;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
            memcpy(depth_obj.points, a, sizeof(float) * 2);

            // compute the distance to the eye
            depth_obj.dist = compute_dist(a);

            // valid object to depth sort
            draw = 1;
            break;

         case DSPHERE:
         {
            (transMat.top()).multpoint3d(((DispCmdSphere *) cmd_ptr)->pos_r, c);
            r = scale_radius(((DispCmdSphere *) cmd_ptr)->pos_r[3]);

            sphere_approx(c, r);
            break;
         }

         case DSPHEREARRAY:
         {
            DispCmdSphereArray *sa = (DispCmdSphereArray *) cmd_ptr;
            int cIndex, rIndex; // cIndex: index of colors & centers
                                // rIndex: index of radii.
            float * centers;
            float * radii;
            float * colors;
            sa->getpointers(centers, radii, colors);

            set_sphere_res(sa->sphereres);

            for (cIndex = 0, rIndex=0; rIndex < sa->numspheres; 
                 cIndex+=3, rIndex++)
            {
                colorIndex = nearest_index(colors[cIndex],
                                           colors[cIndex+1],
                                           colors[cIndex+2]);
                (transMat.top()).multpoint3d(&centers[cIndex] , c);
                r = scale_radius(radii[rIndex]);

                sphere_approx(c, r);
            }

            break;
         }   

         case DLINE:
            // check for zero-length line (degenerate)
            if (!memcmp(((DispCmdLine *) cmd_ptr)->pos1,
                        ((DispCmdLine *) cmd_ptr)->pos2,
                        sizeof(float) * 3)) {
               // degenerate line
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 4);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 2;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos2, b);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0]) / 2;
            cent[1] = (a[1] + b[1]) / 2;
            cent[2] = (a[2] + b[2]) / 2;

            // compute the distance to the eye
            depth_obj.dist = compute_dist(cent);

            // valid object to depth sort
            draw = 1;
            break;

         case DLINEARRAY:
           {
            // XXX much replicated code from DLINE
            float *v = (float *)cmd_ptr;
            int nlines = (int)v[0];
            v++;
            for (int i=0; i<nlines; i++) {
              // check for degenerate line
              if (!memcmp(v,v+3,3*sizeof(float)))
                break;

              // allocate memory
              depth_obj.points = (float *) malloc(sizeof(float) * 4);
              if (!depth_obj.points) {
                 // memory error
                 if (!memerror) {
                    memerror = 1;
                    msgErr << "PSDisplayDevice: Out of memory. Some " <<
                       "objects were not drawn." << sendmsg;
                 }
                 break;
              }

              // copy data
              depth_obj.npoints = 2;
              depth_obj.color = colorIndex;
              (transMat.top()).multpoint3d(v, a);
              (transMat.top()).multpoint3d(v+3, b);
              memcpy(depth_obj.points, a, sizeof(float) * 2);
              memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
  
              // compute the centerpoint of the object
              cent[0] = (a[0] + b[0]) / 2;
              cent[1] = (a[1] + b[1]) / 2;
              cent[2] = (a[2] + b[2]) / 2;
  
              // compute the distance to the eye
              depth_obj.dist = compute_dist(cent);
 
              // we'll add the object here, since we have multiple objects 
              draw = 0;
              memusage += sizeof(float) * 2 * depth_obj.npoints;
              points += depth_obj.npoints;
              objects++;
              depth_list.append(depth_obj);

              v += 6;
            } 
           }
           break;           

         case DPOLYLINEARRAY:
           {
            // XXX much replicated code from DLINE / DLINEARRAY
            float *v = (float *)cmd_ptr;
            int nverts = (int)v[0];
            v++;
            for (int i=0; i<nverts-1; i++) {
              // check for degenerate line
              if (!memcmp(v,v+3,3*sizeof(float)))
                break;

              // allocate memory
              depth_obj.points = (float *) malloc(sizeof(float) * 4);
              if (!depth_obj.points) {
                 // memory error
                 if (!memerror) {
                    memerror = 1;
                    msgErr << "PSDisplayDevice: Out of memory. Some " <<
                       "objects were not drawn." << sendmsg;
                 }
                 break;
              }

              // copy data
              depth_obj.npoints = 2;
              depth_obj.color = colorIndex;
              (transMat.top()).multpoint3d(v, a);
              (transMat.top()).multpoint3d(v+3, b);
              memcpy(depth_obj.points, a, sizeof(float) * 2);
              memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
  
              // compute the centerpoint of the object
              cent[0] = (a[0] + b[0]) / 2;
              cent[1] = (a[1] + b[1]) / 2;
              cent[2] = (a[2] + b[2]) / 2;
  
              // compute the distance to the eye
              depth_obj.dist = compute_dist(cent);
 
              // we'll add the object here, since we have multiple objects 
              draw = 0;
              memusage += sizeof(float) * 2 * depth_obj.npoints;
              points += depth_obj.npoints;
              objects++;
              depth_list.append(depth_obj);

              v += 3;
            } 
           }
           break;           
 
         case DCYLINDER:
         {
            int res;

            (transMat.top()).multpoint3d((float *) cmd_ptr, a);
            (transMat.top()).multpoint3d(&((float *) cmd_ptr)[3], b);
            r = scale_radius(((float *) cmd_ptr)[6]);
            res = (int) ((float *) cmd_ptr)[7];

            cylinder_approx(a, b, r, res, (int) ((float *) cmd_ptr)[8]);
            break;
         }

         case DCONE:
         {
            (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos2, b);
            float r1 = scale_radius(((DispCmdCone *) cmd_ptr)->radius);
            float r2 = scale_radius(((DispCmdCone *) cmd_ptr)->radius2);

            // XXX current implementation can't draw truncated cones.
            if (r2 > 0.0f) {
              msgWarn << "PSDisplayDevice) can't draw truncated cones" 
                      << sendmsg;
            }
            cone_approx(a, b, r1);
            break;
         }

        case DTEXTSIZE:
          textsize = ((DispCmdTextSize *)cmd_ptr)->size;
          break;

        case DTEXT:
        {
            float* pos = (float *)cmd_ptr;
#if 0
            // thickness not implemented yet
            float thickness = pos[3];    // thickness is stored in 4th slot
#endif
            char* txt = (char *)(pos+4);
            int   txtlen = strlen(txt);
            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 2);
            depth_obj.text   = (char  *) malloc(sizeof(char) * (txtlen+1));
            if ( !(depth_obj.points || depth_obj.text) ) {
              // memory error
              if (!memerror) {
                 memerror = 1;
                 msgErr << "PSDisplayDevice: Out of memory. Some " <<
                    "objects were not drawn." << sendmsg;
              }
              break;
           }

            // copy data
            depth_obj.npoints = 1;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            strcpy(depth_obj.text , txt);

            // note scale factor, stored into "light_scale", so we didn't
            // have to add a new structure member just for this.
            depth_obj.light_scale = textsize * 15;

            // compute the distance to the eye
            depth_obj.dist = compute_dist(a);

            // valid object to depth sort
            draw = 1;
            break;
         }

         case DTRIANGLE:
            // check for degenerate triangle
            if (!memcmp(((DispCmdTriangle *) cmd_ptr)->pos1,
                        ((DispCmdTriangle *) cmd_ptr)->pos2,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
                        ((DispCmdTriangle *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
                        ((DispCmdTriangle *) cmd_ptr)->pos3,
                        sizeof(float) * 3)) {
               // degenerate triangle
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 6);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 3;
            depth_obj.color = (nc >= 0) ? nc : colorIndex;
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos2, b);
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos3, c);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], c, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0] + c[0]) / 3;
            cent[1] = (a[1] + b[1] + c[1]) / 3;
            cent[2] = (a[2] + b[2] + c[2]) / 3;

            // compute the distance to the eye for depth sorting
            depth_obj.dist = compute_dist(cent);

            // compute a light shading factor
            depth_obj.light_scale = compute_light(a, b, c);

            // valid object to depth sort
            draw = 1;
            break;

         case DTRIMESH_C4F_N3F_V3F:
            // call a separate routine to break up the mesh into
            // its component triangles
            decompose_mesh((DispCmdTriMesh *) cmd_ptr);
            break;

         case DTRISTRIP:
            // call a separate routine to break up the strip into
            // its component triangles
            decompose_tristrip((DispCmdTriStrips *) cmd_ptr);
            break;

         case DSQUARE:
            // check for degenerate quadrilateral
            if (!memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos2,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
                        ((DispCmdSquare *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos3,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3)) {
               // degenerate quadrilateral
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 8);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 4;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos2, b);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos3, c);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos4, d);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], c, sizeof(float) * 2);
            memcpy(&depth_obj.points[6], d, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0] + c[0] + d[0]) / 4;
            cent[1] = (a[1] + b[1] + c[1] + d[1]) / 4;
            cent[2] = (a[2] + b[2] + c[2] + d[2]) / 4;

            // compute the distance to the eye for depth sorting
            depth_obj.dist = compute_dist(cent);

            // compute a light shading factor
            depth_obj.light_scale = compute_light(a, b, c);

            // valid object to depth sort
            draw = 1;
            break;

         case DCOLORINDEX:
            colorIndex = ((DispCmdColorIndex *) cmd_ptr)->color;
            break;

         case DSPHERERES:
            set_sphere_res(((int *) cmd_ptr)[0]);
            break;

         default:
            // unknown object, so just skip it
            break;
      }

      // if we have a valid object to add to the depth sort list
      if (draw && depth_obj.npoints) {
         memusage += sizeof(float) * 2 * depth_obj.npoints;
         if ( depth_obj.text )
           memusage += sizeof(char) * (1+strlen(depth_obj.text));
         points += depth_obj.npoints;
         objects++;
         depth_list.append(depth_obj);
      }

      depth_obj.npoints = 0;
      depth_obj.points = NULL;

   } // while (tok != DLASTCOMMAND)

     transMat.pop();
   } // end for() [periodic images]
}
// constructor ... open a window and set initial default values
FltkOpenGLDisplayDevice::FltkOpenGLDisplayDevice(int argc, char **argv, 
  VMDApp *vmdapp_p, int *size, int *loc)
    : OpenGLRenderer((char *) "VMD " VMDVERSION " OpenGL Display") {

  vmdapp = vmdapp_p; // save VMDApp handle for use by drag-and-drop handlers, 
                     // and GPU memory management routines

  // set up data possible before opening window
  stereoNames = glStereoNameStr;
  stereoModes = OPENGL_STEREO_MODES;

  // GLSL is only available on MacOS X 10.4 and later.
  renderNames = glRenderNameStr;
  renderModes = OPENGL_RENDER_MODES;

  cacheNames = glCacheNameStr;
  cacheModes = OPENGL_CACHE_MODES;

  // open the window
  int SX = 100, SY = 100, W, H;

  W = size[0];
  H = size[1];
  if (loc) {
    SX = loc[0];
    SY = loc[1];
  }
  window = new myglwindow(SX, SY, W, H, name, this, vmdapp_p);

  ext->hasstereo = FALSE;         // stereo is off initially
  ext->stereodrawforced = FALSE;  // stereo not forced initially
  ext->hasmultisample = FALSE;    // multisample is off initially

  int rc=0;
// FLTK stereo support only started working for MacOS X at around version 1.1.7
#if (FL_MAJOR_VERSION >= 1) && (((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)) || ((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)))
  // find an appropriate visual and colormap ...
  if (getenv("VMDPREFERSTEREO") != NULL) {
    // Stereo limps along with FLTK 1.1.7 on MacOS X
    rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_STEREO);
    ext->hasstereo = TRUE;
#if defined(__APPLE__)
    ext->stereodrawforced = TRUE; // forced draw in stereo all the time when on
#endif
  // FLTK multisample antialiasing still doesn't actually work in 
  // MacOS X as of FLTK 1.1.10...
#if !defined(__APPLE__)
  //  } else if (getenv("VMDPREFERMULTISAMPLE") != NULL) {
  } else if (rc != 0) {
    rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_MULTISAMPLE);
    ext->hasmultisample = TRUE; // FLTK only does SGI multisample, no ARB yet
#endif
  } else {
    rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
  }
#else
  // find an appropriate visual and colormap ...
  rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
#endif

  window->show();
  // (7) bind the rendering context to the window
  window->make_current();

  // (8) actually request the window to be displayed
  screenX = Fl::w();
  screenY = Fl::h();  

  // (9) configure the rendering properly
  setup_initial_opengl_state();  // setup initial OpenGL state
  
  // set flags for the capabilities of this display
  // whether we can do antialiasing or not.
  if (ext->hasmultisample) 
    aaAvailable = TRUE;  // we use multisampling over other methods
  else
    aaAvailable = FALSE; // no non-multisample implementation yet

  // set default settings
  if (ext->hasmultisample) {
    aa_on();  // enable fast multisample based antialiasing by default
              // other antialiasing techniques are slow, so only multisample
              // makes sense to enable by default.
  } 

  cueingAvailable = TRUE;
  cueing_on(); // leave depth cueing on by default, despite the speed hit.

  cullingAvailable = TRUE;
  culling_off();

  set_sphere_mode(sphereMode);
  set_sphere_res(sphereRes);
  set_line_width(lineWidth);
  set_line_style(lineStyle);

  // reshape and clear the display, which initializes some other variables
  reshape();
  normal();
  clear();
  update();
}