zooming to mouse position using glOrtho

Hi guys

Currently I am using glOrtho to zoom and pan around a 2D graph I am rendering.

I have setup up the viewport to the standard width and height. Then I set the glOrtho so that my frustrum makes screen coordinates match world coordinates.

////////////////////////////////////////////////////////////////////
glViewport(0, 0, window_width,window_height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_width,window_height,0 , 100, -100);
///////////////////////////////////////////////////////////////////

When I do my zoom function in my mouse callback, I multiply the frustrum edges by a zoom factor…

glOrtho( 0 * zoomOut,
window_width * zoomOut,
window_height * zoomOut,
0 * zoomOut,
100, -100);

My question is… how do I zoom using mouse position as a centre?

I have tried this… (where mouseStoreX and mouseStoreY are the position stored at the first click)

glOrtho( (0 -mouseStoreX )* zoomOut + mouseStoreX,
(window_width - mouseStoreX) * zoomOut + mouseStoreX,
(window_height - mouseStoreY) * zoomOut + mouseStoreY,
(0 - mouseStoreY) * zoomOut + mouseStoreY,
100, -100);

It seems to work but the frustrum jumps around when I do a new click. I think somewhere I’m not taking into account the zoomOut factor when doing the mouse position storing.

Any help is much appreciated.

Thanks
Dan

It seems to work but the frustrum jumps around when I do a new click

Do you want to zoom with the click position moved to the centre of the view? If so you will jump about.

You code look wrong for this

eg if your window was 100 units wide and you clicked at 25 with a zoom of 2
left = (0-25) * 2 + 25 = -25
right = (100-25) * 2 + 25 = 175

making your centre 75 not 25

[QUOTE=tonyo_au;1248537]Do you want to zoom with the click position moved to the centre of the view? If so you will jump about.

[/QUOTE]

No I want to zoom with the point underneath the mouse as the pivot and everything else scale around it. I have tried various ways of getting around the offet but not yet come up with a solution.

I am getting the mouse world position when I click down…

glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
//flip Y for opengl reasons
winY = (float)viewport[3] - winY;
//get world mouse coordinate
gluUnProject( mouseStoreX, mouseStoreY , 0.0, modelview, projection, viewport, &posX, &posY, &pos);

Then I am calcing the difference from that click position from the current centre…

dx = posX - FS.xOffset;
dy = posY - FS.yOffset;

which I then use to do my scaling around the point in my mouse move function…

FS.left = ((FS.xOffset - dx - (window_width/2.0))*zoomFactor) +dx;
FS.right = ((FS.xOffset -dx + (window_width/2.0))*zoomFactor)+dx ;
FS.bottom = ((FS.yOffset -dy + (window_width/2.0))*zoomFactor)+dy;
FS.top = ((FS.yOffset -dy - (window_width/2.0))*zoomFactor) +dy;

before recentering on mouse release…

FS.xOffset = (FS.left-FS.right)/2.0;

I think somewhere I am not concatenating transforms correctly.

Have you tried this

F = mouse_x / window_width                    - fractional distance of mouse click
W = window_width * zoomFactor               - new window width in world units

mouse_x_in_world = F * W_old + left_old; - mouse in world units
left_new = mouse_x_in_world - F * W 
right_new = mouse_x_in_world + (1-F) * W

similar code for top and bottom

gluUnProject is probably less accurate than this.