Mousewheel Zoom-To-Cursor

BlitzMax Forums/OpenGL Module/Mousewheel Zoom-To-Cursor

USNavyFish(Posted 2008) [#1]
Hello everybody. I'm having trouble implementing a specific feature and was looking for some advice.

I'd like to zoom the 2D playing field in a manner similar to Supreme-Commander, in that the zoom centers on the mouse cursor's current location. Have tried many different methods with little success.

Note that the current method included in my source code is simply a 'safe mode' that does not try and center upon the cursor.

Use mousewheel to zoom, and click-drag to pan around the playing field. You are welcome to use any code snippets you might find useful. Be warned this is full of globals and other bad programming practices.. the program is simply a quick-n-dirty test, to get the zoom algorithm down and be thrown away thereafter.

Thank you in advance for any assistance provided!



EDIT: Link Removed. Solution code posted below. Have a nice day.


USNavyFish(Posted 2008) [#2]
Any ideas? Someone surely has tackled this problem before..


tonyg(Posted 2008) [#3]
Are you after a solution using native OpenGl code which is what this forum is for. If so, I can't help.
I checked your code though and it doesn't seem to use OGL directly (or use the OGL driver). I couldn't find any zoom or pan functions in place.
Isn't it a case of taking the mousex and mousey and making that the centre of your world, set the origin and then zooming?


USNavyFish(Posted 2008) [#4]
I am using Max2D - that is based upon OGL, or so I assumed.

Being horribly written, the zoom and pan functions are built right into the event manager.

This would be much easier if I could access OGL code directly, while still using the nice conveniences provided by Max2D.

Nevertheless, I will implement your suggestion, setting the origin to the mouse's world-coordinates. This seems incredibly logical now that you mention it.

*feeling dumb*


plash(Posted 2008) [#5]
I think this does not directly pertain to OGL, as your asking about zooming to a specific point and not anything specific to OGL (you would get more responses in the general programming section anyways, as more people frequent it then here.)


USNavyFish(Posted 2008) [#6]
I will move my post, thanks


tonyg(Posted 2008) [#7]
P.S. Default driver is DX (on Windows) but not sure what you're developing on.
If you're after native OGL then this might help with the zoom while panning a camera is simply resetting the setorigin.


USNavyFish(Posted 2008) [#8]
So, I figured out how to do it. Finally sat down and drew everything out, which helped immensely.


I'll post the code below in case anyone is interested, and so that this is not an entirely wasted thread.





NOTE: Much better version posted below




Neither of the code pieces below actually REQUIRE MaxGUI. I'm simply using the Desktop() TGadget to pick the user's native resolution, then setting the Globals GW and GH to the native Width and Height (resolution) respectively. If you'd like to compile this without having MaxGUI, just take out the "Import Maxgui.Drivers" line, and then set the globals GW and GH to your desired full screen resolution. Is there a better technique for reading the native resolution without resorting to maxgui?

Anyway, back on topic.. the code..







Again check out the version below, it's much better.


USNavyFish(Posted 2008) [#9]
Improved version

Mousewheel to zoom in / out, centered upong location of cursor. Click and drag to pan. Double clicking instantly zooms full-in on the mouse cursor.







Scaremonger(Posted 2008) [#10]
There is a small "Jump" at the limits of max / min zoom. It can be fixed simply by removing one line of code from each of the zoom functions making the effect much more fluid.

I've also commented out the zoomTarget* limitation code in ZoomIn() because I cannot see what it is achieving!

Otherwise this is a fantastic bit of code and I hope to find a good use for it at some point.

Cheers,

Function ZoomIn(MouseScreenX:Int , MouseScreenY:Int) 
	If Not (ZoomTargetScale  >= ZoomMax) 	
		Local mx:Float = (MouseScreenX - GHW) /ZoomTargetScale
		Local my:Float = (MouseScreenY - GHH) /ZoomTargetScale
		Local z:Float = 1.0 - (1.0/ZoomFactor)
		ZoomTargetX = (mx)*(z) + WorldViewOriginX
		ZoomTargetY = (my)*(z) + WorldViewOriginY

rem Cannot see what this achieves					
		If ZoomTargetX > GW
			ZoomTargetX = GW
		Else If ZoomTargetX < 0
			ZoomTargetX = 0
		EndIf
		If ZoomTargetY > GH
			ZoomTargetY = GH
		Else If ZoomTargetY < 0
			ZoomTargetY = 0
		EndIf
end rem 			
					
		ZoomTargetScale:* ZoomFactor

'# BUGFIX - Scaremonger
'		If ZoomTargetScale  > ZoomMax Then ZoomTargetScale  = ZoomMax
	
	EndIf
End Function

Function ZoomOut(MouseScreenX:Int , MouseScreenY:Int)
	If Not (ZoomTargetScale <= ZoomMin) 
		Local mx:Float = (MouseScreenX - GHW) / ZoomTargetScale
		Local my:Float = (MouseScreenY - GHH) / ZoomTargetScale	
		Local z:Float = 1.0 - ZoomFactor
		ZoomTargetX  = mx*(z)+ WorldViewOriginX
		ZoomTargetY = my*(z)+ WorldViewOriginY
		ZoomTargetScale:/ ZoomFactor
		
'# BUGFIX - Scaremonger
'		If ZoomTargetScale < ZoomMin Then ZoomTargetScale = ZoomMin

	EndIf
End Function




slenkar(Posted 2008) [#11]
Ive been looking through the code but cant understand it enough to adapt to my own uses. I need it for a map drawn with tile images,


USNavyFish(Posted 2009) [#12]
Glad it's been of use... If you still need help adapting it, send me an email (usnavyfish AT gmail)