All animation nodes implemented

This commit is contained in:
Jack Andersen 2018-01-29 15:04:01 -10:00
parent bb10423267
commit 36f1473f3e
31 changed files with 809 additions and 179 deletions

View File

@ -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 CCharAnimTime CAnimTreeBlend::VGetTimeRemaining() const
{ {
return {}; CCharAnimTime remA = x14_a->VGetTimeRemaining();
CCharAnimTime remB = x18_b->VGetTimeRemaining();
return (remA < remB) ? remB : remA;
} }
CSteadyStateAnimInfo CAnimTreeBlend::VGetSteadyStateAnimInfo() const 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<IAnimReader> CAnimTreeBlend::VClone() const std::unique_ptr<IAnimReader> CAnimTreeBlend::VClone() const
{ {
return {}; return std::make_unique<CAnimTreeBlend>(x20_24_b1,
CAnimTreeNode::Cast(x14_a->Clone()),
CAnimTreeNode::Cast(x18_b->Clone()),
x24_blendWeight, x4_name);
} }
void CAnimTreeBlend::SetBlendingWeight(float w) void CAnimTreeBlend::SetBlendingWeight(float w)
{ {
x24_blendWeight = w;
} }
float CAnimTreeBlend::VGetBlendingWeight() const float CAnimTreeBlend::VGetBlendingWeight() const
{ {
return 0.f; return x24_blendWeight;
} }
} }

View File

@ -19,7 +19,7 @@ public:
const std::shared_ptr<CAnimTreeNode>& b, const std::shared_ptr<CAnimTreeNode>& b,
float blendWeight, std::string_view name); float blendWeight, std::string_view name);
SAdvancementResults VAdvanceView(const CCharAnimTime& a); SAdvancementResults VAdvanceView(const CCharAnimTime& dt);
CCharAnimTime VGetTimeRemaining() const; CCharAnimTime VGetTimeRemaining() const;
CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const;
std::unique_ptr<IAnimReader> VClone() const; std::unique_ptr<IAnimReader> VClone() const;

View File

