PDA

View Full Version : Problem with gluProject



Roach
04-22-2003, 04:25 AM
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!




Globe3d::draw()
{

// screen clear. We want this even if we aren't going
// to paint anything else.
//
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);

if (!attributes_.isHidden_) {

// now do the globe work. First push the matrix on
//the stack
glPushMatrix();


// move it to where it should be - note these values change
glTranslatef(attributes_.currentPos_.x_,
attributes_.currentPos_.y_,
attributes_.zoomDist_);

// 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
glRotatef(attributes_.yRotation_.measuredIn(degree ),
1.0, 0.0, 0.0);
glRotatef(attributes_.xRotation_.measuredIn(degree ),
0.0, 1.0, 0.0);

// if the globe needs to be created again
//
if (attributes_.createGlobeDisplayList_) {
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);
glEnable(GL_POLYGON_OFFSET_FILL);

// enable the texture
glEnable(GL_TEXTURE_2D);

// call the display list that contains the earth
glCallList(attributes_.globeDisplayList_);

//nothing else should have a texture
//
glDisable(GL_TEXTURE_2D);

//
// 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
GlobeError::OpenGLError(ARCH_LOCATION);

//
// 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, &amp;globeWinX,
&amp;globeWinY,
&amp;globeWinZ);


glDisable(GL_POLYGON_OFFSET_FILL);

// check and report for any errors
GlobeError::OpenGLError(ARCH_LOCATION);

// 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
//
glPopMatrix();
}

// 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.
glFinish();

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


// make sure this is done drawing before leaving
glXWaitGL();

// check and report for any errors
GlobeError::OpenGLError(ARCH_LOCATION);

}

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);
glEnable(GL_POLYGON_OFFSET_LINE);

glColor3dv(GLOBE_LAUNCH_COLOR);

// set line width of the launch platforms.
glLineWidth(1.0);

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
GlobeError::OpenGLError(ARCH_LOCATION);

// 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];
launchDisplay_[i].xyzVector(vec);

//
// 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, &amp;platformWinX,
&amp;platformWinY,
&amp;platformWinZ);

// check and report for any errors
GlobeError::OpenGLError(ARCH_LOCATION);

// Disable the depth testing for the labels
glDisable(GL_DEPTH_TEST);

//
// 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.
//
glPushMatrix();
glTranslated(vec[0], vec[1], vec[2]);

// make sure the inner and outer radius are
// the same.
gluDisk(launchPlatform, launchPlatformRadius,
launchPlatformRadius, 60, 2);


gluDeleteQuadric(launchPlatform);
glPopMatrix();
}

glEnable(GL_DEPTH_TEST);

} // end of (if (launchPlatform != 0)

} // end of for

glDisable(GL_POLYGON_OFFSET_LINE);

// check and report for any errors
GlobeError::OpenGLError(ARCH_LOCATION);

}
}