Hi gang,
I’m having a little problem with a gluSphere (actually a globe) distorting when positioned in the corners of the screen. All I am really doing is preforming a glTranslatef call to move the globe from the center of the screen, shrink it, and then move it to the new x, y position. I set the viewport with glViewport(0, 0,
static_cast(globeFormWidth_),
static_cast(globeFormHeight_));
Any ideas? Here is some code:
/////////////////////////////////////////////////////////////
// Method: draw_i
//
// Purpose: the real draw
//
// Notes: caller holds application and OpenGL lock
//
void
DcGui_Impl::Globe3d::draw_i()
{
// clear the buffer and the depth buffer. This will paint the
// screen clear. We want this even if we aren’t going to paint
// anything else.
//
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
if (!attributes_.isHidden_) {// first determine the density and set hi/low determineDensity(); // now do the globe work. First push the matrix on the stack // glPushMatrix(); // move it to where it should be 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); glPushMatrix(); // 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); // 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); glPopMatrix(); // now have all the overlays draw for (int i = 0; i < DcGui_Impl::GLOBE_OVERLAY_TOTAL; i++) { glPushMatrix(); //repeat the rotates. Popping the // matrix before removed all the rotates and other translations // glRotatef(attributes_.yRotation_.measuredIn(degree), 1.0, 0.0, 0.0); glRotatef(attributes_.xRotation_.measuredIn(degree), 0.0, 1.0, 0.0); // now draw the overlay. Each overlay determines if it should draw // and does the right thing // attributes_.overlays_[i]->draw(); // pop the matrix so previous colors/rotations/translations/etc // do not affect the next overlay // glPopMatrix(); } // this matrix pop is for the general "move the earth to the right place" // matrix push // glPopMatrix();
}
// 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);}
/////////////////////////////////////////////////////////
// Method: createGlobeDisplayList
//
// Purpose: Create the display list that contains the globe
// and the textures. This should only happen at startup
// and when the globe’s radius is changed (set to “out of
// the way” position")
//
// Notes: caller holds application and (if not in initialization) openGL
// locks
//
void
DcGui_Impl::Globe3d::createGlobeDisplayList()
{
// first delete the existing list
//
if (attributes_.globeDisplayList_ != 0) {
glDeleteLists(attributes_.globeDisplayList_, 1);
}// now generate a new one
attributes_.globeDisplayList_ = glGenLists(1);// as long as we were able to create the list, populate it with
// the globe data
if (attributes_.globeDisplayList_ != 0) {
glNewList(attributes_.globeDisplayList_, GL_COMPILE);
glPushMatrix();
// want texture on while creating the globe
glEnable(GL_TEXTURE_2D);// to ensure that the correct texture will be mapped // onto the globe glBindTexture(GL_TEXTURE_2D, texName_); // set the color to white so the texture mapping will show up glColor3dv(GLOBE_WHITE_COLOR); // orient the earth with the north pole up! This is only for the // earth so pop glRotatef(-90.0, 1.0, 0.0, 0.0); // make it one less than the radius so that the lat-long grid // is a good fit on top. // gluSphere(globe_, attributes_.globeRadius_-1, 48, 48); // turn off the texture since we don't want other objects // to draw with texturing. glDisable(GL_TEXTURE_2D); glPopMatrix(); glEndList();
}
}//////////////////////////////////////////////////////
// Method: setPosition_i
//
// Purpose: set the position (left, right, up, down, default, or out of the
// way) of the globe on the screen
//
// Notes: 1) one of two overloaded functions
// 2) caller holds application and OpenGL locks
//
//
void
DcGui_Impl::Globe3d::setPosition_i(GlobePositionOption pos)
{
// we want the zoom to start here so that the whole world in properly in
// view. It is here rather than being a constant because this is
// the only time it is set.
//
attributes_.zoomDist_ = -280.0;// determine the radius of the globe
// the diameter is 1/3 the window width (for everything but
// out of the way) so the radius is half of that
//
attributes_.globeRadius_ = globeFormWidth_/6.0;// check if the radius is going to change. If so, will need to
// do set radius
bool radiusChanged = false;
if ( (pos != GLOBE_OUT_OF_THE_WAY &&
attributes_.posOption_ == GLOBE_OUT_OF_THE_WAY) | |
(pos == GLOBE_OUT_OF_THE_WAY &&
attributes_.posOption_ != GLOBE_OUT_OF_THE_WAY)) {
radiusChanged = true;
}attributes_.posOption_ = pos;
// always at the center of the screen
attributes_.currentPos_.z_ = 0.0;if (pos == GLOBE_DEFAULT) {
// right in the center
attributes_.currentPos_.x_ = 0.0;
attributes_.currentPos_.y_ = 0.0;
}
// all the rest move it out of the way but also
// account for the radius of the earth
else if (pos == GLOBE_UPPER_RIGHT) {
// move it over a quarter of the screen both x, y
attributes_.currentPos_.x_ = globeFormWidth_/4.0;
attributes_.currentPos_.y_ = globeFormHeight_/4.0;
}
else if (pos == DcGui_Impl::GLOBE_UPPER_LEFT) {
// move it over a quarter of the screen left x and up y
attributes_.currentPos_.x_ = (0-(globeFormWidth_/4.0));
attributes_.currentPos_.y_ = (globeFormHeight_/4.0);
}
else if (pos == DcGui_Impl::GLOBE_LOWER_LEFT) {
// move it over a quarter of the screen left x and down y
attributes_.currentPos_.x_ =
(0 - (globeFormWidth_/4.0));
attributes_.currentPos_.y_ =
(0 - (globeFormHeight_/4.0));
}
else if (pos == DcGui_Impl::GLOBE_LOWER_RIGHT) {
// move it over a quarter of the screen right x and down y
attributes_.currentPos_.x_ =
(globeFormWidth_/4.0);
attributes_.currentPos_.y_ =
(0 - (globeFormHeight_/4.0));
}
else if (pos == DcGui_Impl::GLOBE_OUT_OF_THE_WAY) {
// this needs to be 60% of the current size
attributes_.globeRadius_ = (attributes_.globeRadius_/10) * 6;// move it into the right quadrant attributes_.currentPos_.x_ = (globeFormWidth_/4.0); attributes_.currentPos_.y_ = (globeFormHeight_/4.0);
}
if (radiusChanged) {
// a change in the earth’s radius means that we need to
// reset the globe display list
createGlobeDisplayList();// it also means that the overlays need to readjust their values // use attributes_.overlays_.size() in case the // overlays have not been set up yet (this is called in // the constructor) // for (int i = 0; i < attributes_.overlays_.size(); i++) { attributes_.overlays_[i]->updateEarthRadius(attributes_.globeRadius_); }
}
}
Any ideas??
[This message has been edited by Roach (edited 01-02-2003).]