@ -128,33 +128,55 @@ CParticleData::EParentedMode CAnimTreeDoubleChild::VGetParticlePOIState(const ch
return x18_b->VGetParticlePOIState(name); 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 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 u32 CAnimTreeDoubleChild::Depth() const
{ {
return 0; return std::max(x14_a->Depth(), x18_b->Depth()) + 1;
} }
CAnimTreeEffectiveContribution CAnimTreeDoubleChild::VGetContributionOfHighestInfluence() const 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 u32 CAnimTreeDoubleChild::VGetNumChildren() const
{ {
return 0; return x14_a->VGetNumChildren() + x18_b->VGetNumChildren() + 2;
} }
std::shared_ptr<IAnimReader> CAnimTreeDoubleChild::VGetBestUnblendedChild() const std::shared_ptr<IAnimReader> CAnimTreeDoubleChild::VGetBestUnblendedChild() const
{ {
return {}; std::shared_ptr<CAnimTreeNode> bestChild = (VGetRightChildWeight() > 0.5f) ? x18_b : x14_a;
if (!bestChild)
return {};
return bestChild->GetBestUnblendedChild();
} }
void CAnimTreeDoubleChild::VGetWeightedReaders( void CAnimTreeDoubleChild::VGetWeightedReaders(

View File

@ -0,0 +1,128 @@
#include "CAnimTreeLoopIn.hpp"
#include "CTreeUtils.hpp"
namespace urde
{
std::string CAnimTreeLoopIn::CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& b,
const std::weak_ptr<CAnimTreeNode>& c)
{
return {};
}
CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& b,
const std::weak_ptr<CAnimTreeNode>& 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<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& 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<std::unique_ptr<IAnimReader>> 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<IAnimReader> CAnimTreeLoopIn::VGetBestUnblendedChild() const
{
if (std::shared_ptr<IAnimReader> bestChild = x14_child->GetBestUnblendedChild())
{
return std::make_shared<CAnimTreeLoopIn>(CAnimTreeNode::Cast(bestChild->Clone()),
x18_nextAnim, x1c_didLoopIn, x20_animCtx, x4_name,
x30_fundamentals, x88_curTime);
}
return {};
}
std::unique_ptr<IAnimReader> CAnimTreeLoopIn::VClone() const
{
return std::make_unique<CAnimTreeLoopIn>(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<CBoolPOINode>(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<CInt32POINode>(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<CParticlePOINode>(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<CSoundPOINode>(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<CAnimTreeNode> 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;
}
}

View File

@ -1,11 +1,48 @@
#ifndef __URDE_CANIMTREELOOPIN_HPP__ #ifndef __URDE_CANIMTREELOOPIN_HPP__
#define __URDE_CANIMTREELOOPIN_HPP__ #define __URDE_CANIMTREELOOPIN_HPP__
#include "CAnimTreeSingleChild.hpp"
#include "CAnimSysContext.hpp"
#include "CSequenceHelper.hpp"
namespace urde namespace urde
{ {
class CAnimTreeLoopIn class CAnimTreeLoopIn : public CAnimTreeSingleChild
{ {
std::shared_ptr<CAnimTreeNode> x18_nextAnim;
bool x1c_didLoopIn = false;
CAnimSysContext x20_animCtx;
CSequenceFundamentals x30_fundamentals;
CCharAnimTime x88_curTime;
public:
static std::string CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& b,
const std::weak_ptr<CAnimTreeNode>& c);
CAnimTreeLoopIn(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& b,
const std::weak_ptr<CAnimTreeNode>& c,
const CAnimSysContext& animCtx,
std::string_view name);
CAnimTreeLoopIn(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& 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<std::unique_ptr<IAnimReader>> VSimplified();
std::shared_ptr<IAnimReader> VGetBestUnblendedChild() const;
std::unique_ptr<IAnimReader> 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);
}; };
} }

View File

@ -1,6 +1,7 @@
#include "CAnimTreeSequence.hpp" #include "CAnimTreeSequence.hpp"
#include "IMetaAnim.hpp" #include "IMetaAnim.hpp"
#include "CAnimSysContext.hpp" #include "CAnimSysContext.hpp"
#include "CTreeUtils.hpp"
namespace urde namespace urde
{ {
@ -9,7 +10,8 @@ CAnimTreeSequence::CAnimTreeSequence(const std::vector<std::shared_ptr<IMetaAnim
const CAnimSysContext& animSys, const CAnimSysContext& animSys,
std::string_view name) std::string_view name)
: CAnimTreeSingleChild(seq[0]->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()), name), : CAnimTreeSingleChild(seq[0]->GetAnimationTree(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<CAnimTreeNode>& curNo
std::string_view name, std::string_view name,
const CSequenceFundamentals& fundamentals, const CSequenceFundamentals& fundamentals,
const CCharAnimTime& time) 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<IAnimReader> CAnimTreeSequence::VGetBestUnblendedChild() const
return ch; return ch;
return std::make_shared<CAnimTreeSequence>(std::static_pointer_cast<CAnimTreeNode>( return std::make_shared<CAnimTreeSequence>(std::static_pointer_cast<CAnimTreeNode>(
std::shared_ptr<IAnimReader>(ch->Clone())), std::shared_ptr<IAnimReader>(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<CAnimTreeNode> 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 CCharAnimTime CAnimTreeSequence::VGetTimeRemaining() const
{ {
if (x38_curIdx == x28_.size() - 1) if (x38_curIdx == x28_sequence.size() - 1)
return x14_child->VGetTimeRemaining(); return x14_child->VGetTimeRemaining();
return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime.GetSeconds(); return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime.GetSeconds();
} }
@ -87,7 +135,7 @@ std::unique_ptr<IAnimReader> CAnimTreeSequence::VClone() const
{ {
return std::make_unique<CAnimTreeSequence>(std::static_pointer_cast<CAnimTreeNode>( return std::make_unique<CAnimTreeSequence>(std::static_pointer_cast<CAnimTreeNode>(
std::shared_ptr<IAnimReader>(x14_child->Clone())), std::shared_ptr<IAnimReader>(x14_child->Clone())),
x28_, x18_, x4_name, x3c_fundamentals, x94_curTime); x28_sequence, x18_animCtx, x4_name, x3c_fundamentals, x94_curTime);
} }
} }

View File

@ -12,8 +12,8 @@ class CTransitionDatabaseGame;
class CAnimTreeSequence : public CAnimTreeSingleChild class CAnimTreeSequence : public CAnimTreeSingleChild
{ {
CAnimSysContext x18_; CAnimSysContext x18_animCtx;
std::vector<std::shared_ptr<IMetaAnim>> x28_; std::vector<std::shared_ptr<IMetaAnim>> x28_sequence;
u32 x38_curIdx = 0; u32 x38_curIdx = 0;
CSequenceFundamentals x3c_fundamentals; CSequenceFundamentals x3c_fundamentals;
CCharAnimTime x94_curTime; CCharAnimTime x94_curTime;
@ -30,8 +30,9 @@ public:
CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const;
std::shared_ptr<IAnimReader> VGetBestUnblendedChild() const; std::shared_ptr<IAnimReader> VGetBestUnblendedChild() const;
bool VSupportsReverseView() const { return false; }
SAdvancementResults VAdvanceView(const CCharAnimTime& a); SAdvancementResults VAdvanceView(const CCharAnimTime& dt);
CCharAnimTime VGetTimeRemaining() const; CCharAnimTime VGetTimeRemaining() const;
CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const;
u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const;

View File

@ -7,107 +7,109 @@ CAnimTreeSingleChild::CAnimTreeSingleChild(const std::weak_ptr<CAnimTreeNode>& n
: CAnimTreeNode(name) : CAnimTreeNode(name)
, x14_child(node.lock()) , 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 CCharAnimTime CAnimTreeSingleChild::VGetTimeRemaining() const
{ {
return {}; return x14_child->VGetTimeRemaining();
} }
bool CAnimTreeSingleChild::VHasOffset(const CSegId& seg) const bool CAnimTreeSingleChild::VHasOffset(const CSegId& seg) const
{ {
return false; return x14_child->VHasOffset(seg);
} }
zeus::CVector3f CAnimTreeSingleChild::VGetOffset(const CSegId& seg) const zeus::CVector3f CAnimTreeSingleChild::VGetOffset(const CSegId& seg) const
{ {
return {}; return x14_child->VGetOffset(seg);
} }
zeus::CQuaternion CAnimTreeSingleChild::VGetRotation(const CSegId& seg) const zeus::CQuaternion CAnimTreeSingleChild::VGetRotation(const CSegId& seg) const
{ {
return {}; return x14_child->VGetRotation(seg);
} }
u32 CAnimTreeSingleChild::VGetBoolPOIList(const CCharAnimTime& time, u32 CAnimTreeSingleChild::VGetBoolPOIList(const CCharAnimTime& time,
CBoolPOINode* listOut, 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, u32 CAnimTreeSingleChild::VGetInt32POIList(const CCharAnimTime& time,
CInt32POINode* listOut, 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, u32 CAnimTreeSingleChild::VGetParticlePOIList(const CCharAnimTime& time,
CParticlePOINode* listOut, 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, u32 CAnimTreeSingleChild::VGetSoundPOIList(const CCharAnimTime& time,
CSoundPOINode* listOut, 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 bool CAnimTreeSingleChild::VGetBoolPOIState(const char* name) const
{ {
return false; return x14_child->VGetBoolPOIState(name);
} }
s32 CAnimTreeSingleChild::VGetInt32POIState(const char* name) const s32 CAnimTreeSingleChild::VGetInt32POIState(const char* name) const
{ {
return -1; return x14_child->VGetInt32POIState(name);
} }
CParticleData::EParentedMode CAnimTreeSingleChild::VGetParticlePOIState(const char* name) const CParticleData::EParentedMode CAnimTreeSingleChild::VGetParticlePOIState(const char* name) const
{ {
return CParticleData::EParentedMode::Initial; return x14_child->VGetParticlePOIState(name);
} }
void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list,
CSegStatementSet& setOut) const CSegStatementSet& setOut) const
{ {
x14_child->VGetSegStatementSet(list, setOut);
} }
void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list,
CSegStatementSet& setOut, CSegStatementSet& setOut,
const CCharAnimTime& time) const const CCharAnimTime& time) const
{ {
x14_child->VGetSegStatementSet(list, setOut, time);
} }
void CAnimTreeSingleChild::VSetPhase(float) void CAnimTreeSingleChild::VSetPhase(float phase)
{ {
x14_child->VSetPhase(phase);
} }
SAdvancementResults SAdvancementResults
CAnimTreeSingleChild::VGetAdvancementResults(const CCharAnimTime& a, CAnimTreeSingleChild::VGetAdvancementResults(const CCharAnimTime& a,
const CCharAnimTime& b) const const CCharAnimTime& b) const
{ {
return {}; return x14_child->VGetAdvancementResults(a, b);
} }
u32 CAnimTreeSingleChild::Depth() const u32 CAnimTreeSingleChild::Depth() const
{ {
return 1; return x14_child->Depth() + 1;
} }
u32 CAnimTreeSingleChild::VGetNumChildren() const u32 CAnimTreeSingleChild::VGetNumChildren() const
{ {
return 0; return x14_child->VGetNumChildren() + 1;
} }
} }

View File

@ -13,7 +13,7 @@ protected:
public: public:
CAnimTreeSingleChild(const std::weak_ptr<CAnimTreeNode>& node, std::string_view name); CAnimTreeSingleChild(const std::weak_ptr<CAnimTreeNode>& node, std::string_view name);
SAdvancementResults VAdvanceView(const CCharAnimTime& a); SAdvancementResults VAdvanceView(const CCharAnimTime& dt);
CCharAnimTime VGetTimeRemaining() const; CCharAnimTime VGetTimeRemaining() const;
bool VHasOffset(const CSegId& seg) const; bool VHasOffset(const CSegId& seg) const;
zeus::CVector3f VGetOffset(const CSegId& seg) const; zeus::CVector3f VGetOffset(const CSegId& seg) const;

View File

@ -5,11 +5,22 @@ namespace urde
CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node, float scale, CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node, float scale,
std::string_view name) std::string_view name)
: CAnimTreeSingleChild(node, name) : CAnimTreeSingleChild(node, name)
, x18_timeScale(new CConstantAnimationTimeScale(scale)) , x18_timeScale(new CConstantAnimationTimeScale(scale))
, x28_targetAccelTime(CCharAnimTime::Infinity())
{ {
} }
CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node,
std::unique_ptr<IVaryingAnimationTimeScale>&& 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<CAnimTreeNode>&, float, std::string CAnimTreeTimeScale::CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&, float,
const CCharAnimTime&, float) const CCharAnimTime&, float)
{ {
@ -20,26 +31,26 @@ CCharAnimTime CAnimTreeTimeScale::GetRealLifeTime(const CCharAnimTime& time) con
{ {
CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); CCharAnimTime timeRem = x14_child->VGetTimeRemaining();
CCharAnimTime tmp = std::min(timeRem, time); CCharAnimTime ret = std::min(timeRem, time);
if (x28_ > CCharAnimTime()) if (x28_targetAccelTime > CCharAnimTime())
{ {
if (tmp < CCharAnimTime(x28_ * x20_)) if (ret < CCharAnimTime(x28_targetAccelTime - x20_curAccelTime))
return x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(), return x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(),
(x20_ + tmp).GetSeconds()); (x20_curAccelTime + ret).GetSeconds());
else else
{ {
CCharAnimTime integral = CCharAnimTime integral =
x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(), x28_.GetSeconds()); x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), x28_targetAccelTime.GetSeconds());
if (integral > tmp) if (integral > ret)
return x18_timeScale->VFindUpperLimit(x20_.GetSeconds(), tmp.GetSeconds()) * return x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), ret.GetSeconds()) -
x20_.GetSeconds(); x20_curAccelTime.GetSeconds();
else else
return integral + (integral * tmp); return integral + (ret - integral);
} }
} }
return tmp; return ret;
} }
void CAnimTreeTimeScale::VSetPhase(float phase) void CAnimTreeTimeScale::VSetPhase(float phase)
@ -49,7 +60,175 @@ void CAnimTreeTimeScale::VSetPhase(float phase)
std::experimental::optional<std::unique_ptr<IAnimReader>> CAnimTreeTimeScale::VSimplified() std::experimental::optional<std::unique_ptr<IAnimReader>> 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<IAnimReader>(newNode)};
}
else if (x20_curAccelTime == x28_targetAccelTime)
{
return {x14_child->Clone()};
}
return {}; 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 ; i<ret ; ++i)
listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime()));
return ret;
}
u32 CAnimTreeTimeScale::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut,
u32 capacity, u32 iterator, u32 unk) const
{
CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ?
x14_child->VGetTimeRemaining() : GetRealLifeTime(time);
u32 ret = x14_child->GetInt32POIList(useTime, listOut, capacity, iterator, unk);
if (x28_targetAccelTime > CCharAnimTime())
for (int i=0 ; i<ret ; ++i)
listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime()));
return ret;
}
u32 CAnimTreeTimeScale::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut,
u32 capacity, u32 iterator, u32 unk) const
{
CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ?
x14_child->VGetTimeRemaining() : GetRealLifeTime(time);
u32 ret = x14_child->GetParticlePOIList(useTime, listOut, capacity, iterator, unk);
if (x28_targetAccelTime > CCharAnimTime())
for (int i=0 ; i<ret ; ++i)
listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime()));
return ret;
}
u32 CAnimTreeTimeScale::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut,
u32 capacity, u32 iterator, u32 unk) const
{
CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ?
x14_child->VGetTimeRemaining() : GetRealLifeTime(time);
u32 ret = x14_child->GetSoundPOIList(useTime, listOut, capacity, iterator, unk);
if (x28_targetAccelTime > CCharAnimTime())
for (int i=0 ; i<ret ; ++i)
listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime()));
return ret;
}
bool CAnimTreeTimeScale::VGetBoolPOIState(const char* name) const
{
return x14_child->VGetBoolPOIState(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<IAnimReader> CAnimTreeTimeScale::VGetBestUnblendedChild() const
{
if (std::shared_ptr<IAnimReader> 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<IAnimReader>(newNode)};
}
return {};
}
std::unique_ptr<IAnimReader> 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<IAnimReader>(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;
}
}
} }

