Mousewheel Zoom-To-Cursor
BlitzMax Forums/OpenGL Module/Mousewheel Zoom-To-Cursor
| ||
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. |
| ||
Any ideas? Someone surely has tackled this problem before.. |
| ||
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? |
| ||
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* |
| ||
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.) |
| ||
I will move my post, thanks |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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, |
| ||
Glad it's been of use... If you still need help adapting it, send me an email (usnavyfish AT gmail) |