BVB Source Codes

CRYENGINE Show PhysicsSync.cpp Source code

Return Download CRYENGINE: download PhysicsSync.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "PhysicsSync.h"
  5. #include <CryPhysics/IPhysics.h>
  6. #include "GameChannel.h"
  7. #include "CryAction.h"
  8. #include "IActorSystem.h"
  9. #include <CryAction/IDebugHistory.h>
  10. #include "NetworkCVars.h"
  11.  
  12. static const int RTT_LOOPS = 2; // how many round trips to include in ping averaging
  13.  
  14. class CPhysicsSync::CDebugTimeline
  15. {
  16. public:
  17.         void AddEvent(CTimeValue remote, CTimeValue local, CTimeValue now)
  18.         {
  19.                 SState state = { remote, local, now };
  20.                 m_states.push_back(state);
  21.                 Render();
  22.         }
  23.  
  24.         void Render()
  25.         {
  26.                 CTimeValue now = gEnv->pTimer->GetAsyncTime();
  27.                 CTimeValue old = now - 1.0f;
  28.                 while (!m_states.empty() && m_states.front().now < old)
  29.                         m_states.pop_front();
  30.  
  31.                 IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();
  32.                 pPD->Begin("PhysSync", true);
  33.  
  34.                 float yLocal = 550;
  35.                 float yRemote = 500;
  36.                 float yNow = 525;
  37. #define TIME_TO_X(tm)             (((tm) - now).GetSeconds() + 1) * 780.0f + 10.0f
  38. #define MARK_AT(x, y, clr, tmout) pPD->Add2DLine((x) - 10, (y) - 10, (x) + 10, (y) + 10, (clr), tmout); pPD->Add2DLine((x) - 10, (y) + 10, (x) + 10, (y) - 10, (clr), tmout)
  39.                 for (std::deque<SState>::iterator it = m_states.begin(); it != m_states.end(); ++it)
  40.                 {
  41.                         float xrem = TIME_TO_X(it->remote);
  42.                         float xloc = TIME_TO_X(it->local);
  43.                         float xnow = TIME_TO_X(it->now);
  44.                         MARK_AT(xrem, yRemote, ColorF(1, 1, 1, 1), 60);
  45.                         MARK_AT(xloc, yLocal, ColorF(1, 0, 0, 1), 60);
  46.                         MARK_AT(xnow, yNow, ColorF(0, 1, 0, 1), 60);
  47.                         pPD->Add2DLine(xnow, yNow, xrem, yRemote, ColorF(1, 1, 1, .5), 60);
  48.                         pPD->Add2DLine(xnow, yNow, xloc, yLocal, ColorF(1, 1, 1, .5), 60);
  49.                 }
  50.         }
  51.  
  52. private:
  53.         struct SState
  54.         {
  55.                 CTimeValue remote;
  56.                 CTimeValue local;
  57.                 CTimeValue now;
  58.         };
  59.         std::deque<SState> m_states;
  60. };
  61.  
  62. CPhysicsSync::CPhysicsSync(CGameChannel* pParent)
  63.         : m_pParent(pParent)
  64.         , m_pWorld(gEnv->pPhysicalWorld)
  65.         , m_physPrevRemoteTime(0.0f)
  66.         , m_pingEstimate(0.0f)
  67.         , m_physEstimatedLocalLaggedTime(0.0f)
  68.         , m_epochWhen(0.0f)
  69.         , m_physEpochTimestamp(0)
  70.         , m_ignoreSnapshot(false)
  71.         , m_catchup(false)
  72. {
  73.         m_pDebugHistory = CCryAction::GetCryAction()->CreateDebugHistoryManager();
  74. }
  75.  
  76. CPhysicsSync::~CPhysicsSync()
  77. {
  78.         if (m_pDebugHistory)
  79.                 m_pDebugHistory->Release();
  80. }
  81.  
  82. static float CalcFrameWeight(float smoothing)
  83. {
  84.         float wt = clamp_tpl(gEnv->pTimer->GetFrameTime() * smoothing, 0.0f, 1.0f);
  85.         return wt;
  86. }
  87.  
  88. bool CPhysicsSync::OnPacketHeader(CTimeValue tm)
  89. {
  90.         // these may change, but setup some default behaviors now
  91.         m_catchup = true;
  92.         m_ignoreSnapshot = false;
  93.  
  94.         // quick check in case we're full
  95.         if (m_pastPings.Full())
  96.                 m_pastPings.Pop();
  97.  
  98.         // add the current ping to our list of past ping samples
  99.         INetChannel* pNetChannel = m_pParent->GetNetChannel();
  100.         SPastPing curPing = { gEnv->pTimer->GetAsyncTime(), pNetChannel->GetPing(true) };
  101.         m_pastPings.Push(curPing);
  102.  
  103.         // find the average ping so far
  104.         float sumPing = 0;
  105.         for (PingQueue::SIterator it = m_pastPings.Begin(); it != m_pastPings.End(); ++it)
  106.                 sumPing += it->value;
  107.         CTimeValue averagePing = sumPing / m_pastPings.Size();
  108.  
  109.         // find how much the average ping has changed from our estimate, in order to adjust later
  110.         CTimeValue deltaPing;
  111.         CTimeValue prevPingEstimate = m_pingEstimate;
  112.         if (m_pingEstimate != 0.0f)
  113.         {
  114.                 float pingWeight = CalcFrameWeight(CNetworkCVars::Get().PhysSyncPingSmooth);
  115.                 m_pingEstimate = (1.0f - pingWeight) * m_pingEstimate.GetSeconds() + pingWeight * averagePing.GetSeconds();
  116.         }
  117.         else
  118.         {
  119.                 m_pingEstimate = averagePing;
  120.         }
  121.  
  122.         CTimeValue oneMS;
  123.         oneMS.SetMilliSeconds(1);
  124.         if (m_pingEstimate != 0.0f)
  125.         {
  126.                 CTimeValue clampAmt = m_pingEstimate.GetSeconds() * 0.5f * 0.5f;
  127.                 if (oneMS < clampAmt)
  128.                         clampAmt = oneMS;
  129.                 deltaPing = CLAMP(m_pingEstimate - prevPingEstimate, -clampAmt, clampAmt);
  130.                 m_pingEstimate = prevPingEstimate + deltaPing;
  131.         }
  132.         else
  133.                 deltaPing = 0.0f;
  134.  
  135.         // expunge any pings that are now older than RTT_LOOPS round trip times
  136.         CTimeValue oldTime = curPing.when - averagePing.GetSeconds() * RTT_LOOPS;
  137.         while (m_pastPings.Size() > 1 && m_pastPings.Front().when < oldTime)
  138.                 m_pastPings.Pop();
  139.  
  140.         // current remote time is tm
  141.         CTimeValue physCurRemoteTime = tm;
  142.         // if we've not yet gotten a previous remote time, estimate it at half a ping ago
  143.         if (m_physPrevRemoteTime == 0.0f)
  144.                 m_physPrevRemoteTime = physCurRemoteTime - 0.5f * averagePing.GetSeconds();
  145.         CTimeValue physDeltaRemoteTime = physCurRemoteTime - m_physPrevRemoteTime;
  146.         if (physDeltaRemoteTime < oneMS)
  147.         {
  148.                 m_ignoreSnapshot = true;
  149.                 m_catchup = false;
  150.                 return true;
  151.         }
  152.  
  153.         double timeGranularity = m_pWorld->GetPhysVars()->timeGranularity;
  154.  
  155.         // estimate how far we need to go back... the main indicator is the physics delta time
  156.         // but we also adjust to the average ping changing
  157.         CTimeValue stepForward = physDeltaRemoteTime + deltaPing.GetSeconds() * 0.5f;
  158.  
  159.         // now estimate what the local timestamp should be
  160.         int curTimestamp = m_pWorld->GetiPhysicsTime();
  161.         int translatedTimestamp = -1;
  162.         bool resetEstimate = true;
  163.         if (m_physEpochTimestamp != 0)
  164.                 resetEstimate = stepForward > 0.25f || stepForward < 0.0f;
  165.         if (!resetEstimate)
  166.         {
  167.                 m_physEstimatedLocalLaggedTime += stepForward;
  168.         }
  169.         else
  170.         {
  171. emergency_reset:
  172.                 m_physEstimatedLocalLaggedTime = -m_pingEstimate;
  173.                 m_physEpochTimestamp = curTimestamp;
  174.                 m_epochWhen = gEnv->pTimer->GetAsyncTime();
  175.         }
  176.         translatedTimestamp = int(m_physEpochTimestamp + m_physEstimatedLocalLaggedTime.GetSeconds() / timeGranularity + 0.5);
  177.         if (translatedTimestamp >= curTimestamp)
  178.         {
  179.                 m_catchup = false;
  180.                 translatedTimestamp = curTimestamp;
  181.                 if (translatedTimestamp > curTimestamp)
  182.                         CryLog("[phys] time compression occurred (%d ticks)", curTimestamp - translatedTimestamp);
  183.         }
  184.         else
  185.         {
  186.                 m_catchup = stepForward<0.125f && stepForward> 0.0f;
  187.         }
  188.  
  189.         //CRY_ASSERT(translatedTimestamp >= 0);
  190.         if (translatedTimestamp < 0)
  191.                 translatedTimestamp = 0;
  192.         CRY_ASSERT(translatedTimestamp <= curTimestamp);
  193.  
  194.         if (!resetEstimate && (curTimestamp - translatedTimestamp) * timeGranularity > 0.25f + m_pingEstimate.GetSeconds())
  195.         {
  196.                 CryLog("[phys] way out of sync (%.2f seconds)... performing emergency reset", float((curTimestamp - translatedTimestamp) * timeGranularity));
  197.                 m_catchup = false;
  198.                 resetEstimate = true;
  199.                 goto emergency_reset;
  200.         }
  201.  
  202.         m_pWorld->SetiSnapshotTime(translatedTimestamp, 0);
  203.         m_pWorld->SetiSnapshotTime(curTimestamp, 1);
  204.         // TODO: SnapTime()
  205.         m_pWorld->SetiSnapshotTime(curTimestamp, 2);
  206.  
  207.         // store the things that we need to keep
  208.         m_physPrevRemoteTime = physCurRemoteTime;
  209.  
  210.         if (!resetEstimate)
  211.         {
  212.                 // slowly move the epoch time versus the current time towards -pingEstimate/2
  213.                 // avoids a side-case where the local time at epoch startup can completely annihilate any backstepping we might do
  214.                 int deltaTimestamp = curTimestamp - m_physEpochTimestamp;
  215.                 m_physEpochTimestamp = curTimestamp;
  216.                 m_epochWhen = gEnv->pTimer->GetAsyncTime();
  217.                 m_physEstimatedLocalLaggedTime -= CTimeValue(deltaTimestamp * timeGranularity);
  218.  
  219.                 float lagWeight = CalcFrameWeight(CNetworkCVars::Get().PhysSyncLagSmooth);
  220.                 m_physEstimatedLocalLaggedTime = (1.0f - lagWeight) * m_physEstimatedLocalLaggedTime.GetSeconds() - lagWeight * 0.5f * m_pingEstimate.GetSeconds();
  221.         }
  222.  
  223.         if (CNetworkCVars::Get().PhysDebug & 2)
  224.         {
  225.                 if (!m_pDBTL.get())
  226.                         m_pDBTL.reset(new CDebugTimeline());
  227.  
  228.                 CTimeValue loc = m_epochWhen + m_physEstimatedLocalLaggedTime;
  229.                 CTimeValue rem = loc - m_pingEstimate;
  230.                 CTimeValue now = gEnv->pTimer->GetAsyncTime();
  231.                 m_pDBTL->AddEvent(rem, loc, now);
  232.         }
  233.  
  234.         OutputDebug((float)physDeltaRemoteTime.GetMilliSeconds(), (float)deltaPing.GetMilliSeconds(), (float)averagePing.GetMilliSeconds(), (float)curPing.value * 1000.0f, (float)stepForward.GetMilliSeconds(), ((float)curTimestamp - (float)translatedTimestamp) * (float)timeGranularity * 1000.0f);
  235.  
  236.         return true;
  237. }
  238.  
  239. bool CPhysicsSync::OnPacketFooter()
  240. {
  241.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  242.  
  243.         IPersistantDebug* pDbg = 0;
  244.         if (CNetworkCVars::Get().PhysDebug)
  245.         {
  246.                 pDbg = CCryAction::GetCryAction()->GetIPersistantDebug();
  247.         }
  248.  
  249.         if (!m_updatedEntities.empty())
  250.         {
  251.                 pe_params_flags set_update;
  252.                 set_update.flagsOR = pef_update;
  253.  
  254.                 while (!m_updatedEntities.empty())
  255.                 {
  256.                         IEntity* pEntity = pEntitySystem->GetEntity(m_updatedEntities.back());
  257.                         m_updatedEntities.pop_back();
  258.  
  259.                         //temp code
  260.                         continue;
  261.  
  262.                         if (!pEntity)
  263.                                 continue;
  264.                         IPhysicalEntity* pPhysicalEntity = pEntity->GetPhysics();
  265.                         if (!pPhysicalEntity)
  266.                                 continue;
  267.  
  268.                         if (CNetworkCVars::Get().PhysDebug)
  269.                         {
  270.                                 pDbg->Begin(string(pEntity->GetName()) + "_phys0", true);
  271.                                 pe_status_pos p;
  272.                                 pPhysicalEntity->GetStatus(&p);
  273.                                 pDbg->AddSphere(p.pos, 0.5f, ColorF(1, 0, 0, 1), 1.0f);
  274.                         }
  275.  
  276.                         // TODO: Need an elegant way to detect physicalization
  277.                         IActor* pClientActor = CCryAction::GetCryAction()->GetClientActor();
  278.                         if (pClientActor && pClientActor->GetEntity() == pEntity)
  279.                         {
  280.                                 pe_params_flags flags;
  281.                                 flags.flagsOR = pef_log_collisions;
  282.                                 pPhysicalEntity->SetParams(&flags);
  283.                         }
  284.  
  285.                         pe_params_flags flags;
  286.                         pPhysicalEntity->GetParams(&flags);
  287.                         if ((flags.flags & pef_update) == 0)
  288.                         {
  289.                                 pPhysicalEntity->SetParams(&set_update);
  290.                                 m_clearEntities.push_back(pPhysicalEntity);
  291.                         }
  292.                 }
  293.  
  294.                 // more temp code
  295.                 return true;
  296.  
  297. #if 0
  298.                 float step = min(0.3f, m_deltaTime * m_pWorld->GetPhysVars()->timeGranularity);
  299.                 do
  300.                 {
  301.                         float thisStep = min(step, 0.1f);
  302.                         //                      CryLogAlways( "step %f", thisStep );
  303.                         m_pWorld->TimeStep(thisStep, ent_flagged_only);
  304.                         step -= thisStep;
  305.                 }
  306.                 while (step > 0.0001f);
  307.  
  308.                 pe_params_flags clear_update;
  309.                 clear_update.flagsAND = ~pef_update;
  310.                 if (CNetworkCVars::Get().PhysDebug && !m_clearEntities.empty())
  311.                         pDbg->Begin("final_phys", true);
  312.                 while (!m_clearEntities.empty())
  313.                 {
  314.                         if (CNetworkCVars::Get().PhysDebug)
  315.                         {
  316.                                 pe_status_pos p;
  317.                                 m_clearEntities.back()->GetStatus(&p);
  318.                                 pDbg->AddSphere(p.pos, 0.5f, ColorF(0, 0, 1, 1), 1.0f);
  319.                         }
  320.  
  321.                         m_clearEntities.back()->SetParams(&clear_update);
  322.                         m_clearEntities.pop_back();
  323.                 }
  324. #endif
  325.         }
  326.  
  327.         return true;
  328. }
  329.  
  330. void CPhysicsSync::OutputDebug(float deltaPhys, float deltaPing, float averagePing, float ping, float stepForward, float deltaTimestamp)
  331. {
  332.         if (!CNetworkCVars::Get().PhysDebug)
  333.         {
  334.                 for (size_t i = 0; i < m_vpHistories.size(); i++)
  335.                         m_vpHistories[i]->SetVisibility(false);
  336.                 return;
  337.         }
  338.  
  339.         if (!m_pDebugHistory)
  340.                 m_pDebugHistory = gEnv->pGameFramework->CreateDebugHistoryManager();
  341.  
  342.         int nHist = 0;
  343.         IDebugHistory* pHist;
  344.  
  345. #define HISTORY(val)                                                                         \
  346.   if (m_vpHistories.size() <= nHist)                                                         \
  347.   {                                                                                          \
  348.     pHist = m_pDebugHistory->CreateHistory( # val);                                          \
  349.     int y = nHist % 3;                                                                       \
  350.     int x = nHist / 3;                                                                       \
  351.     pHist->SetupLayoutAbs((float)(50 + x * 210), (float)(110 + y * 160), 200.f, 150.f, 5.f); \
  352.     pHist->SetupScopeExtent(-360, +360, -0.01f, +0.01f);                                     \
  353.     m_vpHistories.push_back(pHist);                                                          \
  354.   }                                                                                          \
  355.   else                                                                                       \
  356.     pHist = m_vpHistories[nHist];                                                            \
  357.   nHist++;                                                                                   \
  358.   pHist->AddValue(val);                                                                      \
  359.   pHist->SetVisibility(true)
  360.  
  361.         HISTORY(deltaPhys);
  362.         HISTORY(deltaPing);
  363.         //      HISTORY(averagePing);
  364.         HISTORY(ping);
  365.         float pingEstimate = m_pingEstimate.GetMilliSeconds();
  366.         HISTORY(pingEstimate);
  367.         HISTORY(deltaTimestamp);
  368.         HISTORY(stepForward);
  369. }
  370.  
downloadPhysicsSync.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top