From 36f1473f3e9f6d81eee68104237377e99c5272aa Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 29 Jan 2018 15:04:01 -1000 Subject: [PATCH] All animation nodes implemented --- Runtime/Character/CAnimTreeBlend.cpp | 59 +++++- Runtime/Character/CAnimTreeBlend.hpp | 2 +- Runtime/Character/CAnimTreeDoubleChild.cpp | 34 ++- Runtime/Character/CAnimTreeLoopIn.cpp | 128 ++++++++++++ Runtime/Character/CAnimTreeLoopIn.hpp | 39 +++- Runtime/Character/CAnimTreeSequence.cpp | 62 +++++- Runtime/Character/CAnimTreeSequence.hpp | 7 +- Runtime/Character/CAnimTreeSingleChild.cpp | 46 +++-- Runtime/Character/CAnimTreeSingleChild.hpp | 2 +- Runtime/Character/CAnimTreeTimeScale.cpp | 205 +++++++++++++++++-- Runtime/Character/CAnimTreeTimeScale.hpp | 27 ++- Runtime/Character/CAnimTreeTransition.hpp | 3 +- Runtime/Character/CAnimationDatabaseGame.cpp | 4 +- Runtime/Character/CCharAnimTime.cpp | 2 +- Runtime/Character/CMetaAnimSequence.cpp | 7 +- Runtime/Character/CMetaTransMetaAnim.cpp | 6 +- Runtime/Character/CMetaTransPhaseTrans.cpp | 28 ++- Runtime/Character/CMetaTransPhaseTrans.hpp | 8 +- Runtime/Character/CSequenceHelper.cpp | 81 +++++++- Runtime/Character/CSequenceHelper.hpp | 9 +- Runtime/Character/CTimeScaleFunctions.cpp | 115 +++++++---- Runtime/Character/CTimeScaleFunctions.hpp | 52 ++--- Runtime/Character/CTreeUtils.cpp | 8 +- Runtime/Character/CTreeUtils.hpp | 4 +- Runtime/Character/IAnimReader.cpp | 9 + Runtime/Character/IAnimReader.hpp | 3 +- Runtime/Particle/CElementGen.cpp | 21 +- Runtime/Weapon/CGunWeapon.cpp | 2 +- Runtime/Weapon/CPlayerGun.cpp | 11 +- Runtime/Weapon/CPlayerGun.hpp | 2 +- Runtime/Weapon/CPowerBeam.cpp | 2 + 31 files changed, 809 insertions(+), 179 deletions(-) diff --git a/Runtime/Character/CAnimTreeBlend.cpp b/Runtime/Character/CAnimTreeBlend.cpp index e0d4b36a8..e82b85063 100644 --- a/Runtime/Character/CAnimTreeBlend.cpp +++ b/Runtime/Character/CAnimTreeBlend.cpp @@ -19,33 +19,80 @@ CAnimTreeBlend::CAnimTreeBlend(bool b1, } -SAdvancementResults CAnimTreeBlend::VAdvanceView(const CCharAnimTime& a) +SAdvancementResults CAnimTreeBlend::VAdvanceView(const CCharAnimTime& dt) { - return {}; + IncAdvancementDepth(); + SAdvancementResults resA = x14_a->VAdvanceView(dt); + SAdvancementResults resB = x18_b->VAdvanceView(dt); + DecAdvancementDepth(); + if (ShouldCullTree()) + { + if (GetBlendingWeight() < 0.5f) + x20_25_cullSelector = 1; + else + x20_25_cullSelector = 2; + } + + const SAdvancementResults& maxRemTime = (resA.x0_remTime < resB.x0_remTime) ? resB : resA; + if (x1c_flags & 0x1) + { + return {maxRemTime.x0_remTime, SAdvancementDeltas::Blend(resA.x8_deltas, resB.x8_deltas, + GetBlendingWeight())}; + } + else + { + return resB; + } } CCharAnimTime CAnimTreeBlend::VGetTimeRemaining() const { - return {}; + CCharAnimTime remA = x14_a->VGetTimeRemaining(); + CCharAnimTime remB = x18_b->VGetTimeRemaining(); + return (remA < remB) ? remB : remA; } CSteadyStateAnimInfo CAnimTreeBlend::VGetSteadyStateAnimInfo() const { - return {}; + CSteadyStateAnimInfo ssA = x14_a->VGetSteadyStateAnimInfo(); + CSteadyStateAnimInfo ssB = x18_b->VGetSteadyStateAnimInfo(); + zeus::CVector3f resOffset; + if (ssA.GetDuration() < ssB.GetDuration()) + { + resOffset = ssA.GetOffset() * (ssB.GetDuration() / ssA.GetDuration()) * x24_blendWeight + + ssB.GetOffset() * (1.f - x24_blendWeight); + } + else if (ssB.GetDuration() < ssA.GetDuration()) + { + resOffset = ssA.GetOffset() * x24_blendWeight + + ssB.GetOffset() * (ssA.GetDuration() / ssB.GetDuration()) * (1.f - x24_blendWeight); + } + else + { + resOffset = ssA.GetOffset() + ssB.GetOffset(); + } + + return {ssA.IsLooping(), + (ssA.GetDuration() < ssB.GetDuration()) ? ssB.GetDuration() : ssA.GetDuration(), + resOffset}; } std::unique_ptr CAnimTreeBlend::VClone() const { - return {}; + return std::make_unique(x20_24_b1, + CAnimTreeNode::Cast(x14_a->Clone()), + CAnimTreeNode::Cast(x18_b->Clone()), + x24_blendWeight, x4_name); } void CAnimTreeBlend::SetBlendingWeight(float w) { + x24_blendWeight = w; } float CAnimTreeBlend::VGetBlendingWeight() const { - return 0.f; + return x24_blendWeight; } } diff --git a/Runtime/Character/CAnimTreeBlend.hpp b/Runtime/Character/CAnimTreeBlend.hpp index 7308e40e6..01075aae0 100644 --- a/Runtime/Character/CAnimTreeBlend.hpp +++ b/Runtime/Character/CAnimTreeBlend.hpp @@ -19,7 +19,7 @@ public: const std::shared_ptr& b, float blendWeight, std::string_view name); - SAdvancementResults VAdvanceView(const CCharAnimTime& a); + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); CCharAnimTime VGetTimeRemaining() const; CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; std::unique_ptr VClone() const; diff --git a/Runtime/Character/CAnimTreeDoubleChild.cpp b/Runtime/Character/CAnimTreeDoubleChild.cpp index 5f0dc721e..cd786b82e 100644 --- a/Runtime/Character/CAnimTreeDoubleChild.cpp +++ b/Runtime/Character/CAnimTreeDoubleChild.cpp @@ -128,33 +128,55 @@ CParticleData::EParentedMode CAnimTreeDoubleChild::VGetParticlePOIState(const ch return x18_b->VGetParticlePOIState(name); } -void CAnimTreeDoubleChild::VSetPhase(float) +void CAnimTreeDoubleChild::VSetPhase(float phase) { + x14_a->VSetPhase(phase); + x18_b->VSetPhase(phase); } SAdvancementResults CAnimTreeDoubleChild::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const { - return {}; + SAdvancementResults resA = x14_a->VGetAdvancementResults(a, b); + SAdvancementResults resB = x18_b->VGetAdvancementResults(a, b); + return (resA.x0_remTime > resB.x0_remTime) ? resA : resB; } u32 CAnimTreeDoubleChild::Depth() const { - return 0; + return std::max(x14_a->Depth(), x18_b->Depth()) + 1; } CAnimTreeEffectiveContribution CAnimTreeDoubleChild::VGetContributionOfHighestInfluence() const { - return {0.f, "", CSteadyStateAnimInfo(), CCharAnimTime(), 0}; + CAnimTreeEffectiveContribution cA = x14_a->GetContributionOfHighestInfluence(); + CAnimTreeEffectiveContribution cB = x18_b->GetContributionOfHighestInfluence(); + + float leftWeight = (1.f - VGetRightChildWeight()) * cA.GetContributionWeight(); + float rightWeight = VGetRightChildWeight() * cB.GetContributionWeight(); + + if (leftWeight > rightWeight) + { + return {leftWeight, cA.GetPrimitiveName(), cA.GetSteadyStateAnimInfo(), + cA.GetTimeRemaining(), cA.GetAnimDatabaseIndex()}; + } + else + { + return {rightWeight, cB.GetPrimitiveName(), cB.GetSteadyStateAnimInfo(), + cB.GetTimeRemaining(), cB.GetAnimDatabaseIndex()}; + } } u32 CAnimTreeDoubleChild::VGetNumChildren() const { - return 0; + return x14_a->VGetNumChildren() + x18_b->VGetNumChildren() + 2; } std::shared_ptr CAnimTreeDoubleChild::VGetBestUnblendedChild() const { - return {}; + std::shared_ptr bestChild = (VGetRightChildWeight() > 0.5f) ? x18_b : x14_a; + if (!bestChild) + return {}; + return bestChild->GetBestUnblendedChild(); } void CAnimTreeDoubleChild::VGetWeightedReaders( diff --git a/Runtime/Character/CAnimTreeLoopIn.cpp b/Runtime/Character/CAnimTreeLoopIn.cpp index e69de29bb..b7ab4a112 100644 --- a/Runtime/Character/CAnimTreeLoopIn.cpp +++ b/Runtime/Character/CAnimTreeLoopIn.cpp @@ -0,0 +1,128 @@ +#include "CAnimTreeLoopIn.hpp" +#include "CTreeUtils.hpp" + +namespace urde +{ + +std::string CAnimTreeLoopIn::CreatePrimitiveName(const std::weak_ptr& a, + const std::weak_ptr& b, + const std::weak_ptr& c) +{ + return {}; +} + +CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr& a, + const std::weak_ptr& b, + const std::weak_ptr& c, + const CAnimSysContext& animCtx, + std::string_view name) +: CAnimTreeSingleChild(CTreeUtils::GetTransitionTree(a, c, animCtx), name), + x18_nextAnim(b.lock()), x20_animCtx(animCtx), + x30_fundamentals(CSequenceHelper(x14_child, x18_nextAnim, animCtx).ComputeSequenceFundamentals()) +{ +} + +CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr& a, + const std::weak_ptr& b, + bool didLoopIn, + const CAnimSysContext& animCtx, + std::string_view name, + const CSequenceFundamentals& fundamentals, + const CCharAnimTime& time) +: CAnimTreeSingleChild(a, name), x18_nextAnim(b.lock()), x1c_didLoopIn(didLoopIn), x20_animCtx(animCtx), + x30_fundamentals(fundamentals), x88_curTime(time) +{ +} + +CAnimTreeEffectiveContribution CAnimTreeLoopIn::VGetContributionOfHighestInfluence() const +{ + return x14_child->GetContributionOfHighestInfluence(); +} + +std::experimental::optional> CAnimTreeLoopIn::VSimplified() +{ + CCharAnimTime remTime = x14_child->VGetTimeRemaining(); + if (remTime.GreaterThanZero() && !remTime.EpsilonZero()) + { + auto simp = x14_child->Simplified(); + if (simp) + x14_child = CAnimTreeNode::Cast(std::move(*simp)); + } + else if (x1c_didLoopIn && x14_child->VGetTimeRemaining().EqualsZero()) + { + return x14_child->Clone(); + } + return {}; +} + +std::shared_ptr CAnimTreeLoopIn::VGetBestUnblendedChild() const +{ + if (std::shared_ptr bestChild = x14_child->GetBestUnblendedChild()) + { + return std::make_shared(CAnimTreeNode::Cast(bestChild->Clone()), + x18_nextAnim, x1c_didLoopIn, x20_animCtx, x4_name, + x30_fundamentals, x88_curTime); + } + return {}; +} + +std::unique_ptr CAnimTreeLoopIn::VClone() const +{ + return std::make_unique(CAnimTreeNode::Cast(x14_child->Clone()), + x18_nextAnim, x1c_didLoopIn, x20_animCtx, x4_name, + x30_fundamentals, x88_curTime); +} + +u32 CAnimTreeLoopIn::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, + u32 capacity, u32 iterator, u32 unk) const +{ + return _getPOIList(time, listOut, capacity, iterator, unk, + x30_fundamentals.GetBoolPointsOfInterest(), x88_curTime); +} + +u32 CAnimTreeLoopIn::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, + u32 capacity, u32 iterator, u32 unk) const +{ + return _getPOIList(time, listOut, capacity, iterator, unk, + x30_fundamentals.GetInt32PointsOfInterest(), x88_curTime); +} + +u32 CAnimTreeLoopIn::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, + u32 capacity, u32 iterator, u32 unk) const +{ + return _getPOIList(time, listOut, capacity, iterator, unk, + x30_fundamentals.GetParticlePointsOfInterest(), x88_curTime); +} + +u32 CAnimTreeLoopIn::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, + u32 capacity, u32 iterator, u32 unk) const +{ + return _getPOIList(time, listOut, capacity, iterator, unk, + x30_fundamentals.GetSoundPointsOfInterest(), x88_curTime); +} + +CSteadyStateAnimInfo CAnimTreeLoopIn::VGetSteadyStateAnimInfo() const +{ + return x30_fundamentals.GetSteadyStateAnimInfo(); +} + +CCharAnimTime CAnimTreeLoopIn::VGetTimeRemaining() const +{ + return x30_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x88_curTime; +} + +SAdvancementResults CAnimTreeLoopIn::VAdvanceView(const CCharAnimTime& dt) +{ + std::shared_ptr origChild = x14_child; + SAdvancementResults res = origChild->VAdvanceView(dt); + x88_curTime += dt - res.x0_remTime; + CCharAnimTime remTime = origChild->VGetTimeRemaining(); + if ((remTime.EpsilonZero() || (dt - res.x0_remTime).EpsilonZero()) && !x1c_didLoopIn) + { + x14_child = CTreeUtils::GetTransitionTree(origChild, x18_nextAnim, x20_animCtx); + x1c_didLoopIn = true; + } + return res; +} + +} \ No newline at end of file diff --git a/Runtime/Character/CAnimTreeLoopIn.hpp b/Runtime/Character/CAnimTreeLoopIn.hpp index 36bdce21f..4fd340c85 100644 --- a/Runtime/Character/CAnimTreeLoopIn.hpp +++ b/Runtime/Character/CAnimTreeLoopIn.hpp @@ -1,11 +1,48 @@ #ifndef __URDE_CANIMTREELOOPIN_HPP__ #define __URDE_CANIMTREELOOPIN_HPP__ +#include "CAnimTreeSingleChild.hpp" +#include "CAnimSysContext.hpp" +#include "CSequenceHelper.hpp" + namespace urde { -class CAnimTreeLoopIn +class CAnimTreeLoopIn : public CAnimTreeSingleChild { + std::shared_ptr x18_nextAnim; + bool x1c_didLoopIn = false; + CAnimSysContext x20_animCtx; + CSequenceFundamentals x30_fundamentals; + CCharAnimTime x88_curTime; +public: + static std::string CreatePrimitiveName(const std::weak_ptr& a, + const std::weak_ptr& b, + const std::weak_ptr& c); + CAnimTreeLoopIn(const std::weak_ptr& a, + const std::weak_ptr& b, + const std::weak_ptr& c, + const CAnimSysContext& animCtx, + std::string_view name); + CAnimTreeLoopIn(const std::weak_ptr& a, + const std::weak_ptr& b, + bool didLoopIn, + const CAnimSysContext& animCtx, + std::string_view name, + const CSequenceFundamentals& fundamentals, + const CCharAnimTime& time); + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + bool VSupportsReverseView() const { return false; } + std::experimental::optional> VSimplified(); + std::shared_ptr VGetBestUnblendedChild() const; + std::unique_ptr VClone() const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + CCharAnimTime VGetTimeRemaining() const; + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); }; } diff --git a/Runtime/Character/CAnimTreeSequence.cpp b/Runtime/Character/CAnimTreeSequence.cpp index b7cc93fb3..ac5df458d 100644 --- a/Runtime/Character/CAnimTreeSequence.cpp +++ b/Runtime/Character/CAnimTreeSequence.cpp @@ -1,6 +1,7 @@ #include "CAnimTreeSequence.hpp" #include "IMetaAnim.hpp" #include "CAnimSysContext.hpp" +#include "CTreeUtils.hpp" namespace urde { @@ -9,7 +10,8 @@ CAnimTreeSequence::CAnimTreeSequence(const std::vectorGetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()), name), - x18_(animSys), x3c_fundamentals(CSequenceHelper(seq, animSys).ComputeSequenceFundamentals()), x94_curTime(0.f) + x18_animCtx(animSys), x28_sequence(seq), + x3c_fundamentals(CSequenceHelper(seq, animSys).ComputeSequenceFundamentals()), x94_curTime(0.f) { } @@ -19,7 +21,8 @@ CAnimTreeSequence::CAnimTreeSequence(const std::shared_ptr& curNo std::string_view name, const CSequenceFundamentals& fundamentals, const CCharAnimTime& time) -: CAnimTreeSingleChild(curNode, name), x18_(animSys), x28_(metaAnims), x3c_fundamentals(fundamentals), x94_curTime(time) +: CAnimTreeSingleChild(curNode, name), x18_animCtx(animSys), x28_sequence(metaAnims), + x3c_fundamentals(fundamentals), x94_curTime(time) { } @@ -35,17 +38,62 @@ std::shared_ptr CAnimTreeSequence::VGetBestUnblendedChild() const return ch; return std::make_shared(std::static_pointer_cast( std::shared_ptr(ch->Clone())), - x28_, x18_, x4_name, x3c_fundamentals, x94_curTime); + x28_sequence, x18_animCtx, x4_name, x3c_fundamentals, x94_curTime); } -SAdvancementResults CAnimTreeSequence::VAdvanceView(const CCharAnimTime& a) +SAdvancementResults CAnimTreeSequence::VAdvanceView(const CCharAnimTime& dt) { - return {}; + CCharAnimTime totalDelta; + zeus::CVector3f posDelta; + zeus::CQuaternion rotDelta; + + std::shared_ptr curChild = x14_child; + if (x38_curIdx >= x28_sequence.size() && curChild->VGetTimeRemaining().EqualsZero()) + { + x3c_fundamentals = CSequenceHelper(x28_sequence, x18_animCtx).ComputeSequenceFundamentals(); + x38_curIdx = 0; + x14_child = CTreeUtils::GetTransitionTree(curChild, x28_sequence[x38_curIdx]->GetAnimationTree( + x18_animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders()), x18_animCtx); + curChild = x14_child; + } + + CCharAnimTime remTime = dt; + while (remTime.GreaterThanZero() && x38_curIdx < x28_sequence.size()) + { + CCharAnimTime chRem = curChild->VGetTimeRemaining(); + if (chRem.EqualsZero()) + { + ++x38_curIdx; + if (x38_curIdx < x28_sequence.size()) + { + x14_child = CTreeUtils::GetTransitionTree(curChild, x28_sequence[x38_curIdx]->GetAnimationTree( + x18_animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders()), x18_animCtx); + } + } + curChild = x14_child; + if (x38_curIdx < x28_sequence.size()) + { + SAdvancementResults res = curChild->VAdvanceView(remTime); + if (auto simp = curChild->Simplified()) + { + curChild = CAnimTreeNode::Cast(std::move(*simp)); + x14_child = curChild; + } + CCharAnimTime prevRemTime = remTime; + remTime = res.x0_remTime; + totalDelta += prevRemTime - remTime; + posDelta += res.x8_deltas.x0_posDelta; + rotDelta = rotDelta * res.x8_deltas.xc_rotDelta; + } + } + + x94_curTime += totalDelta; + return {dt - totalDelta, {posDelta, rotDelta}}; } CCharAnimTime CAnimTreeSequence::VGetTimeRemaining() const { - if (x38_curIdx == x28_.size() - 1) + if (x38_curIdx == x28_sequence.size() - 1) return x14_child->VGetTimeRemaining(); return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime.GetSeconds(); } @@ -87,7 +135,7 @@ std::unique_ptr CAnimTreeSequence::VClone() const { return std::make_unique(std::static_pointer_cast( std::shared_ptr(x14_child->Clone())), - x28_, x18_, x4_name, x3c_fundamentals, x94_curTime); + x28_sequence, x18_animCtx, x4_name, x3c_fundamentals, x94_curTime); } } diff --git a/Runtime/Character/CAnimTreeSequence.hpp b/Runtime/Character/CAnimTreeSequence.hpp index a02138c9a..68536cc96 100644 --- a/Runtime/Character/CAnimTreeSequence.hpp +++ b/Runtime/Character/CAnimTreeSequence.hpp @@ -12,8 +12,8 @@ class CTransitionDatabaseGame; class CAnimTreeSequence : public CAnimTreeSingleChild { - CAnimSysContext x18_; - std::vector> x28_; + CAnimSysContext x18_animCtx; + std::vector> x28_sequence; u32 x38_curIdx = 0; CSequenceFundamentals x3c_fundamentals; CCharAnimTime x94_curTime; @@ -30,8 +30,9 @@ public: CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; std::shared_ptr VGetBestUnblendedChild() const; + bool VSupportsReverseView() const { return false; } - SAdvancementResults VAdvanceView(const CCharAnimTime& a); + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); CCharAnimTime VGetTimeRemaining() const; CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; diff --git a/Runtime/Character/CAnimTreeSingleChild.cpp b/Runtime/Character/CAnimTreeSingleChild.cpp index 151259d2d..8a3d4e8a6 100644 --- a/Runtime/Character/CAnimTreeSingleChild.cpp +++ b/Runtime/Character/CAnimTreeSingleChild.cpp @@ -7,107 +7,109 @@ CAnimTreeSingleChild::CAnimTreeSingleChild(const std::weak_ptr& n : CAnimTreeNode(name) , x14_child(node.lock()) { - } -SAdvancementResults CAnimTreeSingleChild::VAdvanceView(const CCharAnimTime& a) +SAdvancementResults CAnimTreeSingleChild::VAdvanceView(const CCharAnimTime& dt) { - return {}; + return x14_child->VAdvanceView(dt); } CCharAnimTime CAnimTreeSingleChild::VGetTimeRemaining() const { - return {}; + return x14_child->VGetTimeRemaining(); } bool CAnimTreeSingleChild::VHasOffset(const CSegId& seg) const { - return false; + return x14_child->VHasOffset(seg); } zeus::CVector3f CAnimTreeSingleChild::VGetOffset(const CSegId& seg) const { - return {}; + return x14_child->VGetOffset(seg); } zeus::CQuaternion CAnimTreeSingleChild::VGetRotation(const CSegId& seg) const { - return {}; + return x14_child->VGetRotation(seg); } u32 CAnimTreeSingleChild::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32) const + u32 capacity, u32 iterator, u32 unk) const { - return 0; + return x14_child->GetBoolPOIList(time, listOut, capacity, iterator, unk); } u32 CAnimTreeSingleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, - u32 capacity, u32 iterator, u32) const + u32 capacity, u32 iterator, u32 unk) const { - return 0; + return x14_child->GetInt32POIList(time, listOut, capacity, iterator, unk); } u32 CAnimTreeSingleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32) const + u32 capacity, u32 iterator, u32 unk) const { - return 0; + return x14_child->GetParticlePOIList(time, listOut, capacity, iterator, unk); } u32 CAnimTreeSingleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32) const + u32 capacity, u32 iterator, u32 unk) const { - return 0; + return x14_child->GetSoundPOIList(time, listOut, capacity, iterator, unk); } bool CAnimTreeSingleChild::VGetBoolPOIState(const char* name) const { - return false; + return x14_child->VGetBoolPOIState(name); } s32 CAnimTreeSingleChild::VGetInt32POIState(const char* name) const { - return -1; + return x14_child->VGetInt32POIState(name); } CParticleData::EParentedMode CAnimTreeSingleChild::VGetParticlePOIState(const char* name) const { - return CParticleData::EParentedMode::Initial; + return x14_child->VGetParticlePOIState(name); } void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const { + x14_child->VGetSegStatementSet(list, setOut); } void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const { + x14_child->VGetSegStatementSet(list, setOut, time); } -void CAnimTreeSingleChild::VSetPhase(float) +void CAnimTreeSingleChild::VSetPhase(float phase) { + x14_child->VSetPhase(phase); } SAdvancementResults CAnimTreeSingleChild::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const { - return {}; + return x14_child->VGetAdvancementResults(a, b); } u32 CAnimTreeSingleChild::Depth() const { - return 1; + return x14_child->Depth() + 1; } u32 CAnimTreeSingleChild::VGetNumChildren() const { - return 0; + return x14_child->VGetNumChildren() + 1; } } diff --git a/Runtime/Character/CAnimTreeSingleChild.hpp b/Runtime/Character/CAnimTreeSingleChild.hpp index 61cc47a7c..6fa14e530 100644 --- a/Runtime/Character/CAnimTreeSingleChild.hpp +++ b/Runtime/Character/CAnimTreeSingleChild.hpp @@ -13,7 +13,7 @@ protected: public: CAnimTreeSingleChild(const std::weak_ptr& node, std::string_view name); - SAdvancementResults VAdvanceView(const CCharAnimTime& a); + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); CCharAnimTime VGetTimeRemaining() const; bool VHasOffset(const CSegId& seg) const; zeus::CVector3f VGetOffset(const CSegId& seg) const; diff --git a/Runtime/Character/CAnimTreeTimeScale.cpp b/Runtime/Character/CAnimTreeTimeScale.cpp index 71b6737f3..14317abc4 100644 --- a/Runtime/Character/CAnimTreeTimeScale.cpp +++ b/Runtime/Character/CAnimTreeTimeScale.cpp @@ -5,11 +5,22 @@ namespace urde CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr& node, float scale, std::string_view name) - : CAnimTreeSingleChild(node, name) - , x18_timeScale(new CConstantAnimationTimeScale(scale)) +: CAnimTreeSingleChild(node, name) +, x18_timeScale(new CConstantAnimationTimeScale(scale)) +, x28_targetAccelTime(CCharAnimTime::Infinity()) { } +CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr& node, + std::unique_ptr&& timeScale, + const CCharAnimTime& time, std::string_view name) +: CAnimTreeSingleChild(node, name) +, x18_timeScale(std::move(timeScale)) +, x28_targetAccelTime(time) +{ + x30_initialTime = x14_child->VGetSteadyStateAnimInfo().GetDuration() - x14_child->VGetTimeRemaining(); +} + std::string CAnimTreeTimeScale::CreatePrimitiveName(const std::weak_ptr&, float, const CCharAnimTime&, float) { @@ -20,26 +31,26 @@ CCharAnimTime CAnimTreeTimeScale::GetRealLifeTime(const CCharAnimTime& time) con { CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); - CCharAnimTime tmp = std::min(timeRem, time); - if (x28_ > CCharAnimTime()) + CCharAnimTime ret = std::min(timeRem, time); + if (x28_targetAccelTime > CCharAnimTime()) { - if (tmp < CCharAnimTime(x28_ * x20_)) - return x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(), - (x20_ + tmp).GetSeconds()); + if (ret < CCharAnimTime(x28_targetAccelTime - x20_curAccelTime)) + return x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), + (x20_curAccelTime + ret).GetSeconds()); else { CCharAnimTime integral = - x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(), x28_.GetSeconds()); + x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), x28_targetAccelTime.GetSeconds()); - if (integral > tmp) - return x18_timeScale->VFindUpperLimit(x20_.GetSeconds(), tmp.GetSeconds()) * - x20_.GetSeconds(); + if (integral > ret) + return x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), ret.GetSeconds()) - + x20_curAccelTime.GetSeconds(); else - return integral + (integral * tmp); + return integral + (ret - integral); } } - return tmp; + return ret; } void CAnimTreeTimeScale::VSetPhase(float phase) @@ -49,7 +60,175 @@ void CAnimTreeTimeScale::VSetPhase(float phase) std::experimental::optional> CAnimTreeTimeScale::VSimplified() { + if (auto simp = x14_child->Simplified()) + { + CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(std::move(*simp)), + x18_timeScale->Clone(), x28_targetAccelTime, x4_name); + newNode->x20_curAccelTime = x20_curAccelTime; + newNode->x30_initialTime = x30_initialTime; + return {std::unique_ptr(newNode)}; + } + else if (x20_curAccelTime == x28_targetAccelTime) + { + return {x14_child->Clone()}; + } return {}; } +u32 CAnimTreeTimeScale::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, + u32 capacity, u32 iterator, u32 unk) const +{ + CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ? + x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetBoolPOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i=0 ; iVGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetInt32POIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i=0 ; iVGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetParticlePOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i=0 ; iVGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetSoundPOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i=0 ; iVGetBoolPOIState(name); +} + +s32 CAnimTreeTimeScale::VGetInt32POIState(const char* name) const +{ + return x14_child->VGetInt32POIState(name); +} + +CParticleData::EParentedMode CAnimTreeTimeScale::VGetParticlePOIState(const char* name) const +{ + return x14_child->VGetParticlePOIState(name); +} + +CAnimTreeEffectiveContribution CAnimTreeTimeScale::VGetContributionOfHighestInfluence() const +{ + CAnimTreeEffectiveContribution c = x14_child->VGetContributionOfHighestInfluence(); + return {c.GetContributionWeight(), c.GetPrimitiveName(), VGetSteadyStateAnimInfo(), + VGetTimeRemaining(), c.GetAnimDatabaseIndex()}; +} + +std::shared_ptr CAnimTreeTimeScale::VGetBestUnblendedChild() const +{ + if (std::shared_ptr bestChild = x14_child->VGetBestUnblendedChild()) + { + CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(bestChild->Clone()), + x18_timeScale->Clone(), x28_targetAccelTime, x4_name); + newNode->x20_curAccelTime = x20_curAccelTime; + newNode->x30_initialTime = x30_initialTime; + return {std::shared_ptr(newNode)}; + } + return {}; +} + +std::unique_ptr CAnimTreeTimeScale::VClone() const +{ + CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(x14_child->Clone()), + x18_timeScale->Clone(), x28_targetAccelTime, x4_name); + newNode->x20_curAccelTime = x20_curAccelTime; + newNode->x30_initialTime = x30_initialTime; + return {std::unique_ptr(newNode)}; +} + +CSteadyStateAnimInfo CAnimTreeTimeScale::VGetSteadyStateAnimInfo() const +{ + CSteadyStateAnimInfo ssInfo = x14_child->VGetSteadyStateAnimInfo(); + if (x28_targetAccelTime == CCharAnimTime::Infinity()) + { + return {ssInfo.IsLooping(), + x18_timeScale->VFindUpperLimit(0.f, ssInfo.GetDuration().GetSeconds()), ssInfo.GetOffset()}; + } + else + { + CCharAnimTime time; + if (x20_curAccelTime.GreaterThanZero()) + time = x18_timeScale->VTimeScaleIntegral(0.f, x20_curAccelTime.GetSeconds()); + return {ssInfo.IsLooping(), x30_initialTime + time + VGetTimeRemaining(), ssInfo.GetOffset()}; + } +} + +CCharAnimTime CAnimTreeTimeScale::VGetTimeRemaining() const +{ + CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); + if (x28_targetAccelTime == CCharAnimTime::Infinity()) + return CCharAnimTime(x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), + timeRem.GetSeconds())) - x20_curAccelTime; + else + return GetRealLifeTime(timeRem); +} + +SAdvancementResults CAnimTreeTimeScale::VAdvanceView(const CCharAnimTime& dt) +{ + if (dt.EqualsZero() && dt > CCharAnimTime()) + return x14_child->VAdvanceView(dt); + + CCharAnimTime origAccelTime = x20_curAccelTime; + CCharAnimTime newTime = x20_curAccelTime + dt; + if (newTime < x28_targetAccelTime) + { + SAdvancementResults res = x14_child->VAdvanceView( + x18_timeScale->VTimeScaleIntegral(origAccelTime.GetSeconds(), newTime.GetSeconds())); + if (res.x0_remTime.EqualsZero()) + { + x20_curAccelTime = newTime; + res.x0_remTime = CCharAnimTime(); + return res; + } + else + { + x20_curAccelTime = x18_timeScale->VFindUpperLimit(origAccelTime.GetSeconds(), + (newTime - res.x0_remTime).GetSeconds()); + res.x0_remTime = dt - (x20_curAccelTime - origAccelTime); + return res; + } + } + else + { + CCharAnimTime newDt(x18_timeScale->VTimeScaleIntegral(origAccelTime.GetSeconds(), + x28_targetAccelTime.GetSeconds())); + SAdvancementResults res2; + if (newDt.GreaterThanZero()) + res2 = x14_child->VAdvanceView(newDt); + res2.x0_remTime = res2.x0_remTime + (newTime - x28_targetAccelTime); + return res2; + } +} + } diff --git a/Runtime/Character/CAnimTreeTimeScale.hpp b/Runtime/Character/CAnimTreeTimeScale.hpp index 28c0e73d0..41a95f01a 100644 --- a/Runtime/Character/CAnimTreeTimeScale.hpp +++ b/Runtime/Character/CAnimTreeTimeScale.hpp @@ -9,17 +9,36 @@ namespace urde class CAnimTreeTimeScale : public CAnimTreeSingleChild { - std::shared_ptr x18_timeScale; - CCharAnimTime x20_; - CCharAnimTime x28_; + std::unique_ptr x18_timeScale; + CCharAnimTime x20_curAccelTime; + CCharAnimTime x28_targetAccelTime; + CCharAnimTime x30_initialTime; public: - CAnimTreeTimeScale(const std::weak_ptr&, float, std::string_view); + CAnimTreeTimeScale(const std::weak_ptr& node, float timeScale, std::string_view name); + CAnimTreeTimeScale(const std::weak_ptr& node, + std::unique_ptr&& timeScale, + const CCharAnimTime& time, std::string_view name); static std::string CreatePrimitiveName(const std::weak_ptr&, float, const CCharAnimTime&, float); CCharAnimTime GetRealLifeTime(const CCharAnimTime&) const; void VSetPhase(float); std::experimental::optional> VSimplified(); + + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + bool VGetBoolPOIState(const char* name) const; + s32 VGetInt32POIState(const char* name) const; + CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; + + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + std::shared_ptr VGetBestUnblendedChild() const; + std::unique_ptr VClone() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + CCharAnimTime VGetTimeRemaining() const; + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); }; } diff --git a/Runtime/Character/CAnimTreeTransition.hpp b/Runtime/Character/CAnimTreeTransition.hpp index 5f91214f2..9cc51cc21 100644 --- a/Runtime/Character/CAnimTreeTransition.hpp +++ b/Runtime/Character/CAnimTreeTransition.hpp @@ -17,7 +17,8 @@ protected: bool x36_initialized = false; SAdvancementResults AdvanceViewForTransitionalPeriod(const CCharAnimTime& time); public: - static std::string CreatePrimitiveName(const std::weak_ptr&, const std::weak_ptr&, + static std::string CreatePrimitiveName(const std::weak_ptr&, + const std::weak_ptr&, float); CAnimTreeTransition(bool b1, const std::weak_ptr& a, diff --git a/Runtime/Character/CAnimationDatabaseGame.cpp b/Runtime/Character/CAnimationDatabaseGame.cpp index fb0012855..0a3884616 100644 --- a/Runtime/Character/CAnimationDatabaseGame.cpp +++ b/Runtime/Character/CAnimationDatabaseGame.cpp @@ -40,6 +40,8 @@ void CAnimationDatabaseGame::GetAllUniquePrimitives(std::vector& pri void CAnimationDatabaseGame::GetUniquePrimitivesFromMetaAnim(std::set& primsOut, std::string_view name) const -{} +{ + // Empty +} } diff --git a/Runtime/Character/CCharAnimTime.cpp b/Runtime/Character/CCharAnimTime.cpp index 63d221747..38bb748c1 100644 --- a/Runtime/Character/CCharAnimTime.cpp +++ b/Runtime/Character/CCharAnimTime.cpp @@ -16,7 +16,7 @@ CCharAnimTime CCharAnimTime::Infinity() bool CCharAnimTime::EqualsZero() const { if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing) - return false; + return true; return (x0_time == 0.f); } diff --git a/Runtime/Character/CMetaAnimSequence.cpp b/Runtime/Character/CMetaAnimSequence.cpp index d090609d8..ba5233d76 100644 --- a/Runtime/Character/CMetaAnimSequence.cpp +++ b/Runtime/Character/CMetaAnimSequence.cpp @@ -37,10 +37,15 @@ CMetaAnimSequence::VGetAnimationTree(const CAnimSysContext& animSys, return GetAnimationTree(animSys, modOrders); } +#if 0 + std::vector anims; + anims.reserve(anims.size()); for (const std::shared_ptr& anim : x4_sequence) { - + std::shared_ptr chNode = anim->GetAnimationTree(animSys, orders); + anims.emplace_back(chNode->GetName()); } +#endif std::shared_ptr ret = std::make_shared(x4_sequence, animSys, ""); diff --git a/Runtime/Character/CMetaTransMetaAnim.cpp b/Runtime/Character/CMetaTransMetaAnim.cpp index 740d78095..de2e4c610 100644 --- a/Runtime/Character/CMetaTransMetaAnim.cpp +++ b/Runtime/Character/CMetaTransMetaAnim.cpp @@ -1,5 +1,6 @@ #include "CMetaTransMetaAnim.hpp" #include "CMetaAnimFactory.hpp" +#include "CAnimTreeLoopIn.hpp" namespace urde { @@ -12,7 +13,10 @@ CMetaTransMetaAnim::VGetTransitionTree(const std::weak_ptr& a, const std::weak_ptr& b, const CAnimSysContext& animSys) const { - return {}; + std::shared_ptr animNode = + x4_metaAnim->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + return std::make_shared(a, b, animNode, animSys, + CAnimTreeLoopIn::CreatePrimitiveName(a, b, animNode)); } } diff --git a/Runtime/Character/CMetaTransPhaseTrans.cpp b/Runtime/Character/CMetaTransPhaseTrans.cpp index 969c64bec..a76402541 100644 --- a/Runtime/Character/CMetaTransPhaseTrans.cpp +++ b/Runtime/Character/CMetaTransPhaseTrans.cpp @@ -1,16 +1,18 @@ #include "CMetaTransPhaseTrans.hpp" #include "CAnimTreeNode.hpp" +#include "CTimeScaleFunctions.hpp" +#include "CAnimTreeTransition.hpp" +#include "CAnimTreeTimeScale.hpp" namespace urde { CMetaTransPhaseTrans::CMetaTransPhaseTrans(CInputStream& in) { - x4_ = in.readFloatBig(); - x8_ = in.readUint32Big(); + x4_transDur = CCharAnimTime(in); xc_ = in.readBool(); - xd_ = in.readBool(); - x10_ = in.readUint32Big(); + xd_runA = in.readBool(); + x10_flags = in.readUint32Big(); } std::shared_ptr @@ -18,7 +20,23 @@ CMetaTransPhaseTrans::VGetTransitionTree(const std::weak_ptr& a, const std::weak_ptr& b, const CAnimSysContext& animSys) const { - return {}; + std::shared_ptr nA = a.lock(); + CAnimTreeEffectiveContribution cA = nA->GetContributionOfHighestInfluence(); + std::shared_ptr nB = b.lock(); + CAnimTreeEffectiveContribution cB = nB->GetContributionOfHighestInfluence(); + float y2A = cA.GetSteadyStateAnimInfo().GetDuration() / cB.GetSteadyStateAnimInfo().GetDuration(); + float y1B = cB.GetSteadyStateAnimInfo().GetDuration() / cA.GetSteadyStateAnimInfo().GetDuration(); + + nB->VSetPhase(zeus::clamp(0.f, 1.f - cA.GetTimeRemaining() / cA.GetSteadyStateAnimInfo().GetDuration(), 1.f)); + auto tsA = std::make_shared(a, + std::make_unique(CCharAnimTime{}, 1.f, x4_transDur, y2A), + x4_transDur, CAnimTreeTimeScale::CreatePrimitiveName(a, 1.f, x4_transDur, y2A)); + auto tsB = std::make_shared(b, + std::make_unique(CCharAnimTime{}, y1B, x4_transDur, 1.f), + x4_transDur, CAnimTreeTimeScale::CreatePrimitiveName(b, y1B, x4_transDur, 1.f)); + + return std::make_shared(xc_, tsA, tsB, x4_transDur, xd_runA, x10_flags, + CAnimTreeTransition::CreatePrimitiveName(tsA, tsB, x4_transDur.GetSeconds())); } } diff --git a/Runtime/Character/CMetaTransPhaseTrans.hpp b/Runtime/Character/CMetaTransPhaseTrans.hpp index d8759755b..9fd079d0c 100644 --- a/Runtime/Character/CMetaTransPhaseTrans.hpp +++ b/Runtime/Character/CMetaTransPhaseTrans.hpp @@ -3,17 +3,17 @@ #include "IMetaTrans.hpp" #include "IOStreams.hpp" +#include "CCharAnimTime.hpp" namespace urde { class CMetaTransPhaseTrans : public IMetaTrans { - float x4_; - u32 x8_; + CCharAnimTime x4_transDur; bool xc_; - bool xd_; - u32 x10_; + bool xd_runA; + u32 x10_flags; public: CMetaTransPhaseTrans(CInputStream& in); EMetaTransType GetType() const {return EMetaTransType::PhaseTrans;} diff --git a/Runtime/Character/CSequenceHelper.cpp b/Runtime/Character/CSequenceHelper.cpp index ea3530f9c..477c1701f 100644 --- a/Runtime/Character/CSequenceHelper.cpp +++ b/Runtime/Character/CSequenceHelper.cpp @@ -5,6 +5,7 @@ #include "CParticlePOINode.hpp" #include "CSoundPOINode.hpp" #include "IMetaAnim.hpp" +#include "CTreeUtils.hpp" namespace urde { @@ -22,7 +23,7 @@ CSequenceFundamentals::CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo, CSequenceHelper::CSequenceHelper(const std::shared_ptr& a, const std::shared_ptr& b, const CAnimSysContext& animCtx) -: x0_transDB(animCtx.x0_transDB) +: x0_animCtx(animCtx) { x10_treeNodes.reserve(2); x10_treeNodes.push_back(a); @@ -31,7 +32,7 @@ CSequenceHelper::CSequenceHelper(const std::shared_ptr& a, CSequenceHelper::CSequenceHelper(const std::vector>& nodes, const CAnimSysContext& animCtx) -: x0_transDB(animCtx.x0_transDB) +: x0_animCtx(animCtx) { x10_treeNodes.reserve(nodes.size()); for (const std::shared_ptr& meta : nodes) @@ -40,7 +41,81 @@ CSequenceHelper::CSequenceHelper(const std::vector>& CSequenceFundamentals CSequenceHelper::ComputeSequenceFundamentals() { - return {}; + CCharAnimTime duration; + zeus::CVector3f offset; + std::vector boolNodes; + std::vector int32Nodes; + std::vector particleNodes; + std::vector soundNodes; + if (x10_treeNodes.size() > 0) + { + std::shared_ptr node = CAnimTreeNode::Cast(x10_treeNodes[0]->Clone()); + for (int i=0 ; iGetBoolPOIList(CCharAnimTime::Infinity(), boolNodeArr, 64, 0, 0); + boolNodes.reserve(boolNodes.size() + numBools); + for (int j=0 ; jGetInt32POIList(CCharAnimTime::Infinity(), int32NodeArr, 64, 0, 0); + int32Nodes.reserve(int32Nodes.size() + numInt32s); + for (int j=0 ; jGetParticlePOIList(CCharAnimTime::Infinity(), particleNodeArr, 64, 0, 0); + particleNodes.reserve(particleNodes.size() + numParticles); + for (int j=0 ; jGetSoundPOIList(CCharAnimTime::Infinity(), soundNodeArr, 64, 0, 0); + soundNodes.reserve(soundNodes.size() + numSounds); + for (int j=0 ; jVGetTimeRemaining(); + + CCharAnimTime remTime = node->VGetTimeRemaining(); + while (!remTime.EqualsZero() && !remTime.EpsilonZero()) + { + SAdvancementResults res = node->VAdvanceView(remTime); + auto simp = node->Simplified(); + if (simp) + node = CAnimTreeNode::Cast(std::move(*simp)); + CCharAnimTime prevRemTime = remTime; + remTime = res.x0_remTime; + /* This was originally accumulating uninitialized register values (stack variable misuse?) */ + offset += res.x8_deltas.x0_posDelta; + } + + if (i < x10_treeNodes.size()-1) + { + node = CTreeUtils::GetTransitionTree(node, + CAnimTreeNode::Cast(x10_treeNodes[i+1]->Clone()), x0_animCtx); + } + } + } + + return {{false, duration, offset}, boolNodes, int32Nodes, particleNodes, soundNodes}; } } diff --git a/Runtime/Character/CSequenceHelper.hpp b/Runtime/Character/CSequenceHelper.hpp index 1c00e5484..e5ab86f18 100644 --- a/Runtime/Character/CSequenceHelper.hpp +++ b/Runtime/Character/CSequenceHelper.hpp @@ -6,10 +6,10 @@ #include "CInt32POINode.hpp" #include "CParticlePOINode.hpp" #include "CSoundPOINode.hpp" +#include "CAnimSysContext.hpp" namespace urde { -struct CAnimSysContext; class IMetaAnim; class CTransitionDatabaseGame; @@ -21,9 +21,6 @@ class CSequenceFundamentals std::vector x38_particleNodes; std::vector x48_soundNodes; public: - /* HACK: Remove this default constructor */ - CSequenceFundamentals() = default; - CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo, const std::vector& boolNodes, const std::vector& int32Nodes, @@ -39,12 +36,10 @@ public: class CSequenceHelper { - TLockedToken x0_transDB; + CAnimSysContext x0_animCtx; std::vector> x10_treeNodes; std::vector x20_; public: - /* HACK: Remove this default constructor */ - CSequenceHelper() = default; CSequenceHelper(const std::shared_ptr& a, const std::shared_ptr& b, const CAnimSysContext& animCtx); diff --git a/Runtime/Character/CTimeScaleFunctions.cpp b/Runtime/Character/CTimeScaleFunctions.cpp index 7520f64d5..5ba36519b 100644 --- a/Runtime/Character/CTimeScaleFunctions.cpp +++ b/Runtime/Character/CTimeScaleFunctions.cpp @@ -1,80 +1,107 @@ #include "CTimeScaleFunctions.hpp" -#include "CCharAnimTime.hpp" +#include "zeus/Math.hpp" namespace urde { -std::shared_ptr IVaryingAnimationTimeScale::Clone() const +std::unique_ptr IVaryingAnimationTimeScale::Clone() const { return VClone(); } -float CConstantAnimationTimeScale::VTimeScaleIntegral(const float& a, const float& b) const { return (b - a) * x4_; } -float CConstantAnimationTimeScale::VFindUpperLimit(const float& a, const float& b) const { return (b / x4_) + a; } - -std::shared_ptr CConstantAnimationTimeScale::VClone() const +float CConstantAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const { - CConstantAnimationTimeScale* ret = new CConstantAnimationTimeScale(x4_); - return std::shared_ptr(ret); + return (upperLimit - lowerLimit) * x4_scale; } -std::shared_ptr CConstantAnimationTimeScale::VGetFunctionMirrored(const float&) const +float CConstantAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const +{ + return (root / x4_scale) + lowerLimit; +} + +std::unique_ptr CConstantAnimationTimeScale::VClone() const +{ + return std::make_unique(x4_scale); +} + +std::unique_ptr CConstantAnimationTimeScale::VGetFunctionMirrored(float) const { return Clone(); } -float CLinearAnimationTimeScale::VTimeScaleIntegral(const float&, const float&) const + +CLinearAnimationTimeScale::CLinearAnimationTimeScale(const CCharAnimTime& t1, float y1, + const CCharAnimTime& t2, float y2) { - return 0.f; + float y2my1 = y2 - y1; + float t2mt1 = (t2 - t1).GetSeconds(); + x4_desc.x4_slope = y2my1 / t2mt1; + x4_desc.x8_yIntercept = y1 - y2my1 / t2mt1 * t1.GetSeconds(); + x4_desc.xc_t1 = t1.GetSeconds(); + x4_desc.x10_t2 = t2.GetSeconds(); +} + +std::unique_ptr +CLinearAnimationTimeScale::CFunctionDescription::FunctionMirroredAround(float value) const +{ + float slope = -x4_slope; + float t1 = 2.f * value - x10_t2; + float t2 = 2.f * value - xc_t1; + float newYInt = x8_yIntercept - x4_slope * 2.f * value; + float y1 = slope * t1 + newYInt; + float y2 = slope * t2 + newYInt; + return std::make_unique(t1, y1, t2, y2); +} + +float CLinearAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const +{ + if (lowerLimit <= upperLimit) + return TimeScaleIntegralWithSortedLimits(x4_desc, lowerLimit, upperLimit); + else + return -TimeScaleIntegralWithSortedLimits(x4_desc, upperLimit, lowerLimit); } float CLinearAnimationTimeScale::TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, - const float&, const float&) + float lowerLimit, float upperLimit) { - return 0.f; + float lowerEval = desc.x4_slope * lowerLimit + desc.x8_yIntercept; + float upperEval = desc.x4_slope * upperLimit + desc.x8_yIntercept; + return (upperLimit - lowerLimit) * 0.5f * (lowerEval + upperEval); } -float CLinearAnimationTimeScale::VFindUpperLimit(const float&, const float&) const +float CLinearAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const { - return 0.f; + return FindUpperLimitFromRoot(x4_desc, lowerLimit, root); } float CLinearAnimationTimeScale::FindUpperLimitFromRoot(const CFunctionDescription& desc, - const float&, const float&) + float lowerLimit, float root) { - return 0.f; + float M = 0.5f * desc.x4_slope; + float upperLimit = lowerLimit; + float m = 2.f * M; + float lowerIntegration = M * lowerLimit * lowerLimit + desc.x8_yIntercept * lowerLimit; + for (int i=0 ; i<16 ; ++i) + { + float factor = (M * upperLimit * upperLimit + desc.x8_yIntercept * upperLimit - lowerIntegration - root) / + (m * upperLimit + desc.x8_yIntercept); + upperLimit -= factor; + if (zeus::close_enough(factor, 0.f)) + return upperLimit; + } + return -1.f; } -std::shared_ptr CLinearAnimationTimeScale::VClone() const +std::unique_ptr CLinearAnimationTimeScale::VClone() const { - CCharAnimTime timeA(x10_); - CCharAnimTime timeB(xc_); - - CLinearAnimationTimeScale* ret = new CLinearAnimationTimeScale(); - float f30 = x4_ * xc_ + x8_; - ret->x4_ = (x4_ * x10_ + x8_ - f30) / timeB.GetSeconds(); - ret->x8_ = -((x4_ * x10_ + x8_ - f30) / (timeA - timeB).GetSeconds() * timeB.GetSeconds() - f30); - ret->xc_ = timeB.GetSeconds(); - ret->x10_ = timeA.GetSeconds(); - - return std::shared_ptr(ret); + float y1 = x4_desc.x4_slope * x4_desc.xc_t1 + x4_desc.x8_yIntercept; + float y2 = x4_desc.x4_slope * x4_desc.x10_t2 + x4_desc.x8_yIntercept; + return std::make_unique(x4_desc.xc_t1, y1, x4_desc.x10_t2, y2); } -std::shared_ptr -CLinearAnimationTimeScale::VGetFunctionMirrored(const float& parm) const +std::unique_ptr +CLinearAnimationTimeScale::VGetFunctionMirrored(float value) const { - float f27 = -(x4_ * parm * 2.f - x8_); - float f31 = -x4_ * parm * 2.f - x10_ + f27; - CCharAnimTime timeA(2.f * parm - xc_); - CCharAnimTime timeB(2.f * parm - x10_); - - CLinearAnimationTimeScale* ret = new CLinearAnimationTimeScale(); - ret->x4_ = (-x4_ * 2.f * parm - xc_ + f27 - f31) / (timeA - timeB).GetSeconds(); - ret->x8_ = -(((-x4_ * 2.f * parm - xc_ + f27 - f31) / - (timeA - timeB).GetSeconds()) * timeB.GetSeconds() - f31); - ret->xc_ = timeB.GetSeconds(); - ret->x10_ = timeA.GetSeconds(); - - return std::shared_ptr(ret); + return x4_desc.FunctionMirroredAround(value); } } diff --git a/Runtime/Character/CTimeScaleFunctions.hpp b/Runtime/Character/CTimeScaleFunctions.hpp index c1e5dba0e..f6865f2bf 100644 --- a/Runtime/Character/CTimeScaleFunctions.hpp +++ b/Runtime/Character/CTimeScaleFunctions.hpp @@ -2,6 +2,7 @@ #define __URDE_CTIMESCALEFUNCTIONS_HPP__ #include "RetroTypes.hpp" +#include "CCharAnimTime.hpp" namespace urde { @@ -17,45 +18,50 @@ class IVaryingAnimationTimeScale public: virtual ~IVaryingAnimationTimeScale() = default; virtual EVaryingAnimationTimeScaleType GetType() const=0; - virtual float VTimeScaleIntegral(const float&, const float&) const=0; - virtual float VFindUpperLimit(const float&, const float&) const=0; - virtual std::shared_ptr VClone() const=0; - virtual std::shared_ptr VGetFunctionMirrored(const float&) const=0; - std::shared_ptr Clone() const; + virtual float VTimeScaleIntegral(float lowerLimit, float upperLimit) const=0; + virtual float VFindUpperLimit(float lowerLimit, float root) const=0; + virtual std::unique_ptr VClone() const=0; + virtual std::unique_ptr VGetFunctionMirrored(float value) const=0; + std::unique_ptr Clone() const; }; class CConstantAnimationTimeScale : public IVaryingAnimationTimeScale { private: - float x4_; + float x4_scale; public: - CConstantAnimationTimeScale(float f) : x4_(f) {} + CConstantAnimationTimeScale(float scale) : x4_scale(scale) {} EVaryingAnimationTimeScaleType GetType() const { return EVaryingAnimationTimeScaleType::Constant; } - float VTimeScaleIntegral(const float &, const float &) const; - float VFindUpperLimit(const float &, const float &) const; - std::shared_ptr VClone() const; - std::shared_ptr VGetFunctionMirrored(const float &) const; + float VTimeScaleIntegral(float lowerLimit, float upperLimit) const; + float VFindUpperLimit(float lowerLimit, float root) const; + std::unique_ptr VClone() const; + std::unique_ptr VGetFunctionMirrored(float value) const; }; class CLinearAnimationTimeScale : public IVaryingAnimationTimeScale { - float x4_; - float x8_; - float xc_; - float x10_; -public: struct CFunctionDescription { - }; + float x4_slope; + float x8_yIntercept; + float xc_t1; + float x10_t2; + std::unique_ptr FunctionMirroredAround(float value) const; + } x4_desc; + static float FindUpperLimitFromRoot(const CFunctionDescription& desc, + float lowerLimit, float root); + static float TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, + float lowerLimit, float upperLimit); +public: + CLinearAnimationTimeScale(const CCharAnimTime& t1, float y1, + const CCharAnimTime& t2, float y2); EVaryingAnimationTimeScaleType GetType() const {return EVaryingAnimationTimeScaleType::Linear;} - float VTimeScaleIntegral(const float&, const float&) const; - float TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, const float&, const float&); - float VFindUpperLimit(const float&, const float&) const; - float FindUpperLimitFromRoot(const CFunctionDescription& desc, const float&, const float&); - std::shared_ptr VClone() const; - std::shared_ptr VGetFunctionMirrored(const float&) const; + float VTimeScaleIntegral(float lowerLimit, float upperLimit) const; + float VFindUpperLimit(float lowerLimit, float root) const; + std::unique_ptr VClone() const; + std::unique_ptr VGetFunctionMirrored(float value) const; }; } diff --git a/Runtime/Character/CTreeUtils.cpp b/Runtime/Character/CTreeUtils.cpp index 510c26c18..d7fb062c2 100644 --- a/Runtime/Character/CTreeUtils.cpp +++ b/Runtime/Character/CTreeUtils.cpp @@ -7,12 +7,12 @@ namespace urde { -std::shared_ptr CTreeUtils::GetTransitionTree(const std::shared_ptr& a, - const std::shared_ptr& b, +std::shared_ptr CTreeUtils::GetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, const CAnimSysContext& animCtx) { - CAnimTreeEffectiveContribution contribA = a->GetContributionOfHighestInfluence(); - CAnimTreeEffectiveContribution contribB = b->GetContributionOfHighestInfluence(); + CAnimTreeEffectiveContribution contribA = a.lock()->GetContributionOfHighestInfluence(); + CAnimTreeEffectiveContribution contribB = b.lock()->GetContributionOfHighestInfluence(); return animCtx.x0_transDB->GetMetaTrans(contribA.GetAnimDatabaseIndex(), contribB.GetAnimDatabaseIndex())->GetTransitionTree(a, b, animCtx); } diff --git a/Runtime/Character/CTreeUtils.hpp b/Runtime/Character/CTreeUtils.hpp index 5375b8f8a..d4d35222e 100644 --- a/Runtime/Character/CTreeUtils.hpp +++ b/Runtime/Character/CTreeUtils.hpp @@ -11,8 +11,8 @@ struct CAnimSysContext; class CTreeUtils { public: - static std::shared_ptr GetTransitionTree(const std::shared_ptr& a, - const std::shared_ptr& b, + static std::shared_ptr GetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, const CAnimSysContext& animCtx); }; diff --git a/Runtime/Character/IAnimReader.cpp b/Runtime/Character/IAnimReader.cpp index 710f11088..ff124af0b 100644 --- a/Runtime/Character/IAnimReader.cpp +++ b/Runtime/Character/IAnimReader.cpp @@ -15,6 +15,15 @@ SAdvancementDeltas::Interpolate(const SAdvancementDeltas& a, const SAdvancementD }; } +SAdvancementDeltas +SAdvancementDeltas::Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w) +{ + return { + b.x0_posDelta * w - a.x0_posDelta * (1.f - w), + zeus::CQuaternion::slerpShort(a.xc_rotDelta, b.xc_rotDelta, w) + }; +} + SAdvancementResults IAnimReader::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const { diff --git a/Runtime/Character/IAnimReader.hpp b/Runtime/Character/IAnimReader.hpp index 195116d77..19059af37 100644 --- a/Runtime/Character/IAnimReader.hpp +++ b/Runtime/Character/IAnimReader.hpp @@ -26,6 +26,7 @@ struct SAdvancementDeltas static SAdvancementDeltas Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float oldWeight, float newWeight); + static SAdvancementDeltas Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w); }; struct SAdvancementResults @@ -41,8 +42,6 @@ class CSteadyStateAnimInfo bool x14_looping = false; public: - /* HACK: Remove this default constructor */ - CSteadyStateAnimInfo() = default; CSteadyStateAnimInfo(bool looping, const CCharAnimTime& duration, const zeus::CVector3f& offset) : x0_duration(duration), x8_offset(offset), x14_looping(looping) {} diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index a4ea21c45..191964863 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -1344,7 +1344,8 @@ void CElementGen::RenderParticles() zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); systemViewPointMatrix.origin.zeroOut(); zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; - systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemViewPointMatrix) * x178_localScaleTransform; + systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * + systemViewPointMatrix) * x178_localScaleTransform; CGraphics::SetModelMatrix(systemViewPointMatrix); CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); @@ -1388,7 +1389,8 @@ void CElementGen::RenderParticles() const CParticle& particle = x30_particles[i]; sortItems.emplace_back(i); CParticleListItem& sortItem = sortItems.back(); - sortItem.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + sortItem.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * + x80_timeDeltaScale + particle.x10_prevPos); } std::sort(sortItems.begin(), sortItems.end(), @@ -1445,7 +1447,8 @@ void CElementGen::RenderParticles() if (desc->x44_28_x30_28_SORT) viewPoint = sortItems[i].x4_viewPoint; else - viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * + x80_timeDeltaScale + particle.x10_prevPos); if (!constUVs) { @@ -1577,7 +1580,7 @@ void CElementGen::RenderParticles() float size = 0.5f * particle.x2c_lineLengthOrSize; if (0.f == particle.x30_lineWidthOrRota) { - for (int i=0 ; i= 0.00001f; + bool partialCharge = chargeState == EChargeState::Normal ? false : !zeus::close_enough(chargeFactor1, 1.f); CWeapon::EProjectileAttrib attribs = CWeapon::EProjectileAttrib::ArmCannon; if (partialCharge) attribs |= CWeapon::EProjectileAttrib::PartialCharge; diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index b5ca550e7..5e995f594 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -415,17 +415,18 @@ void CPlayerGun::StopChargeSound(CStateManager& mgr) } } -void CPlayerGun::ResetCharge(CStateManager& mgr, bool b1) +void CPlayerGun::ResetCharge(CStateManager& mgr, bool resetBeam) { if (x32c_chargePhase != EChargePhase::NotCharging) StopChargeSound(mgr); if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10) { - bool r30 = !(mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed && !b1); - if (x832_27_chargeAnimStarted || r30) + bool doResetBeam = mgr.GetPlayer().GetMorphballTransitionState() == + CPlayer::EPlayerMorphBallState::Morphed || resetBeam; + if (x832_27_chargeAnimStarted || doResetBeam) PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); - if (r30) + if (doResetBeam) x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); if ((x2f8_stateFlags & 0x2) != 0x2 || x330_chargeState != EChargeState::Normal) { @@ -2559,7 +2560,7 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co } oldViewMtx = CGraphics::g_ViewMatrix; - CGraphics::SetModelMatrix(offsetWorldXf.inverse() * oldViewMtx); + CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); CGraphics::SetModelMatrix(zeus::CTransform::Identity()); x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf); if (x832_26_comboFiring && x77c_comboXferGen) diff --git a/Runtime/Weapon/CPlayerGun.hpp b/Runtime/Weapon/CPlayerGun.hpp index 846cc6d08..10a158bd0 100644 --- a/Runtime/Weapon/CPlayerGun.hpp +++ b/Runtime/Weapon/CPlayerGun.hpp @@ -393,7 +393,7 @@ public: void SetAssistAimTransform(const zeus::CTransform& xf) { x478_assistAimXf = xf; } CGrappleArm& GetGrappleArm() { return *x740_grappleArm; } void DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr); - void ResetCharge(CStateManager& mgr, bool b1); + void ResetCharge(CStateManager& mgr, bool resetBeam); void HandleBeamChange(const CFinalInput& input, CStateManager& mgr); void HandlePhazonBeamChange(CStateManager& mgr); void HandleWeaponChange(const CFinalInput& input, CStateManager& mgr); diff --git a/Runtime/Weapon/CPowerBeam.cpp b/Runtime/Weapon/CPowerBeam.cpp index 4185ec688..902a96e67 100644 --- a/Runtime/Weapon/CPowerBeam.cpp +++ b/Runtime/Weapon/CPowerBeam.cpp @@ -94,6 +94,8 @@ void CPowerBeam::EnableSecondaryFx(ESecondaryFxType type) switch (type) { case ESecondaryFxType::None: + case ESecondaryFxType::ToCombo: + case ESecondaryFxType::CancelCharge: if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) x238_power2ndGen->SetParticleEmission(false); x1cc_enabledSecondaryEffect = ESecondaryFxType::None;