F4MP/tiltedcode/Code/client/Systems/InterpolationSystem.cpp

104 lines
3.1 KiB
C++
Raw Normal View History

#include <TiltedOnlinePCH.h>
#include <Systems/InterpolationSystem.h>
#include <Components.h>
#include <AI/AIProcess.h>
#include <Misc/MiddleProcess.h>
#include <Games/References.h>
#include <World.h>
void InterpolationSystem::Update(Actor* apActor, InterpolationComponent& aInterpolationComponent, const uint64_t aTick) noexcept
{
auto& movements = aInterpolationComponent.TimePoints;
if (movements.size() < 2)
return;
while (movements.size() > 2)
{
const auto second = *(++movements.begin());
if (aTick > second.Tick)
movements.pop_front();
else
break;
}
const auto& first = *(movements.begin());
const auto& second = *(++movements.begin());
// Calculate delta movement since last update
auto delta = 0.0001f;
const auto tickDelta = static_cast<float>(second.Tick - first.Tick);
if (tickDelta > 0.f)
{
delta = 1.f / tickDelta * static_cast<float>(aTick - first.Tick);
}
delta = TiltedPhoques::Min(delta, 1.0f);
const NiPoint3 position{TiltedPhoques::Lerp(first.Position, second.Position, delta)};
aInterpolationComponent.Position = position;
// Don't try to move a null actor
if (!apActor)
return;
apActor->ForcePosition(position);
apActor->LoadAnimationVariables(second.Variables);
if (apActor->currentProcess && apActor->currentProcess->middleProcess)
{
apActor->currentProcess->middleProcess->direction = second.Direction;
}
auto rotA = first.Rotation;
auto rotB = second.Rotation;
const auto deltaX = TiltedPhoques::DeltaAngle(rotA.x, rotB.x, true) * delta;
const auto deltaY = TiltedPhoques::DeltaAngle(rotA.y, rotB.y, true) * delta;
const auto deltaZ = TiltedPhoques::DeltaAngle(rotA.z, rotB.z, true) * delta;
auto finalX = TiltedPhoques::Mod(rotA.x + deltaX, float(TiltedPhoques::Pi * 2));
if (finalX > 0.f && finalX > float(TiltedPhoques::Pi / 2))
finalX -= TiltedPhoques::Pi * 2;
const auto finalY = TiltedPhoques::Mod(rotA.y + deltaY, float(TiltedPhoques::Pi * 2));
const auto finalZ = TiltedPhoques::Mod(rotA.z + deltaZ, float(TiltedPhoques::Pi * 2));
apActor->SetRotation(finalX, finalY, finalZ);
}
void InterpolationSystem::AddPoint(InterpolationComponent& aInterpolationComponent, const InterpolationComponent::TimePoint& acPoint) noexcept
{
auto itor = std::begin(aInterpolationComponent.TimePoints);
const auto end = std::cend(aInterpolationComponent.TimePoints);
while (itor != end)
{
if (itor->Tick > acPoint.Tick)
{
aInterpolationComponent.TimePoints.insert(itor, acPoint);
return;
}
++itor;
}
aInterpolationComponent.TimePoints.push_back(acPoint);
}
InterpolationComponent& InterpolationSystem::Setup(World& aWorld, const entt::entity aEntity) noexcept
{
return aWorld.emplace_or_replace<InterpolationComponent>(aEntity);
}
void InterpolationSystem::Clean(World& aWorld, const entt::entity aEntity) noexcept
{
if (aWorld.all_of<InterpolationComponent>(aEntity))
aWorld.remove<InterpolationComponent>(aEntity);
}