View File

@ -9,17 +9,36 @@ namespace urde
class CAnimTreeTimeScale : public CAnimTreeSingleChild class CAnimTreeTimeScale : public CAnimTreeSingleChild
{ {
std::shared_ptr<CConstantAnimationTimeScale> x18_timeScale; std::unique_ptr<IVaryingAnimationTimeScale> x18_timeScale;
CCharAnimTime x20_; CCharAnimTime x20_curAccelTime;
CCharAnimTime x28_; CCharAnimTime x28_targetAccelTime;
CCharAnimTime x30_initialTime;
public: public:
CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>&, float, std::string_view); CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node, float timeScale, std::string_view name);
CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node,
std::unique_ptr<IVaryingAnimationTimeScale>&& timeScale,
const CCharAnimTime& time, std::string_view name);
static std::string CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&, float, const CCharAnimTime&, float); static std::string CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&, float, const CCharAnimTime&, float);
CCharAnimTime GetRealLifeTime(const CCharAnimTime&) const; CCharAnimTime GetRealLifeTime(const CCharAnimTime&) const;
void VSetPhase(float); void VSetPhase(float);
std::experimental::optional<std::unique_ptr<IAnimReader>> VSimplified(); std::experimental::optional<std::unique_ptr<IAnimReader>> 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<IAnimReader> VGetBestUnblendedChild() const;
std::unique_ptr<IAnimReader> VClone() const;
CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const;
CCharAnimTime VGetTimeRemaining() const;
SAdvancementResults VAdvanceView(const CCharAnimTime& dt);
}; };
} }

