#include #include #include #include #include #include #include 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(second.Tick - first.Tick); if (tickDelta > 0.f) { delta = 1.f / tickDelta * static_cast(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(aEntity); } void InterpolationSystem::Clean(World& aWorld, const entt::entity aEntity) noexcept { if (aWorld.all_of(aEntity)) aWorld.remove(aEntity); }