Formula for zooming at a constant speed through arbitrary zoom range?

Place to get help with not working mods / modding interface.
Post Reply
User avatar
TheBloke
Fast Inserter
Fast Inserter
Posts: 123
Joined: Mon Dec 03, 2018 2:48 am
Contact:

Formula for zooming at a constant speed through arbitrary zoom range?

Post by TheBloke »

Hi all

Maths question: what formula/calculation will enable me to zoom a player over any arbitrary range of zoom values, at a consistent, linear speed?

For example, being able to zoom from player.zoom = 0.0001 to 1.7 over 200 ticks, or 2.5 to 0.5 in 240 ticks, or any other from->to values and duration, always at a constant zoom rate, relative to the game world?

The problem I have is that the zoom scale is not linear. Increasing zoom from 0.1 to 0.2 results in a much larger relative movement than going from 1.0 to 1.1. Therefore my naive method of "targetZoom - startZoom / duration" results in a zoom-in that starts very fast then gets slow, and a zoom-out that starts slow then gets fast.

My maths knowledge is extremely rusty so I'd be most grateful for any help with this.

If you're wondering why I want this, and why I don't just use the new cutscene controller, here's the background: I wanted a version of the cutscene controller in which movement speed is always linear. The vanilla cutscene system is awesome, but it applies easing to every movement - meaning it's slower at the start and end of each movement than in the middle. I've raised a modding interface request for a new flag in the cutscene controller which would enable linear movement on a per-waypoint basis, and in response posila suggested a workaround of re-implementing linear zooming using player.teleport and player.zoom. He told me that this is how the old trailers did it.

This has mostly been straightforward, other than this issue with translating the zoom range into a linear movement. Unfortunately the old trailer code is no longer available for download that I can find (it's linked in this thread, but the link has been dead for a year or more.)

For reference, this is the zoom code I currently have:

Code: Select all

  -- called from on_tick when a cutscene is active
  if waypoint.target_zoom > cutscene.start_zoom then
    waypoint.zoom_step = waypoint.zoom_step or ( waypoint.target_zoom - cutscene.start_zoom ) / waypoint.duration
    cutscene.current_zoom = cutscene.current_zoom + waypoint.zoom_step
  else
    waypoint.zoom_step = waypoint.zoom_step or ( cutscene.start_zoom - waypoint.target_zoom ) / waypoint.duration
    cutscene.current_zoom = cutscene.current_zoom - waypoint.zoom_step
  end
  player.zoom = cutscene.current_zoom
Thanks in advance!

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2250
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Formula for zooming at a constant speed through arbitrary zoom range?

Post by boskid »

i think zoom follows exponential curve with coef 1.05 between zoom levels but i may be wrong

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Formula for zooming at a constant speed through arbitrary zoom range?

Post by darkfrei »

boskid wrote:
Mon Oct 14, 2019 5:30 pm
i think zoom follows exponential curve with coef 1.05 between zoom levels but i may be wrong
Then it will be better with 10^(1/50) = 1,0471285480508995334645020315281 and every 50 steps you get factor 10 or
2^(1/15) = 1,047294122820626717891597012091 and you get every 15 steps factor 2 exactly.

User avatar
TheBloke
Fast Inserter
Fast Inserter
Posts: 123
Joined: Mon Dec 03, 2018 2:48 am
Contact:

Re: Formula for zooming at a constant speed through arbitrary zoom range?

Post by TheBloke »

Thanks so much guys! That's perfect.

This is what I have now, which gives a smooth, consistently paced zoom:

Code: Select all

  local zoom_step
  if waypoint.target_zoom > cutscene.current_zoom then
    zoom_step = ( waypoint.target_zoom / cutscene.current_zoom ) ^ ( 1 / ( waypoint.duration - waypoint.current_step ) )
    cutscene.current_zoom = cutscene.current_zoom * zoom_step
  else
    zoom_step = ( cutscene.current_zoom / waypoint.target_zoom ) ^ ( 1 / ( waypoint.duration - waypoint.current_step ) )
    cutscene.current_zoom = cutscene.current_zoom * ( 1 / zoom_step )
  end
  player.zoom = cutscene.current_zoom
Thanks again!

Edit: I was asked for a quick demo of how it looks in action, so here it is: https://youtu.be/noZKonslSV0

Post Reply

Return to “Modding help”