diff --git a/MUNGA/ENTITY.cpp b/MUNGA/ENTITY.cpp index eb4db2c..1631a0a 100644 --- a/MUNGA/ENTITY.cpp +++ b/MUNGA/ENTITY.cpp @@ -825,6 +825,21 @@ void step_till += fixed_step; } + // + // How far past the last completed step the frame we are + // about to draw falls, as a fraction of one step. This is + // the leftover the fixed-step loop deliberately does not + // simulate - see renderPreviousOrigin in entity.h. + // + { + Scalar leftover = till - GetLastPerformance(); + Scalar fraction = (fixed_step > (Scalar) 0) + ? (leftover / fixed_step) : (Scalar) 0; + if (fraction < (Scalar) 0) fraction = (Scalar) 0; + if (fraction > (Scalar) 1) fraction = (Scalar) 1; + renderStepFraction = fraction; + } + for (int i=0; i= 20) { localOrigin.angularPosition.Normalize(); diff --git a/MUNGA_L4/L4VIDRND.cpp b/MUNGA_L4/L4VIDRND.cpp index f570820..50e2383 100644 --- a/MUNGA_L4/L4VIDRND.cpp +++ b/MUNGA_L4/L4VIDRND.cpp @@ -1082,8 +1082,18 @@ void // DPL_FLUSH_DCS ( myDCS ); // } myRenderer->GetMatrixStack()->Push(); + // + // The transform to DRAW with, blended across the fixed simulation + // step this frame falls inside - see Entity::GetRenderToWorld. This + // is the whole of render interpolation on the vehicle side: the + // renderable already ran once per frame and simply re-read a value + // that only changed at the physics rate. + // + LinearMatrix renderToWorld; + myEntity->GetRenderToWorld(&renderToWorld); + Matrix4x4 tempMatrix; - tempMatrix = myEntity->localToWorld; + tempMatrix = renderToWorld; myRenderer->GetMatrixStack()->MultMatrix(&tempMatrix.ToD3DMatrix()); //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); @@ -5651,7 +5661,17 @@ void // time based upon the setting of the eyepoint rotation //---------------------------------------------------------------------- // - if((myEyepointRotation && *myEyepointRotation != oldEyepointRotation) || oldLocalToWorld != myEntity->localToWorld || mForceUpdate) + // + // The last term is render interpolation. This gate rebuilt the view + // only when the entity's localToWorld CHANGED, which happens at the + // physics rate - so with the world now drawn on a blended transform the + // eye would have gone on stepping, and the judder would simply have + // moved from the scenery to the camera. While a blend is in progress + // the view has to be rebuilt every frame; renderStepFraction is zero + // whenever interpolation is off or idle, so the old behaviour is + // untouched. See Entity::GetRenderToWorld. + // + if((myEyepointRotation && *myEyepointRotation != oldEyepointRotation) || oldLocalToWorld != myEntity->localToWorld || mForceUpdate || myEntity->renderStepFraction > (Scalar) 0) { mForceUpdate = false; oldLocalToWorld = myEntity->localToWorld;