PDA

View Full Version : Another zoom to cursor thread



LexFrenchy
02-02-2013, 11:31 AM
Hello,

I have a 2D application which is an image viewer.
I have the ability to pan around the image in the window and I have a basic zoom.
Now I'd like to improve the zoom so it zoom to the point under the mouse.
So far I've read everything possible on google and i've come close to something working,
but still can't find something perfect, here is what I got:



glMatrixMode (GL_PROJECTION);
glLoadIdentity();

// w and h are respectivly the width and height of the window
// newzoom_pos is the point in openGL coordinates where the user requested the zoom
// zoomFactor is between [0.1,10.0] , 0.1 -> 1.0 means downscale, 1.0 -> 10.0 means upscale
// transX and transY are used to pan around the image
float left = (0.f+transX -newzoom_pos.x())/zoomFactor +newzoom_pos.x();
float right = (w+transX -newzoom_pos.x())/zoomFactor +newzoom_pos.x();
float bottom = (h-transY-newzoom_pos.y())/zoomFactor +newzoom_pos.y();
float top = (0.f-transY -newzoom_pos.y())/zoomFactor +newzoom_pos.y();

glOrtho(left, right, top, bottom, -1, 1);



glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

it works well when the texture is filling all the window : i.e when the user zoom in a lot.
But when the image is small and does not fit yet in the viewer entirely ( there's black around), well it is messy and does not work...

btw, here is the code when the user zoom-in, in the mouse wheel event handler:



zoomFactor+=0.1;
QPoint oglpos = openGLpos(new_zoomPoint.x(), new_zoomPoint.y());
this->newzoom_pos = oglpos;

the openGLpos function is the following:


QPoint ViewerGL::openGLpos(int x,int y){
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX=0, winY=0, winZ=0;
GLdouble posX=0, posY=0, posZ=0;
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
winX = (float)x;
winY = viewport[3]- y;
if(winY == 0) winY =1.f;
glReadPixels( x, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
GLint b=gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
if(b==GLU_FALSE) cout << "failed unprojection" << endl;
return QPoint(posX,posY);
}



Could anybody help me through this?
Thanks for your help !

Alex

LexFrenchy
02-04-2013, 11:33 PM
Help, i'm still stuck on this !

tonyo_au
02-05-2013, 12:13 AM
well it is messy and does not work...
What exactly is your problem?

LexFrenchy
02-05-2013, 07:54 AM
I can't get the zoom to point working, I think i'm not doing it right in the call to glOrtho, and I could use some advices;)

tonyo_au
02-05-2013, 04:43 PM
Try something like this

lets say that when your zoom is 1:1 (ie no up-scale or down-scale) the width is W and height is H.
then


glOrtho(-W/2,W/2,-H/2,H/2,-1,1);
will centre you around the middle of the image

If the new origin is say new_x,new_y

glOrtho(-W/2+new_x,W/2+new_x,-H/2+new_y,H/2+new_y,-1,1);
will centre you around the new origin

Now we change the zoom to Z (0.1->10);


new_W = W * Z;
new_H = H * Z;
glOrtho(-new_W/2+new_x,new_W/2+new_x,-new_H/2+new_y,new_H/2+new_y,-1,1);


should place you centred around the new origin with the new scale

LexFrenchy
02-06-2013, 12:04 AM
oh thanks a lot ! And new_x, new_y are in openGL coordinates right?

tonyo_au
02-06-2013, 05:18 PM
Yes that's right