Reputation: 149
So... I have this code I wrote to that draws a quad in ortho mode in Opengl. I know where its located and its size. Sometimes square.. some times its rectangular. What I'm attempting to do is zoom in and out and stay over the same location on the quad. I thought it would work but It's not. Knowing the distance from the mouse location to the corner, offset.x and the difference equaling rect_size.x- old_size_w the basic math would me this: (offset.x/rect_size.x) * difference. That should give me the scale of how much the location needs to move based on where the mouse is sitting. I hope someone can sort this out.. Thank you!....
Some numbers...
location = 100,100
old_size_w = 1024
rect_size.x = 1088 (new size old_ * 1.0625)
mouse_delta.x = 425
offset = 100 - 425 (-325)
difference = 1088-1024 (64)
delta_x = 325/1088 (.2987132....)
x_offset = Cint(delta_x * difference) (19) (19.11764...)
SO.... we are only moving by 19 pixels.. If we do the math from the other direction.. the 2 must = the difference from the old zoom and the new zoom
delta_x = (1088-325) /1088 (.701286...)
x_offset2 = Cint(delta_x * difference) (45) (44.88235...)
19 + 45 = 64 <--- this proves out the math
Yet... I am getting a nasty shift that gets worse the closer to the right of the image I move. Maybe someone can find the problem.. r_x is remaining X in the code below and is for proving the math.
Public Sub img_scale_up()
If Not ready_to_render Then Return
If Zoom_Factor >= 4.0 Then
Zoom_Factor = 4.0
Return 'to big and the t_bmp creation will hammer memory.
End If
Dim amt As Single = 0.0625
Zoom_Factor += amt
Dim offset As New Point
'old_w and old_h are the orginal size of the image.
Dim old_size_w, old_size_h As Double
old_size_w = (old_w * (Zoom_Factor - amt))
old_size_h = (old_h * (Zoom_Factor - amt))
offset = rect_location - (mouse_delta)
rect_size.X = Zoom_Factor * old_w
rect_size.Y = Zoom_Factor * old_h
Dim r_x As Double = ((rect_size.X - -offset.X) / rect_size.X) * (rect_size.X - old_size_w)
Dim delta_x As Double = CSng(offset.X / rect_size.X)
Dim delta_y As Double = CSng(offset.Y / rect_size.Y)
Dim x_offset = delta_x * (rect_size.X - old_size_w)
Dim y_offset = delta_y * (rect_size.Y - old_size_h)
rect_location.X += CInt(x_offset)
rect_location.Y += CInt(y_offset)
draw_(current_image)
Upvotes: 0
Views: 1552
Reputation: 149
Ok.. I sorted this out.. I used the a couple of the wrong values for both zooming in and out. This is the entire code for zooming around the mouse center and maintaining the center of the mouse. Anyone trying to figure this out.. well here's the code that works perfectly :)
Public Sub img_scale_up()
If Not ready_to_render Then Return
If Zoom_Factor >= 4.0 Then
Zoom_Factor = 4.0
Return 'to big and the t_bmp creation will hammer memory.
End If
Dim amt As Single = 0.0625
Zoom_Factor += amt
'this bit of math zooms the texture around the mouses center during the resize.
'old_w and old_h is the original size of the image in width and height
'mouse_pos is current mouse position in the window.
Dim offset As New Point
Dim old_size_w, old_size_h As Double
old_size_w = (old_w * (Zoom_Factor - amt))
old_size_h = (old_h * (Zoom_Factor - amt))
offset = rect_location - (mouse_pos)
rect_size.X = Zoom_Factor * old_w
rect_size.Y = Zoom_Factor * old_h
Dim delta_x As Double = CDbl(offset.X / old_size_w)
Dim delta_y As Double = CDbl(offset.Y / old_size_h)
Dim x_offset = delta_x * (rect_size.X - old_size_w)
Dim y_offset = delta_y * (rect_size.Y - old_size_h)
rect_location.X += CInt(x_offset)
rect_location.Y += CInt(y_offset)
draw_(current_image)
End Sub
Public Sub img_scale_down()
If Not ready_to_render Then Return
If Zoom_Factor <= 0.25 Then
Zoom_Factor = 0.25
Return
End If
Dim amt As Single = 0.0625
Zoom_Factor -= amt
'this bit of math zooms the texture around the mouses center during the resize.
'old_w and old_h is the original size of the image in width and height
'mouse_pos is current mouse position in the window.
Dim offset As New Point
Dim old_size_w, old_size_h As Double
old_size_w = (old_w * (Zoom_Factor - amt))
old_size_h = (old_h * (Zoom_Factor - amt))
offset = rect_location - (mouse_pos)
rect_size.X = Zoom_Factor * old_w
rect_size.Y = Zoom_Factor * old_h
Dim delta_x As Double = CDbl(offset.X / (rect_size.X + (rect_size.X - old_size_w)))
Dim delta_y As Double = CDbl(offset.Y / (rect_size.Y + (rect_size.Y - old_size_h)))
Dim x_offset = delta_x * (rect_size.X - old_size_w)
Dim y_offset = delta_y * (rect_size.Y - old_size_h)
rect_location.X += -CInt(x_offset)
rect_location.Y += -CInt(y_offset)
draw_(current_image)
End Sub
Upvotes: 1
Reputation: 51923
I usually get lost (doing silly mistakes) in deriving the right equations (as I use many view transform formulas not just one) and mostly I am to lazy to derive so I do it like this instead:
convert mouse position to coordinate system where offset is not scaled
if it is screen or world coordinate system depends on your transformation order. Store the result as mx0,my0
apply zoom
change
convert mouse position to coordinate system where offset is not scaled
it is the same as #1 but with updated zoom
. Store the result as mx1,my1
update offset
simply add:
offset_x += mx0-mx1;
offset_y += my0-my1;
Where offset_x,offset_y
holds your view offset (position).
Also see Zooming graphics based on current mouse position
Upvotes: 1
Reputation: 6404
Store mouse position as u, v where u and v are on 0.0 - 1.0. Translate your image so that mouse it as 0, 0. Manipulate, in this case by scaling. Then translate back so that 0, 0, goes to u. v.
Upvotes: 1