Zoom to a point on the screen
BlitzMax Forums/BlitzMax Beginners Area/Zoom to a point on the screen
| ||
I thought this would be straight forward but I cannot figure it out! What I want to do is zoom into a particular area of the whole display (I have a scaling routine in place which takes care of everything so that's not a problem) Some example params: physical view area = 512,384 zoom=2.0 ' any value here but min=1.0 xpos=MouseX() ypos=MouseY() As per above, I would like to zoom into the graphics wherever the mouse pointer is using a factor of 2.0 * It sounds simple but I cannot seem to get the offsets correct (via SetOrigin) From the example parameters the zoomed graphics would be twice as big as the 'physical' display area If say, the mouse is at 20,50 how do I calculate the offsets to shift the graphics? Bearing in mind the zoom could be anything from 1.0 onwards * |
| ||
I agree this is difficult and it took me many hours to figure this out. Here is some code I produced in case it is of any use to you. TVec2 just has fields x and y, and a few methods such as scal which means multiply, Sub(tract) and Add. _view is the top left corner of the current viewing window. Click to cell takes the current mouse pointer position on the screen and converts it to the coordinate it is over on the map. When drawing you also have to pass along the current zoom/scale to everything so they are drawn at the correct size. I wish I could better explain the code but I barely understand it myself, as I wrote it through trial and error.'scroll along the map by the distance delta Method scroll(delta:TVec2) _view.Add(delta.Scal(1.0/_zoom_scale), _view) If _view.x < 0 Then _view.x = 0 If _view.x > _size.x - TSettings.resolution_x*(1.0/_zoom_scale) Then _view.x = (_size.x - TSettings.resolution_x*(1.0/_zoom_scale)) If _view.y < 0 Then _view.y = 0 If _view.y > _size.y - TSettings.resolution_y*(1.0/_zoom_scale) Then _view.y = (_size.y - TSettings.resolution_y*(1.0/_zoom_scale)) End Method 'go immediately to this position of the map Method set_view(pos:TVec2) Global tempvec:TVec2 = New TVec2 _view = pos.Sub((tempvec.Set(TSettings.resolution_x/2, TSettings.resolution_y/2).Scal(1.0/_zoom_scale))) End Method Method zoom_in() Global vec:TVec2 = New TVec2 vec = (click_to_cell(New TVec2.Set( TSettings.resolution_x/2, TSettings.resolution_y/2))) _zoom_scale :+ 0.02 If _zoom_scale > 1.0 Then _zoom_scale = 1.0 set_view(vec) End Method Method zoom_out() Global vec:TVec2 = New TVec2 vec = (click_to_cell(New TVec2.Set( TSettings.resolution_x/2, TSettings.resolution_y/2))) _zoom_scale :- 0.02 If _zoom_scale < 0.2 Then _zoom_scale = 0.2 set_view(vec) End Method Method click_to_cell:TVec2(click:TVec2) Return get_view_area().Add(click.Scal(1.0/_zoom_scale)) End Method Method get_view_area:TVec2() Return _view.Copy() End Method |
| ||
My Odd2D driver can do this for you. In fact that is precisely why I started the project, well that and full screen rotation. You set the point you want to zoom in on using SetScreenFocus, and then zoom in/out with SetZoom. Simples. Odd2D discussion thread Odd2D direct download |
| ||
Thanks both David, It sounds like we are both aiming at the same thing My lightweight OpenGL code also allows rotation, zoom, and origin offsetting EDIT: Solved! ' transform the display (zoom into point at mouse position) Local mxoffs#=Float(MouseX())*zoom-Float(MouseX()) Local myoffs#=Float(MouseY())*zoom-Float(MouseY()) SetScale zoom,zoom SetOrigin -mxoffs , -myoffs |