View File

@ -17,7 +17,8 @@ protected:
bool x36_initialized = false; bool x36_initialized = false;
SAdvancementResults AdvanceViewForTransitionalPeriod(const CCharAnimTime& time); SAdvancementResults AdvanceViewForTransitionalPeriod(const CCharAnimTime& time);
public: public:
static std::string CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&, const std::weak_ptr<CAnimTreeNode>&, static std::string CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&,
const std::weak_ptr<CAnimTreeNode>&,
float); float);
CAnimTreeTransition(bool b1, const std::weak_ptr<CAnimTreeNode>& a, CAnimTreeTransition(bool b1, const std::weak_ptr<CAnimTreeNode>& a,

View File

@ -40,6 +40,8 @@ void CAnimationDatabaseGame::GetAllUniquePrimitives(std::vector<CPrimitive>& pri
void CAnimationDatabaseGame::GetUniquePrimitivesFromMetaAnim(std::set<CPrimitive>& primsOut, void CAnimationDatabaseGame::GetUniquePrimitivesFromMetaAnim(std::set<CPrimitive>& primsOut,
std::string_view name) const std::string_view name) const
{} {
// Empty
}
} }

View File

@ -16,7 +16,7 @@ CCharAnimTime CCharAnimTime::Infinity()
bool CCharAnimTime::EqualsZero() const bool CCharAnimTime::EqualsZero() const
{ {
if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing) if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing)
return false; return true;
return (x0_time == 0.f); return (x0_time == 0.f);
} }

View File

@ -37,10 +37,15 @@ CMetaAnimSequence::VGetAnimationTree(const CAnimSysContext& animSys,
return GetAnimationTree(animSys, modOrders); return GetAnimationTree(animSys, modOrders);
} }
#if 0
std::vector<std::string> anims;
anims.reserve(anims.size());
for (const std::shared_ptr<IMetaAnim>& anim : x4_sequence) for (const std::shared_ptr<IMetaAnim>& anim : x4_sequence)
{ {
std::shared_ptr<CAnimTreeNode> chNode = anim->GetAnimationTree(animSys, orders);
anims.emplace_back(chNode->GetName());
} }
#endif
std::shared_ptr<CAnimTreeNode> ret = std::shared_ptr<CAnimTreeNode> ret =
std::make_shared<CAnimTreeSequence>(x4_sequence, animSys, ""); std::make_shared<CAnimTreeSequence>(x4_sequence, animSys, "");

View File

@ -1,5 +1,6 @@
#include "CMetaTransMetaAnim.hpp" #include "CMetaTransMetaAnim.hpp"
#include "CMetaAnimFactory.hpp" #include "CMetaAnimFactory.hpp"
#include "CAnimTreeLoopIn.hpp"
namespace urde namespace urde
{ {
@ -12,7 +13,10 @@ CMetaTransMetaAnim::VGetTransitionTree(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& b, const std::weak_ptr<CAnimTreeNode>& b,
const CAnimSysContext& animSys) const const CAnimSysContext& animSys) const
{ {
return {}; std::shared_ptr<CAnimTreeNode> animNode =
x4_metaAnim->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders());
return std::make_shared<CAnimTreeLoopIn>(a, b, animNode, animSys,
CAnimTreeLoopIn::CreatePrimitiveName(a, b, animNode));
} }
} }

View File

@ -1,16 +1,18 @@
#include "CMetaTransPhaseTrans.hpp" #include "CMetaTransPhaseTrans.hpp"
#include "CAnimTreeNode.hpp" #include "CAnimTreeNode.hpp"
#include "CTimeScaleFunctions.hpp"
#include "CAnimTreeTransition.hpp"
#include "CAnimTreeTimeScale.hpp"
namespace urde namespace urde
{ {
CMetaTransPhaseTrans::CMetaTransPhaseTrans(CInputStream& in) CMetaTransPhaseTrans::CMetaTransPhaseTrans(CInputStream& in)
{ {
x4_ = in.readFloatBig(); x4_transDur = CCharAnimTime(in);
x8_ = in.readUint32Big();
xc_ = in.readBool(); xc_ = in.readBool();
xd_ = in.readBool(); xd_runA = in.readBool();
x10_ = in.readUint32Big(); x10_flags = in.readUint32Big();
} }
std::shared_ptr<CAnimTreeNode> std::shared_ptr<CAnimTreeNode>
@ -18,7 +20,23 @@ CMetaTransPhaseTrans::VGetTransitionTree(const std::weak_ptr<CAnimTreeNode>& a,
const std::weak_ptr<CAnimTreeNode>& b, const std::weak_ptr<CAnimTreeNode>& b,
const CAnimSysContext& animSys) const const CAnimSysContext& animSys) const
{ {
return {}; std::shared_ptr<CAnimTreeNode> nA = a.lock();
CAnimTreeEffectiveContribution cA = nA->GetContributionOfHighestInfluence();
std::shared_ptr<CAnimTreeNode> 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<CAnimTreeTimeScale>(a,
std::make_unique<CLinearAnimationTimeScale>(CCharAnimTime{}, 1.f, x4_transDur, y2A),
x4_transDur, CAnimTreeTimeScale::CreatePrimitiveName(a, 1.f, x4_transDur, y2A));
auto tsB = std::make_shared<CAnimTreeTimeScale>(b,
std::make_unique<CLinearAnimationTimeScale>(CCharAnimTime{}, y1B, x4_transDur, 1.f),
x4_transDur, CAnimTreeTimeScale::CreatePrimitiveName(b, y1B, x4_transDur, 1.f));
return std::make_shared<CAnimTreeTransition>(xc_, tsA, tsB, x4_transDur, xd_runA, x10_flags,
CAnimTreeTransition::CreatePrimitiveName(tsA, tsB, x4_transDur.GetSeconds()));
} }
} }

