3

It seems that this is quite a common question, but I can't find a person with my same circumstances. The closest seems to be: OpenGL: scale then translate? and how?.

The problem I'd really like some help with is to do with moving around while zoomed into (and out of) a 2d scene using OpenGl. The code for zooming out is pretty simple:

void RefMapGLScene::zoomOut(){
  currentScale = currentScale-zoomFactor;
  double xAdjust = (((get_width())*zoomFactor/2));
  double yAdjust = ((get_height()*zoomFactor/2));
  zoomTranslateX -= xAdjust;
  zoomTranslateY -= yAdjust;
}

The code for zooming in is basically the same (add the zoomFactor to currentScale, and increment zoomTranslateX and Y).

The code for rending everything is also simple:

glPushMatrix();
glTranslated(-zoomTranslateX, -zoomTranslateY, 0);

glScaled(currentScale, currentScale, 1);
glTranslated(totalMovedX, totalMovedY, 0);

graph->draw();

glPopMatrix();

Essentially, zoomTranslate stores an adjustment needed to make the screen move a little towards the middle when zooming. I don't do anything nice like move to where the mouse is pointing, I just move to the middle (ie, to the right and up/down depending on your co-ordinate system). TotalMovedX and Y store the mouse movement as follows:

if (parent->rightButtonDown){
  totalMovedX += (-(mousex-curx))/currentScale;
  totalMovedY += (-(mousey-cury))/currentScale;
}

Dragging while not zoomed in or out works great. Zooming works great. Dragging while zoomed in/out does not work great :) Essentially, when zoomed in, the canvas moves a lot slower than the mouse. The opposite for when zoomed out.

I've tried everything I can think of, and have read a lot of this site about people with similar issues. I also tried reimplementing my code using glOrtho to handle the zooms, but ended up facing other problems, so came back to this way. Could anybody please suggest how I handle these dragging events?

Community
  • 1
  • 1
Simon
  • 31
  • 1
  • 1
  • 2

1 Answers1

3

The order of operations matter. Operations on matrices are applied in the reverse order in which you multiplied the matrices. In your case you apply the canvas movement before the scaling, so your mouse drag is also zoomed.

Change your code to this:

glPushMatrix();
glTranslated(-zoomTranslateX, -zoomTranslateY, 0);

glTranslated(totalMovedX, totalMovedY, 0);
glScaled(currentScale, currentScale, 1);

graph->draw();

glPopMatrix();

Also after changing that order you don't have to scale your mouse moves, so you can omit that division by currentScale

if (parent->rightButtonDown){
  totalMovedX += (-(mousex-curx));
  totalMovedY += (-(mousey-cury));
}
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • 3
    I actually found the problem, both your code and mine work fine. I was just saving totalMovedX and totalMovedY as an int, which meant the decimals were getting truncated. Really elementary mistake. Thank you for answering. – Simon May 02 '11 at 07:26