Equation for Zooming

Started by
3 comments, last by wilberolive 9 years, 1 month ago

For some reason I'm struggling to work out something that I thought would be simple. I'm working on a 2D game and I'm trying to get a zoom working. Here's what I've got to work with.

minZoom = 0.2f <-- This is the smallest zoom amount (i.e. so the whole map can be seen on the screen)

maxZoom = 4.0f <-- This is the largest zoom amount (i.e. the map is zoomed in 4x its size)

My first thought was that I could just linearly interpolate between the two values. I wanted to have something like 10 or 20 discreet steps in between minZoom and maxZoom (I'll decide on how many once I get this working and see how it feels). However liner interpolation doesn't work because with a fixed number of steps, the step size is the same between each step. This means that as you zoom out, the jump in pixel size gets bigger and bigger so the zoom becomes like an exponential zoom, which means that near maxZoom it is very slow (turn the mouse wheel a lot for not much zoom) and near minZoom it is very fast (turn the mouse wheel a little and it jumps a lot).

So to solve this problem I need to do some sort of easing I think, so that the number of steps is fixed, but the step sizes are variable. They should start out at size x at maxZoom and then get smaller as you approach minZoom. What size x is and how fast they get smaller will probably require so trial and error to get the feel right so that the zoom feels constant.

I'm stuck with working out the math for this. I've tried a number of things but can't get anything to work right. I found the quadratic easing in function here http://gizma.com/easing/#quad1, which seems to do what I want, but the problem with that function is it works over a period of time. I don't know what that "period of time" is.

I have my two extreme values (4.0 and 0.2) and the number of steps in between (let's say 10, but it could be 20 or 15). Each time the mouse wheel is "clicked" I want to increment that step by 1 up or down depending on which way the mouse wheel is rolled. I need to come up with a function that will interpolate between 4.0 and 0.2 in 10 steps (inclusive, i.e. step 0 = 4.0 and step 9 = 0.2) but with a variable step size so that it starts with a step size of x, which is reduced in size with each step in order to slow down the zoom.

Advertisement

You want an exponential interpolation. An easy way to achieve that is to linearly interpolate in logarithmic domain.

  1. Calculate the logarithm of your two end points: logMinZoom = log(minZoom) and logMaxZoom = log(maxZoom).
  2. Linearly interpolate between logMinZoom and logMaxZoom in the desired number of steps: logZoom = logMinZoom + (logMaxZoom-logMinZoom)*step/(maxSteps-1).
  3. Transform logarithmic zoom to linear zoom: zoom = exp(logZoom).

This ensures that zoom increases or decreases with a uniform scale instead of with a uniform offset.

OK, that makes sense, except I don't understand the last line. Not sure what exp(logZoom) means and how it is calculated? I've tried Googling it but have so far not found a reasonable explanation that makes sense to me.


OK, that makes sense, except I don't understand the last line. Not sure what exp(logZoom) means and how it is calculated? I've tried Googling it but have so far not found a reasonable explanation that makes sense to me.

The exponential function exp(x) is just the inverse of the natural logarithm function log(x).

Never mind, I discovered that the c++ std library has an exp() function that does exactly what it says on the box. Your solution works brilliantly! I can't believe I wasted so much time trying to solve something that ended up being about 5 lines of code... wow, why don't I come here more often instead of wrestling with these things on my own?!?!

This topic is closed to new replies.

Advertisement