From 55e751648fe72626e8939cd82f8edb6ecfb8a2a2 Mon Sep 17 00:00:00 2001 From: Cyd Date: Mon, 10 Aug 2026 22:26:15 -0500 Subject: [PATCH] The camera says whether it is tracking a staircase Janky tracking on a Live Cam, and the rotation is a spring-damper on the fixed simulation step, so it should glide. Which leaves the input rather than the smoothing: the camera follows a REMOTE pod, whose position only changes on this host when an update lands. If the watched point sits still for most steps and then leaps, the camera is tracking a staircase faithfully and nothing in the rotation can hide it. So FollowGoal now reports, every five seconds: how many simulation steps it ran, how many of those saw the target move at all, the largest single jump in metres, and how many times the trackside camera was cut to a different one. At 50 Hz that is about 250 steps per report, so: moved near 250 the target moves every step - look elsewhere for the jank, most likely frame pacing moved near 50 the target changes about ten times a second and the camera is stepping between arrivals biggest jump large confirms leaps rather than drift several cuts the trackside camera is flip-flopping, which snaps rather than glides and is its own kind of jank The cut count is worth having because timeOnCamera is 0 for a race - the director sets it to 0 outside football - so the closest-camera choice is re-evaluated every step and only hysteresis stops it oscillating. Not baselined locally: FollowGoal only runs on a camera station with a peer, so unlike the nav and copy traces this one goes out unverified against real numbers. The counters are simple enough to trust; the interpretation above is what to hold it to. Co-Authored-By: Claude Opus 5 (1M context) --- MUNGA/CAMSHIP.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/MUNGA/CAMSHIP.cpp b/MUNGA/CAMSHIP.cpp index 9e8e0db..567cf0e 100644 --- a/MUNGA/CAMSHIP.cpp +++ b/MUNGA/CAMSHIP.cpp @@ -12,6 +12,12 @@ //############################# CameraShip ################################ //########################################################################## +// +// Trackside camera cuts since the last RP412CAMLOG report - counted where +// the cut happens and drained where it is reported, both in FollowGoal. +// +static int gCameraCuts = 0; + //############################################################################# // Shared Data Support // @@ -320,6 +326,63 @@ void Point3D target; target.Multiply(focusOffset, goalEntity->localToWorld); + // + // RP412CAMLOG: is the thing we are following actually MOVING every + // step, or arriving in jumps? + // + // This runs on the fixed simulation step, so it is called at a steady + // rate whatever the frame rate. The entity it follows is a REMOTE pod, + // whose position only changes when an update lands - so if the watched + // point is identical on most steps and then leaps, the camera is + // tracking a staircase and no amount of smoothing here will hide it. + // Reported as: steps counted, how many of them saw any movement at + // all, the largest single jump, and how often the trackside camera was + // cut to a different one (a cut is a snap, not a glide, and would look + // like jank of a different kind). + // + if (RPCameraLog()) + { + static Scalar next_say = 0.0f; + static Point3D last_target(0.0f, 0.0f, 0.0f); + static Logical have_last = False; + static int steps = 0; + static int moved = 0; + static Scalar biggest = 0.0f; + + ++steps; + if (have_last) + { + Vector3D step_delta; + step_delta.Subtract(target, last_target); + Scalar distance = step_delta.Length(); + if (distance > 0.0f) + { + ++moved; + } + if (distance > biggest) + { + biggest = distance; + } + } + last_target = target; + have_last = True; + + if ((Scalar) Now() >= next_say) + { + if (next_say > 0.0f) + { + DEBUG_STREAM << "CamLog: follow - " << steps << " steps, " + << moved << " moved, biggest jump " << biggest + << "m, " << gCameraCuts << " cut(s)\n" << std::flush; + } + next_say = ((Scalar) Now()) + 5.0f; + steps = 0; + moved = 0; + biggest = 0.0f; + gCameraCuts = 0; + } + } + // //------------------------------------------------------------------------ // If time has not yet expired on this camera, keep with it if can see the @@ -348,6 +411,7 @@ void // if (currentCamera != old_camera) { + ++gCameraCuts; AimCameraAtPoint(target); lastSwitch = lastPerformance; }