public void Client_UpdatePositionsBySnapshots( bool rendering )
{
//!!!!!slowly? we can ignore updating if no changes
if( client_receivePositionsSnapshots.Count == 0 )
return;
float time;
{
float clientTime = EntitySystemWorld.Instance.Client_TickTime;
if( rendering )
{
float timeFromLastTick = RendererWorld.Instance.FrameRenderTime -
EntitySystemWorld.Instance.Client_TimeWhenTickTimeWasUpdated;
clientTime += timeFromLastTick;
}
//interpolationTime should be greater than sending interval (currently TickDelta)
float interpolationTime = TickDelta * 1.5f;
time = clientTime - interpolationTime;
}
int networkTickNumber = (int)( (float)time * EntitySystemWorld.Instance.GameFPS );// time / TickDelta
//remove not necessary snapshots
{
again:
if( client_receivePositionsSnapshots.Count > 1 )
{
if( client_receivePositionsSnapshots[ 1 ].networkTickNumber <= networkTickNumber )
{
client_receivePositionsSnapshots.RemoveAt( 0 );
goto again;
}
}
}
Client_ReceivePositionsSnapshot snapshot1;
Client_ReceivePositionsSnapshot snapshot2;
if( rendering )
{
Client_GetReceivePositionsSnapshots( networkTickNumber, out snapshot1, out snapshot2 );
}
else
{
//use last snapshot
snapshot1 = client_receivePositionsSnapshots[
client_receivePositionsSnapshots.Count - 1 ];
snapshot2 = null;
}
if( snapshot2 != null )
{
//with interpolation
float timeCoef;
{
float time1 = ( (float)networkTickNumber ) * TickDelta;
//float time2 = time1 + TickDelta;
float timeDiff = TickDelta;//time2 - time1
timeCoef = 1.0f - ( time - time1 ) / timeDiff;
MathFunctions.Saturate( ref timeCoef );
}
if( PhysicsModel != null )
{
for( int n = 0; n < PhysicsModel.Bodies.Length; n++ )
{
Body body = PhysicsModel.Bodies[ n ];
if( snapshot1.bodies == null || n >= snapshot1.bodies.Length )
continue;
if( snapshot2.bodies == null || n >= snapshot2.bodies.Length )
continue;
Client_ReceivePositionsSnapshot.BodyItem bodyItem1 = snapshot1.bodies[ n ];
Client_ReceivePositionsSnapshot.BodyItem bodyItem2 = snapshot2.bodies[ n ];
Vec3 pos;
Quat rot;
Vec3.Lerp( ref bodyItem2.position, ref bodyItem1.position, timeCoef, out pos );
Quat.Slerp( ref bodyItem2.rotation, ref bodyItem1.rotation, timeCoef, out rot );
body.Position = pos;
body.Rotation = rot;
body.OldPosition = pos;
body.OldRotation = rot;
}
UpdatePositionAndRotationByPhysics( true );
OldPosition = Position;
OldRotation = Rotation;
}
else
{
Vec3 pos;
Quat rot;
Vec3 scl;
Vec3.Lerp( ref snapshot2.position, ref snapshot1.position, timeCoef, out pos );
Quat.Slerp( ref snapshot2.rotation, ref snapshot1.rotation, timeCoef, out rot );
Vec3.Lerp( ref snapshot2.scale, ref snapshot1.scale, timeCoef, out scl );
SetTransform( pos, rot, scl );
SetOldTransform( pos, rot, scl );
}
}
else
{
//without interpolation
if( PhysicsModel != null )
{
for( int n = 0; n < PhysicsModel.Bodies.Length; n++ )
{
Body body = PhysicsModel.Bodies[ n ];
if( snapshot1.bodies == null || n >= snapshot1.bodies.Length )
continue;
Client_ReceivePositionsSnapshot.BodyItem bodyItem = snapshot1.bodies[ n ];
body.Position = bodyItem.position;
body.Rotation = bodyItem.rotation;
body.OldPosition = bodyItem.position;
body.OldRotation = bodyItem.rotation;
}
UpdatePositionAndRotationByPhysics( true );
OldPosition = Position;
OldRotation = Rotation;
}
else
{
SetTransform( snapshot1.position, snapshot1.rotation, snapshot1.scale );
SetOldTransform( snapshot1.position, snapshot1.rotation, snapshot1.scale );
}
}
}