View File

@ -3,17 +3,17 @@
#include "IMetaTrans.hpp" #include "IMetaTrans.hpp"
#include "IOStreams.hpp" #include "IOStreams.hpp"
#include "CCharAnimTime.hpp"
namespace urde namespace urde
{ {
class CMetaTransPhaseTrans : public IMetaTrans class CMetaTransPhaseTrans : public IMetaTrans
{ {
float x4_; CCharAnimTime x4_transDur;
u32 x8_;
bool xc_; bool xc_;
bool xd_; bool xd_runA;
u32 x10_; u32 x10_flags;
public: public:
CMetaTransPhaseTrans(CInputStream& in); CMetaTransPhaseTrans(CInputStream& in);
EMetaTransType GetType() const {return EMetaTransType::PhaseTrans;} EMetaTransType GetType() const {return EMetaTransType::PhaseTrans;}

View File

@ -5,6 +5,7 @@
#include "CParticlePOINode.hpp" #include "CParticlePOINode.hpp"
#include "CSoundPOINode.hpp" #include "CSoundPOINode.hpp"
#include "IMetaAnim.hpp" #include "IMetaAnim.hpp"
#include "CTreeUtils.hpp"
namespace urde namespace urde
{ {
@ -22,7 +23,7 @@ CSequenceFundamentals::CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo,
CSequenceHelper::CSequenceHelper(const std::shared_ptr<CAnimTreeNode>& a, CSequenceHelper::CSequenceHelper(const std::shared_ptr<CAnimTreeNode>& a,
const std::shared_ptr<CAnimTreeNode>& b, const std::shared_ptr<CAnimTreeNode>& b,
const CAnimSysContext& animCtx) const CAnimSysContext& animCtx)
: x0_transDB(animCtx.x0_transDB) : x0_animCtx(animCtx)
{ {
x10_treeNodes.reserve(2); x10_treeNodes.reserve(2);
x10_treeNodes.push_back(a); x10_treeNodes.push_back(a);
@ -31,7 +32,7 @@ CSequenceHelper::CSequenceHelper(const std::shared_ptr<CAnimTreeNode>& a,
CSequenceHelper::CSequenceHelper(const std::vector<std::shared_ptr<IMetaAnim>>& nodes, CSequenceHelper::CSequenceHelper(const std::vector<std::shared_ptr<IMetaAnim>>& nodes,
const CAnimSysContext& animCtx) const CAnimSysContext& animCtx)
: x0_transDB(animCtx.x0_transDB) : x0_animCtx(animCtx)
{ {
x10_treeNodes.reserve(nodes.size()); x10_treeNodes.reserve(nodes.size());
for (const std::shared_ptr<IMetaAnim>& meta : nodes) for (const std::shared_ptr<IMetaAnim>& meta : nodes)
@ -40,7 +41,81 @@ CSequenceHelper::CSequenceHelper(const std::vector<std::shared_ptr<IMetaAnim>>&
CSequenceFundamentals CSequenceHelper::ComputeSequenceFundamentals() CSequenceFundamentals CSequenceHelper::ComputeSequenceFundamentals()
{ {
return {}; CCharAnimTime duration;
zeus::CVector3f offset;
std::vector<CBoolPOINode> boolNodes;
std::vector<CInt32POINode> int32Nodes;
std::vector<CParticlePOINode> particleNodes;
std::vector<CSoundPOINode> soundNodes;
if (x10_treeNodes.size() > 0)
{
std::shared_ptr<CAnimTreeNode> node = CAnimTreeNode::Cast(x10_treeNodes[0]->Clone());
for (int i=0 ; i<x10_treeNodes.size() ; ++i)
{
CBoolPOINode boolNodeArr[64];
u32 numBools = node->GetBoolPOIList(CCharAnimTime::Infinity(), boolNodeArr, 64, 0, 0);
boolNodes.reserve(boolNodes.size() + numBools);
for (int j=0 ; j<numBools ; ++j)
{
CBoolPOINode& n = boolNodeArr[j];
n.SetTime(n.GetTime() + duration);
boolNodes.push_back(n);
}
CInt32POINode int32NodeArr[64];
u32 numInt32s = node->GetInt32POIList(CCharAnimTime::Infinity(), int32NodeArr, 64, 0, 0);
int32Nodes.reserve(int32Nodes.size() + numInt32s);
for (int j=0 ; j<numInt32s ; ++j)
{
CInt32POINode& n = int32NodeArr[j];
n.SetTime(n.GetTime() + duration);
int32Nodes.push_back(n);
}
CParticlePOINode particleNodeArr[64];
u32 numParticles = node->GetParticlePOIList(CCharAnimTime::Infinity(), particleNodeArr, 64, 0, 0);
particleNodes.reserve(particleNodes.size() + numParticles);
for (int j=0 ; j<numParticles ; ++j)
{
CParticlePOINode& n = particleNodeArr[j];
n.SetTime(n.GetTime() + duration);
particleNodes.push_back(n);
}
CSoundPOINode soundNodeArr[64];
u32 numSounds = node->GetSoundPOIList(CCharAnimTime::Infinity(), soundNodeArr, 64, 0, 0);
soundNodes.reserve(soundNodes.size() + numSounds);
for (int j=0 ; j<numSounds ; ++j)
{
CSoundPOINode& n = soundNodeArr[j];
n.SetTime(n.GetTime() + duration);
soundNodes.push_back(n);
}
duration += node->VGetTimeRemaining();
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};
} }
} }

View File

@ -6,10 +6,10 @@
#include "CInt32POINode.hpp" #include "CInt32POINode.hpp"
#include "CParticlePOINode.hpp" #include "CParticlePOINode.hpp"
#include "CSoundPOINode.hpp" #include "CSoundPOINode.hpp"
#include "CAnimSysContext.hpp"
namespace urde namespace urde
{ {
struct CAnimSysContext;
class IMetaAnim; class IMetaAnim;
class CTransitionDatabaseGame; class CTransitionDatabaseGame;
@ -21,9 +21,6 @@ class CSequenceFundamentals
std::vector<CParticlePOINode> x38_particleNodes; std::vector<CParticlePOINode> x38_particleNodes;
std::vector<CSoundPOINode> x48_soundNodes; std::vector<CSoundPOINode> x48_soundNodes;
public: public:
/* HACK: Remove this default constructor */
CSequenceFundamentals() = default;
CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo, CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo,
const std::vector<CBoolPOINode>& boolNodes, const std::vector<CBoolPOINode>& boolNodes,
const std::vector<CInt32POINode>& int32Nodes, const std::vector<CInt32POINode>& int32Nodes,
@ -39,12 +36,10 @@ public:
class CSequenceHelper class CSequenceHelper
{ {
TLockedToken<CTransitionDatabaseGame> x0_transDB; CAnimSysContext x0_animCtx;
std::vector<std::shared_ptr<CAnimTreeNode>> x10_treeNodes; std::vector<std::shared_ptr<CAnimTreeNode>> x10_treeNodes;
std::vector<bool> x20_; std::vector<bool> x20_;
public: public:
/* HACK: Remove this default constructor */
CSequenceHelper() = default;
CSequenceHelper(const std::shared_ptr<CAnimTreeNode>& a, CSequenceHelper(const std::shared_ptr<CAnimTreeNode>& a,
const std::shared_ptr<CAnimTreeNode>& b, const std::shared_ptr<CAnimTreeNode>& b,
const CAnimSysContext& animCtx); const CAnimSysContext& animCtx);

View File

@ -1,80 +1,107 @@
#include "CTimeScaleFunctions.hpp" #include "CTimeScaleFunctions.hpp"
#include "CCharAnimTime.hpp" #include "zeus/Math.hpp"
namespace urde namespace urde
{ {
std::shared_ptr<IVaryingAnimationTimeScale> IVaryingAnimationTimeScale::Clone() const std::unique_ptr<IVaryingAnimationTimeScale> IVaryingAnimationTimeScale::Clone() const
{ {
return VClone(); return VClone();
} }
float CConstantAnimationTimeScale::VTimeScaleIntegral(const float& a, const float& b) const { return (b - a) * x4_; } float CConstantAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const
float CConstantAnimationTimeScale::VFindUpperLimit(const float& a, const float& b) const { return (b / x4_) + a; }
std::shared_ptr<IVaryingAnimationTimeScale> CConstantAnimationTimeScale::VClone() const
{ {
CConstantAnimationTimeScale* ret = new CConstantAnimationTimeScale(x4_); return (upperLimit - lowerLimit) * x4_scale;
return std::shared_ptr<IVaryingAnimationTimeScale>(ret);
} }
std::shared_ptr<IVaryingAnimationTimeScale> CConstantAnimationTimeScale::VGetFunctionMirrored(const float&) const float CConstantAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const
{
return (root / x4_scale) + lowerLimit;
}
std::unique_ptr<IVaryingAnimationTimeScale> CConstantAnimationTimeScale::VClone() const
{
return std::make_unique<CConstantAnimationTimeScale>(x4_scale);
}
std::unique_ptr<IVaryingAnimationTimeScale> CConstantAnimationTimeScale::VGetFunctionMirrored(float) const
{ {
return Clone(); 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<IVaryingAnimationTimeScale>
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<CLinearAnimationTimeScale>(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, 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, 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<IVaryingAnimationTimeScale> CLinearAnimationTimeScale::VClone() const std::unique_ptr<IVaryingAnimationTimeScale> CLinearAnimationTimeScale::VClone() const
{ {
CCharAnimTime timeA(x10_); float y1 = x4_desc.x4_slope * x4_desc.xc_t1 + x4_desc.x8_yIntercept;
CCharAnimTime timeB(xc_); float y2 = x4_desc.x4_slope * x4_desc.x10_t2 + x4_desc.x8_yIntercept;
return std::make_unique<CLinearAnimationTimeScale>(x4_desc.xc_t1, y1, x4_desc.x10_t2, y2);
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<IVaryingAnimationTimeScale>(ret);
} }
std::shared_ptr<IVaryingAnimationTimeScale> std::unique_ptr<IVaryingAnimationTimeScale>
CLinearAnimationTimeScale::VGetFunctionMirrored(const float& parm) const CLinearAnimationTimeScale::VGetFunctionMirrored(float value) const
{ {
float f27 = -(x4_ * parm * 2.f - x8_); return x4_desc.FunctionMirroredAround(value);
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<IVaryingAnimationTimeScale>(ret);
} }
} }

View File

@ -2,6 +2,7 @@
#define __URDE_CTIMESCALEFUNCTIONS_HPP__ #define __URDE_CTIMESCALEFUNCTIONS_HPP__
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "CCharAnimTime.hpp"
namespace urde namespace urde
{ {
@ -17,45 +18,50 @@ class IVaryingAnimationTimeScale
public: public:
virtual ~IVaryingAnimationTimeScale() = default; virtual ~IVaryingAnimationTimeScale() = default;
virtual EVaryingAnimationTimeScaleType GetType() const=0; virtual EVaryingAnimationTimeScaleType GetType() const=0;
virtual float VTimeScaleIntegral(const float&, const float&) const=0; virtual float VTimeScaleIntegral(float lowerLimit, float upperLimit) const=0;
virtual float VFindUpperLimit(const float&, const float&) const=0; virtual float VFindUpperLimit(float lowerLimit, float root) const=0;
virtual std::shared_ptr<IVaryingAnimationTimeScale> VClone() const=0; virtual std::unique_ptr<IVaryingAnimationTimeScale> VClone() const=0;
virtual std::shared_ptr<IVaryingAnimationTimeScale> VGetFunctionMirrored(const float&) const=0; virtual std::unique_ptr<IVaryingAnimationTimeScale> VGetFunctionMirrored(float value) const=0;
std::shared_ptr<IVaryingAnimationTimeScale> Clone() const; std::unique_ptr<IVaryingAnimationTimeScale> Clone() const;
}; };
class CConstantAnimationTimeScale : public IVaryingAnimationTimeScale class CConstantAnimationTimeScale : public IVaryingAnimationTimeScale
{ {
private: private:
float x4_; float x4_scale;
public: public:
CConstantAnimationTimeScale(float f) : x4_(f) {} CConstantAnimationTimeScale(float scale) : x4_scale(scale) {}
EVaryingAnimationTimeScaleType GetType() const { return EVaryingAnimationTimeScaleType::Constant; } EVaryingAnimationTimeScaleType GetType() const { return EVaryingAnimationTimeScaleType::Constant; }
float VTimeScaleIntegral(const float &, const float &) const; float VTimeScaleIntegral(float lowerLimit, float upperLimit) const;
float VFindUpperLimit(const float &, const float &) const; float VFindUpperLimit(float lowerLimit, float root) const;
std::shared_ptr<IVaryingAnimationTimeScale> VClone() const; std::unique_ptr<IVaryingAnimationTimeScale> VClone() const;
std::shared_ptr<IVaryingAnimationTimeScale> VGetFunctionMirrored(const float &) const; std::unique_ptr<IVaryingAnimationTimeScale> VGetFunctionMirrored(float value) const;
}; };
class CLinearAnimationTimeScale : public IVaryingAnimationTimeScale class CLinearAnimationTimeScale : public IVaryingAnimationTimeScale
{ {
float x4_;
float x8_;
float xc_;
float x10_;
public:
struct CFunctionDescription struct CFunctionDescription
{ {
}; float x4_slope;
float x8_yIntercept;
float xc_t1;
float x10_t2;
std::unique_ptr<IVaryingAnimationTimeScale> 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;} EVaryingAnimationTimeScaleType GetType() const {return EVaryingAnimationTimeScaleType::Linear;}
float VTimeScaleIntegral(const float&, const float&) const; float VTimeScaleIntegral(float lowerLimit, float upperLimit) const;
float TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, const float&, const float&); float VFindUpperLimit(float lowerLimit, float root) const;
float VFindUpperLimit(const float&, const float&) const; std::unique_ptr<IVaryingAnimationTimeScale> VClone() const;
float FindUpperLimitFromRoot(const CFunctionDescription& desc, const float&, const float&); std::unique_ptr<IVaryingAnimationTimeScale> VGetFunctionMirrored(float value) const;
std::shared_ptr<IVaryingAnimationTimeScale> VClone() const;
std::shared_ptr<IVaryingAnimationTimeScale> VGetFunctionMirrored(const float&) const;
}; };
} }

View File

@ -7,12 +7,12 @@
namespace urde namespace urde
{ {
std::shared_ptr<CAnimTreeNode> CTreeUtils::GetTransitionTree(const std::shared_ptr<CAnimTreeNode>& a, std::shared_ptr<CAnimTreeNode> CTreeUtils::GetTransitionTree(const std::weak_ptr<CAnimTreeNode>& a,
const std::shared_ptr<CAnimTreeNode>& b, const std::weak_ptr<CAnimTreeNode>& b,
const CAnimSysContext& animCtx) const CAnimSysContext& animCtx)
{ {
CAnimTreeEffectiveContribution contribA = a->GetContributionOfHighestInfluence(); CAnimTreeEffectiveContribution contribA = a.lock()->GetContributionOfHighestInfluence();
CAnimTreeEffectiveContribution contribB = b->GetContributionOfHighestInfluence(); CAnimTreeEffectiveContribution contribB = b.lock()->GetContributionOfHighestInfluence();
return animCtx.x0_transDB->GetMetaTrans(contribA.GetAnimDatabaseIndex(), return animCtx.x0_transDB->GetMetaTrans(contribA.GetAnimDatabaseIndex(),
contribB.GetAnimDatabaseIndex())->GetTransitionTree(a, b, animCtx); contribB.GetAnimDatabaseIndex())->GetTransitionTree(a, b, animCtx);
} }

View File

@ -11,8 +11,8 @@ struct CAnimSysContext;
class CTreeUtils class CTreeUtils
{ {
public: public:
static std::shared_ptr<CAnimTreeNode> GetTransitionTree(const std::shared_ptr<CAnimTreeNode>& a, static std::shared_ptr<CAnimTreeNode> GetTransitionTree(const std::weak_ptr<CAnimTreeNode>& a,
const std::shared_ptr<CAnimTreeNode>& b, const std::weak_ptr<CAnimTreeNode>& b,
const CAnimSysContext& animCtx); const CAnimSysContext& animCtx);
}; };

View File

@ -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 SAdvancementResults
IAnimReader::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const IAnimReader::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const
{ {

View File

@ -26,6 +26,7 @@ struct SAdvancementDeltas
static SAdvancementDeltas Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b, static SAdvancementDeltas Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b,
float oldWeight, float newWeight); float oldWeight, float newWeight);
static SAdvancementDeltas Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w);
}; };
struct SAdvancementResults struct SAdvancementResults
@ -41,8 +42,6 @@ class CSteadyStateAnimInfo
bool x14_looping = false; bool x14_looping = false;
public: public:
/* HACK: Remove this default constructor */
CSteadyStateAnimInfo() = default;
CSteadyStateAnimInfo(bool looping, const CCharAnimTime& duration, const zeus::CVector3f& offset) CSteadyStateAnimInfo(bool looping, const CCharAnimTime& duration, const zeus::CVector3f& offset)
: x0_duration(duration), x8_offset(offset), x14_looping(looping) {} : x0_duration(duration), x8_offset(offset), x14_looping(looping) {}

View File

@ -1344,7 +1344,8 @@ void CElementGen::RenderParticles()
zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix);
systemViewPointMatrix.origin.zeroOut(); systemViewPointMatrix.origin.zeroOut();
zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; 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::SetModelMatrix(systemViewPointMatrix);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
@ -1388,7 +1389,8 @@ void CElementGen::RenderParticles()
const CParticle& particle = x30_particles[i]; const CParticle& particle = x30_particles[i];
sortItems.emplace_back(i); sortItems.emplace_back(i);
CParticleListItem& sortItem = sortItems.back(); 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(), std::sort(sortItems.begin(), sortItems.end(),
@ -1445,7 +1447,8 @@ void CElementGen::RenderParticles()
if (desc->x44_28_x30_28_SORT) if (desc->x44_28_x30_28_SORT)
viewPoint = sortItems[i].x4_viewPoint; viewPoint = sortItems[i].x4_viewPoint;
else 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) if (!constUVs)
{ {
@ -1577,7 +1580,7 @@ void CElementGen::RenderParticles()
float size = 0.5f * particle.x2c_lineLengthOrSize; float size = 0.5f * particle.x2c_lineLengthOrSize;
if (0.f == particle.x30_lineWidthOrRota) if (0.f == particle.x30_lineWidthOrRota)
{ {
for (int i=0 ; i<mbspVal ; ++i) for (int j=0 ; j<mbspVal ; ++j)
{ {
vec += mbspVec; vec += mbspVec;
zeus::CVector3f vec2 = systemCameraMatrix * vec; zeus::CVector3f vec2 = systemCameraMatrix * vec;
@ -1620,7 +1623,7 @@ void CElementGen::RenderParticles()
float sinT = std::sin(theta) * size; float sinT = std::sin(theta) * size;
float cosT = std::cos(theta) * size; float cosT = std::cos(theta) * size;
for (int i=0 ; i<mbspVal ; ++i) for (int j=0 ; j<mbspVal ; ++j)
{ {
vec += mbspVec; vec += mbspVec;
zeus::CVector3f vec2 = systemCameraMatrix * vec; zeus::CVector3f vec2 = systemCameraMatrix * vec;
@ -1800,10 +1803,10 @@ void CElementGen::RenderParticlesIndirectTexture()
inst.pos[2] = zeus::CVector4f{viewPoint.x + size, viewPoint.y, viewPoint.z - size, 1.f}; inst.pos[2] = zeus::CVector4f{viewPoint.x + size, viewPoint.y, viewPoint.z - size, 1.f};
inst.pos[3] = zeus::CVector4f{viewPoint.x - size, viewPoint.y, viewPoint.z - size, 1.f}; inst.pos[3] = zeus::CVector4f{viewPoint.x - size, viewPoint.y, viewPoint.z - size, 1.f};
inst.color = particle.x34_color; inst.color = particle.x34_color;
inst.texrTindUVs[0] = zeus::CVector4f{uvs.xMax, uvs.yMax, uvsInd.xMin, uvsInd.yMin}; inst.texrTindUVs[2] = zeus::CVector4f{uvs.xMax, uvs.yMax, uvsInd.xMin, uvsInd.yMin};
inst.texrTindUVs[1] = zeus::CVector4f{uvs.xMin, uvs.yMax, uvsInd.xMin, uvsInd.yMax}; inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMax, uvsInd.xMin, uvsInd.yMax};
inst.texrTindUVs[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin}; inst.texrTindUVs[0] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin};
inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMax, uvsInd.yMax}; inst.texrTindUVs[1] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMax, uvsInd.yMax};
inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, clipRect.x24_uvYMax, clipRect.x1c_uvXMax, clipRect.x20_uvYMin}; inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, clipRect.x24_uvYMax, clipRect.x1c_uvXMax, clipRect.x20_uvYMin};
} }

View File

@ -228,7 +228,7 @@ void CGunWeapon::Fire(bool underwater, float dt, EChargeState chargeState, const
{ {
CDamageInfo dInfo = GetDamageInfo(mgr, chargeState, chargeFactor1); CDamageInfo dInfo = GetDamageInfo(mgr, chargeState, chargeFactor1);
zeus::CVector3f scale(chargeState == EChargeState::Normal ? 1.f : chargeFactor2); zeus::CVector3f scale(chargeState == EChargeState::Normal ? 1.f : chargeFactor2);
bool partialCharge = chargeState == EChargeState::Normal ? false : std::fabs(chargeFactor1 - 1.f) >= 0.00001f; bool partialCharge = chargeState == EChargeState::Normal ? false : !zeus::close_enough(chargeFactor1, 1.f);
CWeapon::EProjectileAttrib attribs = CWeapon::EProjectileAttrib::ArmCannon; CWeapon::EProjectileAttrib attribs = CWeapon::EProjectileAttrib::ArmCannon;
if (partialCharge) if (partialCharge)
attribs |= CWeapon::EProjectileAttrib::PartialCharge; attribs |= CWeapon::EProjectileAttrib::PartialCharge;

View File

@ -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) if (x32c_chargePhase != EChargePhase::NotCharging)
StopChargeSound(mgr); StopChargeSound(mgr);
if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10) if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10)
{ {
bool r30 = !(mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed && !b1); bool doResetBeam = mgr.GetPlayer().GetMorphballTransitionState() ==
if (x832_27_chargeAnimStarted || r30) CPlayer::EPlayerMorphBallState::Morphed || resetBeam;
if (x832_27_chargeAnimStarted || doResetBeam)
PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false);
if (r30) if (doResetBeam)
x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None);
if ((x2f8_stateFlags & 0x2) != 0x2 || x330_chargeState != EChargeState::Normal) 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; oldViewMtx = CGraphics::g_ViewMatrix;
CGraphics::SetModelMatrix(offsetWorldXf.inverse() * oldViewMtx); CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx);
CGraphics::SetModelMatrix(zeus::CTransform::Identity()); CGraphics::SetModelMatrix(zeus::CTransform::Identity());
x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf); x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf);
if (x832_26_comboFiring && x77c_comboXferGen) if (x832_26_comboFiring && x77c_comboXferGen)

View File

@ -393,7 +393,7 @@ public:
void SetAssistAimTransform(const zeus::CTransform& xf) { x478_assistAimXf = xf; } void SetAssistAimTransform(const zeus::CTransform& xf) { x478_assistAimXf = xf; }
CGrappleArm& GetGrappleArm() { return *x740_grappleArm; } CGrappleArm& GetGrappleArm() { return *x740_grappleArm; }
void DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr); 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 HandleBeamChange(const CFinalInput& input, CStateManager& mgr);
void HandlePhazonBeamChange(CStateManager& mgr); void HandlePhazonBeamChange(CStateManager& mgr);
void HandleWeaponChange(const CFinalInput& input, CStateManager& mgr); void HandleWeaponChange(const CFinalInput& input, CStateManager& mgr);

View File

@ -94,6 +94,8 @@ void CPowerBeam::EnableSecondaryFx(ESecondaryFxType type)
switch (type) switch (type)
{ {
case ESecondaryFxType::None: case ESecondaryFxType::None:
case ESecondaryFxType::ToCombo:
case ESecondaryFxType::CancelCharge:
if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen)
x238_power2ndGen->SetParticleEmission(false); x238_power2ndGen->SetParticleEmission(false);
x1cc_enabledSecondaryEffect = ESecondaryFxType::None; x1cc_enabledSecondaryEffect = ESecondaryFxType::None;