Skip to content

bugfix(camera): Advance scripted camera moves by elapsed logic time - #3143

Draft
bobtista wants to merge 1 commit into
TheSuperHackers:mainfrom
bobtista:bobtista/bugfix/scripted-camera-render-rate
Draft

bugfix(camera): Advance scripted camera moves by elapsed logic time#3143
bobtista wants to merge 1 commit into
TheSuperHackers:mainfrom
bobtista:bobtista/bugfix/scripted-camera-render-rate

Conversation

@bobtista

@bobtista bobtista commented Aug 14, 2026

Copy link
Copy Markdown

Fixes #3142.

rotateCamera, zoomCamera and pitchCamera convert their authored duration into a count of 33.33 ms frames, then advance one step per render frame, so a scripted camera move completes renderFps / logicFps times faster than the mission scripter intended. Network games hit this without any special setup, because FramePacer::getActualLogicTimeScaleFps() returns TheNetwork->getFrameRate() and pins the logic rate near 30 while the render rate follows the player's limit.

Now advances the three movements by the elapsed logic time instead of by one render frame, so they take the authored duration at any render frame rate. curFrame becomes a Real and accumulates milliseconds / TheW3DFrameLengthInMsec, which leaves the easing, the hold frames, and the remaining-time maths used by Set Final Zoom / Set Final Pitch working on the same quantities as before.

Measured with a "1 rotation over 2.00 seconds" move, logic time scale pinned at 30 FPS, varying only the max render FPS:

max render FPS before after
30 1960 ms 1967 ms
60 986 ms 1987 ms
120 525 ms 2000 ms

This mirrors the fix already applied to the fourth scripted camera movement in the same file: #1451 converted moveAlongWaypointPath to accumulate elapsed milliseconds fed by TheFramePacer->getLogicTimeStepMilliseconds(FramePacer::IgnoreFrozenTime), and rotate, zoom and pitch were left on the old frame-counting form. The call sites here now pass the same value.

W3DView lives in Core, so this covers both games.

Also measured on a shipped campaign cutscene, the MD_CHI02 intro, which uses a waypoint pan and a
rotation along with a zoom and a pitch. Logic time scale pinned at 30, render at 125, comparing this
branch against its parent commit. The metric is how fast curFrame advances, which does not depend
on how long the mission holds each shot:

movement authored expected before after
rotate 5.00s 30.0 /s 120.0 /s 30.0 /s
zoom 10.00s 30.0 /s 120.0 /s 30.0 /s
pitch 10.00s 30.0 /s 120.0 /s 30.0 /s

Before the change all three advance at the render rate, so the rotation completes in 1.23s instead
of its authored 5.00s. After the change all three advance at the logic rate and the rotation takes
4.98s.

One note on where this is reachable. Every campaign intro I sampled sets its own frame rate cap
through the SET_FPS_LIMIT script action, always below 30 (MD_USA01 20, MD_GLA01 24,
MD_CHI02 24, MD_CHI03 25), so single player cutscenes render slower than the logic rate and do
not show the fault. It shows up where the logic rate is pinned below the render rate, which is the
network case described above.

Todo:

  • Confirm the authored duration is honoured at 30, 60 and 120 render FPS
  • Check a campaign cutscene that mixes a waypoint pan with a rotation

@bobtista bobtista self-assigned this Aug 14, 2026
@bobtista bobtista added Bug Something is not working right, typically is user facing Rendering Is Rendering related labels Aug 14, 2026
@bobtista
bobtista force-pushed the bobtista/bugfix/scripted-camera-render-rate branch from 905681b to f1acf6f Compare August 26, 2026 14:25
@bobtista
bobtista force-pushed the bobtista/bugfix/scripted-camera-render-rate branch from f1acf6f to c9b6157 Compare August 27, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Rendering Is Rendering related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scripted camera rotate, zoom and pitch speed changes with framerate

1 participant