Working 1-snapshot interpolation

This commit is contained in:
2016-02-09 16:08:28 +01:00
parent e69864680d
commit d5647ce89c
5 changed files with 103 additions and 69 deletions
+23 -16
View File
@@ -16,26 +16,39 @@
#include "Network/EInterpolate.h" #include "Network/EInterpolate.h"
class InterpolationSystem : public PureSystem class InterpolationSystem : public ImpureSystem
{ {
public: public:
InterpolationSystem(SystemParams params); InterpolationSystem(SystemParams params);
~InterpolationSystem() { } ~InterpolationSystem() { }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override; virtual void Update(double dt) override;
private: private:
struct Transform template <typename T>
struct Interpolation
{ {
glm::vec3 Position; Interpolation(const ComponentWrapper& Component, const std::string& Field, const T& Start, const T& Goal)
glm::vec3 Scale; : Component(Component)
glm::quat Orientation; , Field(Field)
float interpolationTime; , Start(Start)
, Goal(Goal)
{ }
ComponentWrapper Component;
std::string Field;
T Start;
T Goal;
double Alpha = 0.0;
}; };
std::unordered_map<EntityID, Transform> m_NextTransform; float m_SnapshotInterval;
std::unordered_map<EntityID, Transform> m_LastReceivedTransform; std::unordered_map<EntityWrapper, Interpolation<glm::vec3>> m_InterpolatePosition;
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; std::unordered_map<EntityWrapper, Interpolation<glm::quat>> m_InterpolateOrientation;
std::unordered_map<EntityWrapper, Interpolation<glm::vec3>> m_InterpolateVelocity;
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
bool InterpolationSystem::OnInterpolate(Events::Interpolate& e);
template <typename T> template <typename T>
T vectorInterpolation(T prev, T next, double currentTime) T vectorInterpolation(T prev, T next, double currentTime)
@@ -44,12 +57,6 @@ private:
T vector = difference * (static_cast<float>(currentTime) / m_SnapshotInterval); T vector = difference * (static_cast<float>(currentTime) / m_SnapshotInterval);
return vector; return vector;
} }
float m_SnapshotInterval;
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
bool InterpolationSystem::OnInterpolate(Events::Interpolate& e);
EventRelay<InterpolationSystem, Events::PlayerSpawned> m_EPlayerSpawned;
bool OnPlayerSpawned(Events::PlayerSpawned& e);
}; };
#endif #endif
+1 -1
View File
@@ -240,7 +240,7 @@ void Server::checkForTimeOuts()
double stopPing = 1000 * m_ConnectedPlayers[i].StopTime / double stopPing = 1000 * m_ConnectedPlayers[i].StopTime /
static_cast<double>(CLOCKS_PER_SEC); static_cast<double>(CLOCKS_PER_SEC);
if (startPing > stopPing + m_TimeoutMs) { if (startPing > stopPing + m_TimeoutMs) {
LOG_INFO("User %i timed out!", i); //LOG_INFO("User %i timed out!", i);
//disconnect(i); //disconnect(i);
} }
} }
+2 -1
View File
@@ -95,11 +95,12 @@ Game::Game(int argc, char* argv[])
// All systems with orderlevel 0 will be updated first. // All systems with orderlevel 0 will be updated first.
unsigned int updateOrderLevel = 0; unsigned int updateOrderLevel = 0;
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
++updateOrderLevel;
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel); m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
@@ -12,7 +12,11 @@ bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComp
return false; return false;
} }
if (component.Info.Name == "Transform") { if (component.Info.Name == "Physics") {
return false;
}
if (component.Info.Name == "Transform" || component.Info.Name == "Physics") {
m_EventBroker->Publish(Events::Interpolate(entity, component)); m_EventBroker->Publish(Events::Interpolate(entity, component));
return false; return false;
} }
+72 -50
View File
@@ -2,74 +2,96 @@
InterpolationSystem::InterpolationSystem(SystemParams params) InterpolationSystem::InterpolationSystem(SystemParams params)
: System(params) : System(params)
, PureSystem("Transform")
{ {
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini"); ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
m_SnapshotInterval = config->Get<float>("Networking.SnapshotInterval", 0.05f); m_SnapshotInterval = config->Get<float>("Networking.SnapshotInterval", 0.05f);
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate); EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &InterpolationSystem::OnPlayerSpawned);
} }
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) void InterpolationSystem::Update(double dt)
{ {
// Don't interpolate entities that might already have been removed // Position
if (!entity.Valid()) { for (auto& kv : m_InterpolatePosition) {
return; EntityWrapper entity = kv.first;
if (!entity.Valid()) {
continue;
}
auto& iPosition = kv.second;
glm::vec3& position = iPosition.Component[iPosition.Field];
iPosition.Alpha += dt;
float alpha = glm::min(iPosition.Alpha / m_SnapshotInterval, 1.0);
position = iPosition.Start + ((iPosition.Goal - iPosition.Start) * alpha);
} }
//return; // Orientation
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map for (auto& kv : m_InterpolateOrientation) {
m_NextTransform[transform.EntityID].interpolationTime += static_cast<float>(dt); EntityWrapper entity = kv.first;
Transform sTransform = m_NextTransform[transform.EntityID]; if (!entity.Valid()) {
float time = sTransform.interpolationTime; continue;
if (time > m_SnapshotInterval) {
if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) {
m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID];
m_NextTransform[transform.EntityID].interpolationTime = time - m_SnapshotInterval;
sTransform = m_NextTransform[transform.EntityID];
m_LastReceivedTransform.erase(transform.EntityID);
} else {
m_NextTransform.erase(transform.EntityID);
}
} }
if (transform.Info.Name == "Transform") { auto& iOrientation = kv.second;
// Position glm::vec3& orientation = iOrientation.Component[iOrientation.Field];
glm::vec3 nextPosition = sTransform.Position;
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
// Orientation
glm::quat nextOrientation = sTransform.Orientation;
glm::quat currentOrientation = glm::quat(static_cast<glm::vec3>(transform["Orientation"]));
(glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp<float>(currentOrientation, nextOrientation, glm::max(sTransform.interpolationTime / m_SnapshotInterval, 1.f)));
// Scale
glm::vec3 nextScale = sTransform.Scale;
glm::vec3 currentScale = static_cast<glm::vec3>(transform["Scale"]);
(glm::vec3&)transform["Scale"] += vectorInterpolation<glm::vec3>(currentScale, nextScale, sTransform.interpolationTime);
}
}
}
bool InterpolationSystem::OnPlayerSpawned(Events::PlayerSpawned& e) iOrientation.Alpha += dt / m_SnapshotInterval;
{ iOrientation.Alpha = glm::min(iOrientation.Alpha, 1.0);
m_LocalPlayer = e.Player; orientation = glm::eulerAngles(glm::slerp(iOrientation.Start, iOrientation.Goal, (float)iOrientation.Alpha));
return true; }
// Velocity
for (auto& kv : m_InterpolateVelocity) {
EntityWrapper entity = kv.first;
if (!entity.Valid()) {
continue;
}
auto& iVelocity = kv.second;
glm::vec3& position = iVelocity.Component[iVelocity.Field];
iVelocity.Alpha += dt;
float alpha = glm::min(iVelocity.Alpha / m_SnapshotInterval, 1.0);
position = iVelocity.Start + ((iVelocity.Goal - iVelocity.Start) * alpha);
}
} }
bool InterpolationSystem::OnInterpolate(Events::Interpolate& e) bool InterpolationSystem::OnInterpolate(Events::Interpolate& e)
{ {
// TODO: Make this work for arbitrary component types
if (e.Component.Info.Name == "Transform") { if (e.Component.Info.Name == "Transform") {
Transform transform; auto cTransform = e.Entity["Transform"];
transform.Position = e.Component["Position"];
transform.Orientation = glm::quat((glm::vec3)e.Component["Orientation"]);
transform.Scale = e.Component["Scale"];
transform.interpolationTime = 0.0f;
if (m_NextTransform.find(e.Entity.ID) != m_NextTransform.end()) { // Did exist // Position
m_LastReceivedTransform[e.Entity.ID] = transform; Interpolation<glm::vec3> iPosition(
} else { // Did not cTransform,
m_NextTransform[e.Entity.ID] = transform; "Position",
cTransform["Position"],
e.Component["Position"]
);
m_InterpolatePosition.erase(e.Entity);
m_InterpolatePosition.insert(std::make_pair(e.Entity, iPosition));
// Orientation
Interpolation<glm::quat> iOrientation(
cTransform,
"Orientation",
glm::quat((glm::vec3&)cTransform["Orientation"]),
glm::quat((glm::vec3&)e.Component["Orientation"])
);
m_InterpolateOrientation.erase(e.Entity);
m_InterpolateOrientation.insert(std::make_pair(e.Entity, iOrientation));
} else if (e.Component.Info.Name == "Physics") {
auto cPhysics = e.Entity["Physics"];
if (!e.Entity.HasComponent("Player")) {
return false;
} }
// Velocity
Interpolation<glm::vec3> iVelocity(
cPhysics,
"Velocity",
cPhysics["Velocity"],
e.Component["Velocity"]
);
m_InterpolateVelocity.erase(e.Entity);
m_InterpolateVelocity.insert(std::make_pair(e.Entity, iVelocity));
} }
return true; return true;