diff --git a/MUNGA_L4/L4VIDRND.cpp b/MUNGA_L4/L4VIDRND.cpp index 7cd0ce0..89e63ff 100644 --- a/MUNGA_L4/L4VIDRND.cpp +++ b/MUNGA_L4/L4VIDRND.cpp @@ -1131,6 +1131,38 @@ void if (traced != EntityID::Null && traced == myEntity->GetEntityID()) { + // + // Scoped out here, not inside the range test below, because + // the foreign-eye check has to read them before that test + // runs. + // + static Vector3D last_dir; + static Logical have_last = False; + static Scalar next_say = 0.0f; + static Scalar mean_angle = 0.0f; + static Scalar last_event = 0.0f; + static Scalar interval_sum = 0.0f; + static Scalar interval_min = 1000.0f; + static Scalar interval_max = 0.0f; + static int interval_count = 0; + static int frames = 0; + static int lurches = 0; + static int stalls = 0; + static Scalar last_angle = 0.0f; + static Logical have_angle = False; + static Scalar fraction_sum = 0.0f; + static int pinned_high = 0; + static int pinned_low = 0; + static Point3D last_pod(0.0f, 0.0f, 0.0f); + static Point3D last_eye(0.0f, 0.0f, 0.0f); + static Logical have_pod = False; + static Scalar last_pod_step = 0.0f; + static Scalar last_eye_step = 0.0f; + static Scalar eye_travel = 0.0f; + static int pod_stalls = 0; + static int eye_stalls = 0; + static int foreign_eye = 0; + gLastSampledFrame = gEyeFrame; Vector3D to_pod; @@ -1140,34 +1172,44 @@ void Scalar range = to_pod.Length(); - if (range > 0.1f) + // + // Reject a sample taken through a DIFFERENT eye. + // + // A camera station draws the map on the gauge wheel as well + // as the world, and that render runs the eye renderable too, + // so gEyeFrame ticks for it and this trace was comparing the + // map's viewpoint against the main one and calling the + // difference a stall. The tell was the period: 0.34s with + // its minimum and maximum identical to six figures, which is + // twenty frames exactly. Nothing in the network or the + // simulation keeps time that well - only a render schedule + // does. The stall and lurch counts converging to the same + // number said the same thing, since a stray viewpoint + // produces one short step going out and one long one coming + // back. + // + // A real camera at racing speed moves under a metre between + // frames, so twenty is far outside anything legitimate while + // still tolerating a genuine cut between trackside cameras. + // + Scalar eye_jump = 0.0f; + if (have_pod) { - static Vector3D last_dir; - static Logical have_last = False; - static Scalar next_say = 0.0f; - static Scalar mean_angle = 0.0f; - static Scalar last_event = 0.0f; - static Scalar interval_sum = 0.0f; - static Scalar interval_min = 1000.0f; - static Scalar interval_max = 0.0f; - static int interval_count = 0; - static int frames = 0; - static int lurches = 0; - static int stalls = 0; - static Scalar last_angle = 0.0f; - static Logical have_angle = False; - static Scalar fraction_sum = 0.0f; - static int pinned_high = 0; - static int pinned_low = 0; - static Point3D last_pod(0.0f, 0.0f, 0.0f); - static Point3D last_eye(0.0f, 0.0f, 0.0f); - static Logical have_pod = False; - static Scalar last_pod_step = 0.0f; - static Scalar last_eye_step = 0.0f; - static Scalar eye_travel = 0.0f; - static int pod_stalls = 0; - static int eye_stalls = 0; + Scalar dx = gEyeWorld.x - last_eye.x; + Scalar dy = gEyeWorld.y - last_eye.y; + Scalar dz = gEyeWorld.z - last_eye.z; + eye_jump = (Scalar) sqrt((double)(dx*dx + dy*dy + dz*dz)); + } + if (eye_jump > 20.0f) + { + ++foreign_eye; + have_last = False; // do not bridge across it + have_angle = False; + have_pod = False; + } + else if (range > 0.1f) + { Vector3D dir; dir.Divide(to_pod, range); ++frames; @@ -1325,7 +1367,8 @@ void DEBUG_STREAM << "CamLog: motion split - pod " << pod_stalls << " stall(s), eye " - << eye_stalls << " stall(s), eye travelled " + << eye_stalls << " stall(s), " << foreign_eye + << " foreign-eye sample(s) rejected, eye travelled " << eye_travel << "m, verdict " << ((pod_stalls > eye_stalls * 2) ? "the pod" @@ -1348,6 +1391,7 @@ void pod_stalls = 0; eye_stalls = 0; eye_travel = 0.0f; + foreign_eye = 0; } } }