adjusting zoom speed

Started by
5 comments, last by Wizumwalt 17 years, 12 months ago
Hey all, In my display() I calculate the time it takes do draw a frame since the last frame and multiply that by some really small value like 0.0001. Then I add that to the current zoomFactor value and run an Animator when the user presses a zoom key. I then use this zoomFactor value in a glOrtho() call and multiply it by the left, right, bottom and top values to zoom my model in and out. The reason I do this is because it zooms my model very smoothly. My problem is that when the model is far away, it zooms slow enough to be under user control, but as it gets nearer (larger) it moves faster and is very hard to adjust and stop at the exact size I want the model to be. It's like watching the Enterprise go into warp speed as near distances and move slowly when it's far away. Anyone have any ideas how to fix this?
Advertisement
Sounds like you just need a non-linear mapping from 'interface' zoom to 'actual' zoom. Say both ranges are normalized to the range [0, 1]. You could then try a simple mapping such as:
actual_zoom = input_zoomn
Where n > 1.

This is just an idea; there are probably better solutions (or at least alternate functions that you could apply).
Lucky for me I'm getting back into math classes this year. I don't really understand what a non-linear mapping or normalizing the ranges would mean.

I'm guessing the 'actual_zoom' value is the value I pass into my opengl calls but the 'input_value' to the 'n' ... I don't get yet. I know exponentials, but I don't get what an exponent or what value to use would do.
Have you change in distance based on the current distance.

Zoom in: NewMagnification *= 1.1f;
Zoom out: NewMagnification /= 1.1f;

or

Zoom in(x): NewMagnification *= power(1.1f, x);
Zoom out(x): NewMagnification /= power(1.1f, x);

It would be a bit faster if you wrote your own power function assuming x is an integer.
I like to use the 2nd set and the param:x is set to the number of clicks on the mouse scroll wheel.
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
I'm not having much luck at this. I commented out my setZoomFactor() methods to try with powers and it zooms so quick either way I can't even see it most of the time. I have JOGL animators started in my key handler which calls my main display loop.

Anyways, can anyone see maybe what's wrong here?


public void display(GLAutoDrawable drawable) {   updateTime();   ...   gl.glOrtho(-winWidth * getZoomFactor(), winWidth * getZoomFactor(), -winHeight * getZoomFactor(), winHeight * getZoomFactor(), 100, -100);   ...}// get time it took to draw this frame since last frameprivate void updateTime() {   if(lastTime == -1) {      lastTime = System.currentTimeMillis();      lastFrameTime = 0;   }   else {currentTime = System.currentTimeMillis();      // Time taken to draw the last frame.      lastFrameTime = currentTime - lastTime;      lastTime = currentTime;   }   if (keyHandler.isZoomInPressed()) {      timeRatio = (float) (lastFrameTime * -0.0001);      //setZoomFactor((float) (getZoomFactor() + timeRatio));      setZoomFactor(getZoomFactor() * (float) Math.pow((getZoomFactor() + timeRatio), 1.1));   }   else if (keyHandler.isZoomOutPressed()) {      timeRatio = (float) (lastFrameTime * 0.0001);      //setZoomFactor((float) (getZoomFactor() + timeRatio));      setZoomFactor(getZoomFactor() / (float) Math.pow((getZoomFactor() + timeRatio), 1.1));   }}
The mapping I suggested will only work if the input zoom is normalized, i.e. in the range [0, 1]. Also, it looks like you're doing something different than what I suggested in my previous post. I'm not sure from looking at your code sample what your zoom range is, but I'll try to sketch out how I would do the conversion:
// Adjust zoom based on user input and frametime, and then:float normalized_zoom = (input_zoom - zoom_min)/(zoom_max - zoom_min);float adjusted_zoom = std::pow(normalized_zoom, zoom_exp); // zoom_exp > 1, adjust to tastefloat actual_zoom = zoom_min + adjusted_zoom * (zoom_max - zoom_min);
This is just an idea; it hasn't been tested or anything. But it seems like it should produce the effect you're looking for.
Thanks, I'll keep working at it. One thing different that I have from what you posted is that there is no input_zoom because I have no destination zoom level. The user pushes a plus or minus key till he gets the desired zoom level he wants and then releases the key.

That is ... if I understood your user input zoom correctly.

This topic is closed to new replies.

Advertisement