Problem with gluProject

Hey gang,
Got a small problem here - and am looking for some advice on what to do (cause I am stumped). Here’s the situation - I have a Globe made with a gluSphere and I need to put “overlays” on it, such as little dots and little circles (to define certain locations on the globe).

Anyways - to place these things on the globe, what I am doing is disabling the Depth Test and using gluProgect to get the window coordinates for both the globe and the circles or dots that I am trying to place on them. I am then comparing the Z window coordinate to see if the circle and/or dot is visible to the user or not (if it’s behind the globe - don’t draw it).

Now - I seem to be at a good starting point - because this works (well most of the time). But I do have a slight problem - it seems that gluProject is not accurate enough, (Or more likely I am doing something wrong) and some of the dots and circles draw when they should be behind the globe. (For example - you can see a circle in cape cod bay - but in all actuality - it’s some place in central Europe, which at this time is on the other side of the visible globe.) If I keep rotating though - the circles then stop drawing (as they should). So it seems to me that I am off by a tiny factor in my calculations. . .

Here’s some code!


// screen clear. We want this even if we aren’t going
// to paint anything else.

if (!attributes_.isHidden_) {

  // now do the globe work.  First push the matrix on 
  //the stack

  // move it to where it should be - note these values change
  // set the pixel zoom where 1.0 is no zoom.  
  // This is for drawing text
  double pixelZoom = attributes_.zoomDist_/280.0;
  if (pixelZoom < 0) {
     pixelZoom = pixelZoom * -1;
  glPixelZoom(pixelZoom, pixelZoom);
  glPolygonOffset(1.0, 1.0);
  // because we are rotating the globe by 90, the x and y
  // rotation need to be on the other axis
            1.0, 0.0, 0.0);
            0.0, 1.0, 0.0);
  // if the globe needs to be created again
  if (attributes_.createGlobeDisplayList_) {

  // We are enabling Polygon Offsetting to help eliminate
  // Z fighting of the overlays that come close to or are
  // directly on top of the globe's surface.
  glPolygonMode(GL_FRONT, GL_FILL);
  // enable the texture
  // call the  display list that contains the earth
  //nothing else should have a texture

  // For gluProject - we need to get the current projection
  // matrix, current viewport matrix, and current viewport. 
  // We will use glGet functions to query the graphics 
  // hardware on what these values are.
  GLdouble modelMatrix[16];
  GLdouble projectionMatrix[16];
  GLint viewport[4];

  // Use the glGet functions to query the graphics hardware
  // for the current matrices and viewport.
  glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
  glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
  glGetIntegerv(GL_VIEWPORT, viewport);
  // check and report for any errors

  // These will be the window coordinates for the Globe. 
  // In this case
  // all we really need is the Z window coordinate, 
  // as we will compare
  // the globeZ value with the winZ value.
  GLdouble globeWinX;
  GLdouble globeWinY;
  GLdouble globeWinZ;

  // Get the window coordiates for the globe. 
  // Note that we are using
  // 0, 0, 0 as object coordinates for the globe because 
  // the globe's
  // object coordinates are represented in the 
  // current matrices that
  // we are passing in. We only actualy care about 
  // the Z window 
  // coordinates as we will be compareing the labelWinZ with the
  // globeWinZ to see if we need to draw the current label.
  gluProject(0, 0, 0, modelMatrix,
             projectionMatrix, viewport, &globeWinX, 
  // check and report for any errors

  // now draw all of the overlays.  They are to be drawn in a
  // specific order which follows.
  // We are passing in the matrixs and the
  // globe window coordinates to the overlays so that 
  // they can compare
  // their window coordinates with the 
  // globe's window coordinates and
  // do depth testing manually. We manually do depth 
  // testing on the
  // overlays that deal with labels that might 
  // curve into the earth
  // (such as tracks and threat regions). 
  // The matrixs and viewport
  // are also passed in so that the overlays can use 
  // the gluProject method.
  // the gluProject method converts object coordinates to
  // window coordinates.  Because the calls to get 
  // the matrixs
  // (using glGet) are expensive, we only want to do 
  // these once. 
  // first the tracks
  drawTracks(modelMatrix, projectionMatrix, viewport, globeWinX,  globeWinY, globeWinZ);

// this matrix pop is for the general “move the earth to the right place”
// matrix push

// While glXSwapBuffers will call a glFlush before it
// swaps the buffers, we want to make sure that all the
// openGL calls are finished before we swap the bufffers.

// this pushes all the information out of the
// back buffer onto the screen
glXSwapBuffers(display_, window_);

// make sure this is done drawing before leaving

// check and report for any errors


void drawTracks(GLdouble modelviewMatrix[16],
GLdouble projectionMatrix[16], GLint viewport[4],
GLdouble globeWinX, GLdouble globeWinY,
GLdouble globeWinZ)
// enable polygon offsetting for Lines.
glPolygonMode(GL_FRONT, GL_LINE);

  // set line width of the launch platforms.
  for (int i = 0; i < launchDisplay_.size(); ++i) {
     // we will use a gluQuadric Disk to draw the
     // circles for the Launch Platforms.
     GLUquadricObj *launchPlatform = gluNewQuadric();
     // check and report error status
     // if the quadric did get created
     if (launchPlatform != 0) {
        gluQuadricDrawStyle(launchPlatform, GLU_LINE);
        // should be based on range of probibility - TBD
        int launchPlatformRadius = 1;
        double vec[3];

        // These will be the window coordinates for the 
        //launch platforms.
        // The window coordinates are the "true" X, Y, 
        // and Z values (i.e. actual pixel values)
        GLdouble platformWinX;
        GLdouble platformWinY;
        GLdouble platformWinZ;
        // Get the window coordinates for the launch 
        // platforms. We use
        // the object coordinates for the current launch 
        // platform to get
        // the proper window coordinates. We only actually
        //care about the Z window coordinates as we will be 
        // compareing the paltformWinZ with the globeWinZ 
        // to see if we need to draw the current label.
        gluProject(vec[0], vec[1], vec[2], modelMatrix,
                   projectionMatrix, viewport, &platformWinX,
        // check and report for any errors

        // Disable the depth testing for the labels
        // Compare the platform Z values with the Globe Z
        // values. The lower the Z value, the closer the 
        // object is to the eye. If the platform Z value is
        // less than the Globe Z value, we then draw
        // the launch platform. If not don't draw anything.
        if (platformWinZ  < globeWinZ)
           // glPushMatrix/glPopMatrix is needed around
           // this code
           // because the translate affects the matrix.
           glTranslated(vec[0], vec[1], vec[2]);
           // make sure the inner and outer radius are 
           // the same.
           gluDisk(launchPlatform, launchPlatformRadius,
                   launchPlatformRadius, 60, 2);
     } // end of (if (launchPlatform != 0) 
  } // end of for

  // check and report for any errors