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"
class InterpolationSystem : public PureSystem
class InterpolationSystem : public ImpureSystem
{
public:
InterpolationSystem(SystemParams params);
~InterpolationSystem() { }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
virtual void Update(double dt) override;
private:
struct Transform
template <typename T>
struct Interpolation
{
glm::vec3 Position;
glm::vec3 Scale;
glm::quat Orientation;
float interpolationTime;
Interpolation(const ComponentWrapper& Component, const std::string& Field, const T& Start, const T& Goal)
: Component(Component)
, Field(Field)
, Start(Start)
, Goal(Goal)
{ }
ComponentWrapper Component;
std::string Field;
T Start;
T Goal;
double Alpha = 0.0;
};
std::unordered_map<EntityID, Transform> m_NextTransform;
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
float m_SnapshotInterval;
std::unordered_map<EntityWrapper, Interpolation<glm::vec3>> m_InterpolatePosition;
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>
T vectorInterpolation(T prev, T next, double currentTime)
@@ -44,12 +57,6 @@ private:
T vector = difference * (static_cast<float>(currentTime) / m_SnapshotInterval);
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
+1 -1
View File
@@ -240,7 +240,7 @@ void Server::checkForTimeOuts()
double stopPing = 1000 * m_ConnectedPlayers[i].StopTime /
static_cast<double>(CLOCKS_PER_SEC);
if (startPing > stopPing + m_TimeoutMs) {
LOG_INFO("User %i timed out!", i);
//LOG_INFO("User %i timed out!", 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.
unsigned int updateOrderLevel = 0;
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
++updateOrderLevel;
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
@@ -12,7 +12,11 @@ bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComp
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));
return false;
}
+72 -50
View File
@@ -2,74 +2,96 @@
InterpolationSystem::InterpolationSystem(SystemParams params)
: System(params)
, PureSystem("Transform")
{
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
m_SnapshotInterval = config->Get<float>("Networking.SnapshotInterval", 0.05f);
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
if (!entity.Valid()) {
return;
// Position
for (auto& kv : m_InterpolatePosition) {
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;
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map
m_NextTransform[transform.EntityID].interpolationTime += static_cast<float>(dt);
Transform sTransform = m_NextTransform[transform.EntityID];
float time = sTransform.interpolationTime;
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);
}
// Orientation
for (auto& kv : m_InterpolateOrientation) {
EntityWrapper entity = kv.first;
if (!entity.Valid()) {
continue;
}
if (transform.Info.Name == "Transform") {
// Position
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);
}
}
}
auto& iOrientation = kv.second;
glm::vec3& orientation = iOrientation.Component[iOrientation.Field];
bool InterpolationSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
{
m_LocalPlayer = e.Player;
return true;
iOrientation.Alpha += dt / m_SnapshotInterval;
iOrientation.Alpha = glm::min(iOrientation.Alpha, 1.0);
orientation = glm::eulerAngles(glm::slerp(iOrientation.Start, iOrientation.Goal, (float)iOrientation.Alpha));
}
// 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)
{
// TODO: Make this work for arbitrary component types
if (e.Component.Info.Name == "Transform") {
Transform transform;
transform.Position = e.Component["Position"];
transform.Orientation = glm::quat((glm::vec3)e.Component["Orientation"]);
transform.Scale = e.Component["Scale"];
transform.interpolationTime = 0.0f;
auto cTransform = e.Entity["Transform"];
if (m_NextTransform.find(e.Entity.ID) != m_NextTransform.end()) { // Did exist
m_LastReceivedTransform[e.Entity.ID] = transform;
} else { // Did not
m_NextTransform[e.Entity.ID] = transform;
// Position
Interpolation<glm::vec3> iPosition(
cTransform,
"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;