CAnimSourceReader imps

This commit is contained in:
Jack Andersen 2016-04-15 17:24:25 -10:00
parent 3bab36faba
commit e51a657ec1
25 changed files with 462 additions and 88 deletions

View File

@ -1,6 +1,8 @@
#include "ProjectResourceFactoryBase.hpp"
#include "Runtime/IObj.hpp"
#define DUMP_CACHE_FILL 1
namespace urde
{
static logvisor::Module Log("urde::ProjectResourceFactoryBase");
@ -93,6 +95,15 @@ static void WriteTag(athena::io::YAMLDocWriter& cacheWriter,
cacheWriter.leaveSubVector();
}
#if DUMP_CACHE_FILL
static void DumpCacheAdd(const SObjectTag& pathTag, const hecl::ProjectPath& path)
{
fprintf(stderr, "%s %08X %s\n",
pathTag.type.toString().c_str(), uint32_t(pathTag.id),
path.getRelativePathUTF8().c_str());
}
#endif
void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::ProjectPath& dir,
athena::io::YAMLDocWriter& cacheWriter,
athena::io::YAMLDocWriter& nameWriter,
@ -127,10 +138,8 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
m_tagToPath[pathTag] = path;
WriteTag(cacheWriter, pathTag, path);
#if 1
fprintf(stderr, "%s %08X %s\n",
pathTag.type.toString().c_str(), uint32_t(pathTag.id),
path.getRelativePathUTF8().c_str());
#if DUMP_CACHE_FILL
DumpCacheAdd(pathTag, path);
#endif
/* Special multi-resource intermediates */
@ -150,11 +159,11 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
hecl::SystemStringView sysStr(arm);
hecl::ProjectPath subPath = path.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true).ensureAuxInfo(_S("CINF"));
SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender);
if (pathTag)
{
m_tagToPath[pathTag] = path;
WriteTag(cacheWriter, pathTag, path);
}
m_tagToPath[pathTag] = subPath;
WriteTag(cacheWriter, pathTag, subPath);
#if DUMP_CACHE_FILL
DumpCacheAdd(pathTag, subPath);
#endif
}
for (const std::string& sub : subtypeNames)
@ -162,11 +171,11 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
hecl::SystemStringView sysStr(sub);
hecl::ProjectPath subPath = path.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true).ensureAuxInfo(_S("CSKR"));
SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender);
if (pathTag)
{
m_tagToPath[pathTag] = path;
WriteTag(cacheWriter, pathTag, path);
}
m_tagToPath[pathTag] = subPath;
WriteTag(cacheWriter, pathTag, subPath);
#if DUMP_CACHE_FILL
DumpCacheAdd(pathTag, subPath);
#endif
}
for (const std::string& act : actionNames)
@ -174,11 +183,11 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
hecl::SystemStringView sysStr(act);
hecl::ProjectPath subPath = path.getWithExtension((_S('.') + sysStr.sys_str()).c_str(), true).ensureAuxInfo(_S("ANIM"));
SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender);
if (pathTag)
{
m_tagToPath[pathTag] = path;
WriteTag(cacheWriter, pathTag, path);
}
m_tagToPath[pathTag] = subPath;
WriteTag(cacheWriter, pathTag, subPath);
#if DUMP_CACHE_FILL
DumpCacheAdd(pathTag, subPath);
#endif
}
}
}

View File

@ -49,6 +49,13 @@ void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj)
SObjectTag ProjectResourceFactoryMP1::TagFromPath(const hecl::ProjectPath& path, hecl::BlenderToken& btok) const
{
if (!path.getAuxInfo().compare(_S("CINF")))
return SObjectTag(SBIG('CINF'), path.hash().val32());
else if (!path.getAuxInfo().compare(_S("CSKR")))
return SObjectTag(SBIG('CSKR'), path.hash().val32());
else if (!path.getAuxInfo().compare(_S("ANIM")))
return SObjectTag(SBIG('ANIM'), path.hash().val32());
if (hecl::IsPathBlend(path))
{
hecl::BlenderConnection& conn = btok.getBlenderConnection();

View File

@ -0,0 +1,33 @@
#include "CAdditiveAnimPlayback.hpp"
#include "CSegStatementSet.hpp"
namespace urde
{
CAdditiveAnimPlayback::CAdditiveAnimPlayback(const std::weak_ptr<CAnimTreeNode>& anim, float weight, bool a,
const CAdditiveAnimationInfo& info, bool b)
: x0_info(info), x8_anim(anim), xc_weight(weight), x14_a(a)
{
if (!a && b)
x20_ = true;
}
void CAdditiveAnimPlayback::AddToSegStatementSet(const CSegIdList& list,
const CCharLayoutInfo&,
CSegStatementSet&) const
{
}
void CAdditiveAnimPlayback::Update(float dt)
{
}
void CAdditiveAnimPlayback::FadeOut()
{
}
void CAdditiveAnimPlayback::SetWeight(float w)
{
}
}

View File

@ -0,0 +1,60 @@
#ifndef __URDE_CADDITIVEANIMPLAYBACK_HPP__
#define __URDE_CADDITIVEANIMPLAYBACK_HPP__
#include "RetroTypes.hpp"
namespace urde
{
class CAnimTreeNode;
class CAdditiveAnimationInfo;
class CSegIdList;
class CCharLayoutInfo;
class CSegStatementSet;
class CAdditiveAnimationInfo
{
float x0_a = 0.f;
float x4_b = 0.f;
public:
void read(CInputStream& in)
{
x0_a = in.readFloatBig();
x4_b = in.readFloatBig();
}
CAdditiveAnimationInfo() = default;
CAdditiveAnimationInfo(CInputStream& in) {read(in);}
};
class CAdditiveAnimPlayback
{
public:
enum class EAdditivePlaybackState
{
Zero,
One,
Two,
Three,
Four
};
private:
CAdditiveAnimationInfo x0_info;
std::weak_ptr<CAnimTreeNode> x8_anim;
float xc_weight;
float x10_ = 0.f;
bool x14_a;
float x18_ = 0.f;
EAdditivePlaybackState x1c_ = EAdditivePlaybackState::One;
bool x20_ = false;
public:
CAdditiveAnimPlayback(const std::weak_ptr<CAnimTreeNode>& anim, float weight, bool a,
const CAdditiveAnimationInfo& info, bool b);
void AddToSegStatementSet(const CSegIdList& list, const CCharLayoutInfo&, CSegStatementSet&) const;
void Update(float dt);
void FadeOut();
void SetWeight(float w);
};
}
#endif // __URDE_CADDITIVEANIMPLAYBACK_HPP__

View File

@ -5,6 +5,7 @@
#include "CCharacterFactory.hpp"
#include "CAnimationManager.hpp"
#include "CTransitionManager.hpp"
#include "CAdditiveAnimPlayback.hpp"
#include "IAnimReader.hpp"
namespace urde
@ -46,8 +47,9 @@ CAnimData::CAnimData(ResId id,
xe4_iceModelData = *iceModel;
}
ResId CAnimData::GetEventResourceIdForAnimResourceId(ResId) const
ResId CAnimData::GetEventResourceIdForAnimResourceId(ResId id) const
{
return x0_charFactory->GetEventResourceIdForAnimResourceId(id);
}
void CAnimData::AddAdditiveSegData(const CSegIdList& list, CSegStatementSet& stSet)

View File

@ -36,6 +36,7 @@ class CSkinRules;
class CAnimTreeNode;
class CSegIdList;
class CSegStatementSet;
class CAdditiveAnimPlayback;
struct SAdvancementDeltas;
class CAnimData
@ -96,7 +97,7 @@ class CAnimData
u32 x1038_ = 0;
u32 x103c_ = 0;
u32 x1040_ = 0;
u32 x1044_ = 0;
rstl::reserved_vector<std::pair<u32, CAdditiveAnimPlayback>, 8> x1044_additiveAnims;
public:
CAnimData(ResId,

View File

@ -0,0 +1,19 @@
#ifndef __URDE_CANIMPERSEGMENTDATA_HPP__
#define __URDE_CANIMPERSEGMENTDATA_HPP__
#include "zeus/CQuaternion.hpp"
#include "zeus/CVector3f.hpp"
namespace urde
{
struct CAnimPerSegmentData
{
zeus::CQuaternion x0_rotation;
zeus::CVector3f x10_offset;
bool x1c_hasOffset = false;
};
}
#endif // __URDE_CANIMPERSEGMENTDATA_HPP__

View File

@ -1,6 +1,8 @@
#include "CAnimSource.hpp"
#include "CAnimPOIData.hpp"
#include "CSegId.hpp"
#include "CSegIdList.hpp"
#include "CSegStatementSet.hpp"
namespace urde
{
@ -148,7 +150,37 @@ void CAnimSource::GetSegStatementSet(const CSegIdList& list,
if (std::fabs(remTime) < 0.00001f)
remTime = 0.f;
float t = ClampZeroToOne(remTime / x8_interval);
/* TODO: Finish */
const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4;
const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4;
for (const CSegId& id : list.GetList())
{
u8 rotIdx = x20_rotationChannels[id];
if (rotIdx != 0xff)
{
const float* frameDataA =
&x40_data.x0_storage[frameIdx*floatsPerFrame+rotIdx*4];
const float* frameDataB =
&x40_data.x0_storage[(frameIdx+1)*floatsPerFrame+rotIdx*4];
zeus::CQuaternion quatA(frameDataA[0], frameDataA[1], frameDataA[2], frameDataA[3]);
zeus::CQuaternion quatB(frameDataB[0], frameDataB[1], frameDataB[2], frameDataB[3]);
set.x4_segData[id].x0_rotation = zeus::CQuaternion::slerp(quatA, quatB, t);
u8 transIdx = x30_translationChannels[rotIdx];
if (transIdx != 0xff)
{
const float* frameDataA =
&x40_data.x0_storage[frameIdx*floatsPerFrame+rotFloatsPerFrame+transIdx*3];
const float* frameDataB =
&x40_data.x0_storage[(frameIdx-1)*floatsPerFrame+rotFloatsPerFrame+transIdx*3];
zeus::CVector3f vecA(frameDataA[0], frameDataA[1], frameDataA[2]);
zeus::CVector3f vecB(frameDataB[0], frameDataB[1], frameDataB[2]);
set.x4_segData[id].x10_offset = zeus::CVector3f::lerp(vecA, vecB, t);
set.x4_segData[id].x1c_hasOffset = true;
}
}
}
}
const std::vector<CSoundPOINode>& CAnimSource::GetSoundPOIStream() const

View File

@ -74,6 +74,7 @@ public:
const std::vector<CParticlePOINode>& GetParticlePOIStream() const;
const std::vector<CInt32POINode>& GetInt32POIStream() const;
const std::vector<CBoolPOINode>& GetBoolPOIStream() const;
const TCachedToken<CAnimPOIData>& GetPOIData() const {return x58_evntData;}
zeus::CQuaternion GetRotation(const CSegId& seg, const CCharAnimTime& time) const;
zeus::CVector3f GetOffset(const CSegId& seg, const CCharAnimTime& time) const;
bool HasOffset(const CSegId& seg) const;

View File

@ -241,61 +241,210 @@ CAnimSourceReaderBase::CAnimSourceReaderBase(std::unique_ptr<IAnimSourceInfo>&&
const CCharAnimTime& time)
: x4_sourceInfo(std::move(sourceInfo)), xc_curTime(time) {}
SAdvancementResults CAnimSourceReader::VGetAdvancementResults(const CCharAnimTime& a,
const CCharAnimTime& b) const
CAnimSourceReaderBase::CAnimSourceReaderBase(std::unique_ptr<IAnimSourceInfo>&& sourceInfo,
const CAnimSourceReaderBase& other)
: x4_sourceInfo(std::move(sourceInfo)),
xc_curTime(other.xc_curTime),
x14_passedBoolCount(other.x14_passedBoolCount),
x18_passedIntCount(other.x18_passedIntCount),
x1c_passedParticleCount(other.x1c_passedParticleCount),
x20_passedSoundCount(other.x20_passedSoundCount),
x24_boolStates(other.x24_boolStates),
x34_int32States(other.x34_int32States),
x44_particleStates(other.x44_particleStates)
{}
SAdvancementResults CAnimSourceReader::VGetAdvancementResults(const CCharAnimTime& dt,
const CCharAnimTime& startOff) const
{
SAdvancementResults ret;
CCharAnimTime accum = xc_curTime + startOff;
if (xc_curTime + startOff >= x54_source->GetDuration())
{
ret.x0_remTime = dt;
return ret;
}
else if (dt.EqualsZero())
{
return ret;
}
else
{
CCharAnimTime prevTime = accum;
accum += dt;
CCharAnimTime remTime;
if (accum > x54_source->GetDuration())
{
remTime = accum - x54_source->GetDuration();
accum = x54_source->GetDuration();
}
zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse();
zeus::CQuaternion rb = x54_source->GetRotation(3, accum);
ret.x0_remTime = remTime;
ret.x8_deltas.xc_rotDelta = rb * ra;
if (x54_source->HasOffset(3))
{
zeus::CVector3f ta = x54_source->GetOffset(3, prevTime);
zeus::CVector3f tb = x54_source->GetOffset(3, accum);
ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta);
}
return ret;
}
}
void CAnimSourceReader::VSetPhase(float)
void CAnimSourceReader::VSetPhase(float phase)
{
xc_curTime = phase * x54_source->GetDuration();
if (x54_source->GetPOIData())
{
UpdatePOIStates();
if (!xc_curTime.GreaterThanZero())
{
x14_passedBoolCount = 0;
x18_passedIntCount = 0;
x1c_passedParticleCount = 0;
x20_passedSoundCount = 0;
}
}
}
SAdvancementResults CAnimSourceReader::VReverseView(const CCharAnimTime& time)
SAdvancementResults CAnimSourceReader::VReverseView(const CCharAnimTime& dt)
{
SAdvancementResults ret;
if (xc_curTime.EqualsZero())
{
ret.x0_remTime = dt;
return ret;
}
else if (dt.EqualsZero())
{
return ret;
}
else
{
CCharAnimTime prevTime = xc_curTime;
xc_curTime -= dt;
CCharAnimTime remTime;
if (xc_curTime < CCharAnimTime())
{
remTime = CCharAnimTime() - xc_curTime;
xc_curTime = CCharAnimTime();
}
if (x54_source->GetPOIData())
UpdatePOIStates();
zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse();
zeus::CQuaternion rb = x54_source->GetRotation(3, xc_curTime);
ret.x0_remTime = remTime;
ret.x8_deltas.xc_rotDelta = rb * ra;
if (x54_source->HasOffset(3))
{
zeus::CVector3f ta = x54_source->GetOffset(3, prevTime);
zeus::CVector3f tb = x54_source->GetOffset(3, xc_curTime);
ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta);
}
return ret;
}
}
std::shared_ptr<IAnimReader> CAnimSourceReader::VClone() const
{
return std::make_shared<CAnimSourceReader>(*this);
}
void CAnimSourceReader::VGetSegStatementSet(const CSegIdList& list,
CSegStatementSet& setOut) const
{
x54_source->GetSegStatementSet(list, setOut, xc_curTime);
}
void CAnimSourceReader::VGetSegStatementSet(const CSegIdList& list,
CSegStatementSet& setOut,
const CCharAnimTime& time) const
{
x54_source->GetSegStatementSet(list, setOut, time);
}
SAdvancementResults CAnimSourceReader::VAdvanceView(const CCharAnimTime& a)
SAdvancementResults CAnimSourceReader::VAdvanceView(const CCharAnimTime& dt)
{
SAdvancementResults ret;
if (xc_curTime >= x54_source->GetDuration())
{
ret.x0_remTime = dt;
return ret;
}
else if (dt.EqualsZero())
{
return ret;
}
else
{
CCharAnimTime prevTime = xc_curTime;
xc_curTime += dt;
CCharAnimTime remTime;
if (xc_curTime > x54_source->GetDuration())
{
remTime = xc_curTime - x54_source->GetDuration();
xc_curTime = x54_source->GetDuration();
}
if (x54_source->GetPOIData())
UpdatePOIStates();
zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse();
zeus::CQuaternion rb = x54_source->GetRotation(3, xc_curTime);
ret.x0_remTime = remTime;
ret.x8_deltas.xc_rotDelta = rb * ra;
if (x54_source->HasOffset(3))
{
zeus::CVector3f ta = x54_source->GetOffset(3, prevTime);
zeus::CVector3f tb = x54_source->GetOffset(3, xc_curTime);
ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta);
}
return ret;
}
}
CCharAnimTime CAnimSourceReader::VGetTimeRemaining() const
{
return x54_source->GetDuration() - xc_curTime;
}
void CAnimSourceReader::VGetSteadyStateAnimInfo() const
CSteadyStateAnimInfo CAnimSourceReader::VGetSteadyStateAnimInfo() const
{
return x64_steadyStateInfo;
}
bool CAnimSourceReader::VHasOffset(const CSegId& seg) const
{
return x54_source->HasOffset(seg);
}
zeus::CVector3f CAnimSourceReader::VGetOffset(const CSegId& seg) const
{
return x54_source->GetOffset(seg, xc_curTime);
}
zeus::CVector3f CAnimSourceReader::VGetOffset(const CSegId& seg,
const CCharAnimTime& time) const
{
return x54_source->GetOffset(seg, time);
}
zeus::CQuaternion CAnimSourceReader::VGetRotation(const CSegId& seg) const
{
return x54_source->GetRotation(seg, xc_curTime);
}
CAnimSourceReader::CAnimSourceReader(const TSubAnimTypeToken<CAnimSource>& source,
@ -304,10 +453,15 @@ CAnimSourceReader::CAnimSourceReader(const TSubAnimTypeToken<CAnimSource>& sourc
x54_source(source)
{
CAnimSource* sourceData = x54_source.GetObj();
x64_duration = sourceData->GetDuration();
x6c_curRootOffset = sourceData->GetOffset(sourceData->GetRootBoneId(), time);
x64_steadyStateInfo.x64_duration = sourceData->GetDuration();
x64_steadyStateInfo.x6c_curRootOffset = sourceData->GetOffset(sourceData->GetRootBoneId(), time);
PostConstruct(time);
}
CAnimSourceReader::CAnimSourceReader(const CAnimSourceReader& other)
: CAnimSourceReaderBase(std::make_unique<CAnimSourceInfo>(other.x54_source), other),
x54_source(other.x54_source), x64_steadyStateInfo(other.x64_steadyStateInfo)
{}
}

View File

@ -39,6 +39,7 @@ public:
class CAnimSourceReaderBase : public IAnimReader
{
protected:
std::unique_ptr<IAnimSourceInfo> x4_sourceInfo;
CCharAnimTime xc_curTime;
u32 x14_passedBoolCount = 0;
@ -56,11 +57,13 @@ class CAnimSourceReaderBase : public IAnimReader
protected:
void PostConstruct(const CCharAnimTime& time);
void UpdatePOIStates();
CAnimSourceReaderBase(std::unique_ptr<IAnimSourceInfo>&& sourceInfo,
const CAnimSourceReaderBase& other);
public:
CAnimSourceReaderBase(std::unique_ptr<IAnimSourceInfo>&& sourceInfo,
const CCharAnimTime& time);
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;
@ -77,11 +80,10 @@ public:
class CAnimSourceReader : public CAnimSourceReaderBase
{
TSubAnimTypeToken<CAnimSource> x54_source;
CCharAnimTime x64_duration;
zeus::CVector3f x6c_curRootOffset;
bool x78_ = false;
CSteadyStateAnimInfo x64_steadyStateInfo;
public:
CAnimSourceReader(const TSubAnimTypeToken<CAnimSource>& source, const CCharAnimTime& time);
CAnimSourceReader(const CAnimSourceReader& other);
SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const;
bool VSupportsReverseView() const {return true;}
@ -92,7 +94,7 @@ public:
void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const;
SAdvancementResults VAdvanceView(const CCharAnimTime& a);
CCharAnimTime VGetTimeRemaining() const;
void VGetSteadyStateAnimInfo() const;
CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const;
bool VHasOffset(const CSegId& seg) const;
zeus::CVector3f VGetOffset(const CSegId& seg) const;
zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& time) const;

View File

@ -5,24 +5,11 @@
#include "CAnimation.hpp"
#include "CTransition.hpp"
#include "CHalfTransition.hpp"
#include "CAdditiveAnimPlayback.hpp"
namespace urde
{
class CAdditiveAnimationInfo
{
float x0_a = 0.f;
float x4_b = 0.f;
public:
void read(CInputStream& in)
{
x0_a = in.readFloatBig();
x4_b = in.readFloatBig();
}
CAdditiveAnimationInfo() = default;
CAdditiveAnimationInfo(CInputStream& in) {read(in);}
};
class CAnimationSet
{
u16 x0_tableCount;

View File

@ -6,13 +6,12 @@ namespace urde
zeus::CVector3f CCharLayoutInfo::GetFromParentUnrotated(const CSegId& id) const
{
const CCharLayoutNode::Bone& bone = x0_node->GetBone(id);
const CSegId& prev = x0_node->GetPrevBone(bone.x0_parentId);
if (prev == 0xff)
const CCharLayoutNode::Bone& bone = x0_node->GetBoneMap()[id];
if (!x0_node->GetBoneMap().HasElement(bone.x0_parentId))
return bone.x4_origin;
else
{
const CCharLayoutNode::Bone& pBone = x0_node->GetBone(bone.x0_parentId);
const CCharLayoutNode::Bone& pBone = x0_node->GetBoneMap()[bone.x0_parentId];
return bone.x4_origin - pBone.x4_origin;
}
}
@ -34,11 +33,8 @@ CCharLayoutNode::CCharLayoutNode(CInputStream& in)
for (u32 i=0 ; i<count ; ++i)
{
u32 thisId = in.readUint32Big();
Bone& bone = x6c_bones[thisId];
Bone& bone = x0_boneMap[thisId];
bone.read(in);
x8_prevBones[thisId] = x1_curPrevBone;
x1_curPrevBone = thisId;
++x0_boneCount;
}
}

View File

@ -5,6 +5,7 @@
#include "IOStreams.hpp"
#include "CSegIdList.hpp"
#include "CSegId.hpp"
#include "TSegIdMap.hpp"
namespace urde
{
@ -20,15 +21,10 @@ public:
void read(CInputStream& in);
};
private:
CSegId x0_boneCount = 0;
CSegId x1_curPrevBone = 0;
CSegId x8_prevBones[100];
Bone x6c_bones[100];
TSegIdMap<Bone> x0_boneMap;
public:
CCharLayoutNode(CInputStream& in);
const Bone& GetBone(const CSegId& id) const {return x6c_bones[id];}
const CSegId& GetPrevBone(const CSegId& id) const {return x8_prevBones[id];}
const TSegIdMap<Bone>& GetBoneMap() const {return x0_boneMap;}
};
class CCharLayoutInfo

View File

@ -8,6 +8,7 @@
#include "CRandom16.hpp"
#include "CPrimitive.hpp"
#include "CAnimData.hpp"
#include "CAdditiveAnimPlayback.hpp"
#include "GameGlobalObjects.hpp"
#include "Graphics/CSkinnedModel.hpp"

View File

@ -8,30 +8,26 @@ namespace urde
void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout,
const CSegId& boneId, const CSegId& nullId)
{
const CSegId& idA = x8_prevBones[boneId];
if (idA == 0xff)
if (!x0_treeMap.HasElement(boneId))
{
const CCharLayoutNode::Bone& bone = layout.GetRootNode()->GetBone(boneId);
const CCharLayoutNode::Bone& bone = layout.GetRootNode()->GetBoneMap()[boneId];
if (bone.x0_parentId == nullId)
{
xcec_rootId = boneId;
xcf0_hasRoot = true;
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
x6c_nodes[boneId] = CTreeNode(origin);
x0_treeMap[boneId] = CTreeNode(origin);
}
else
{
BuildIntoHierarchy(layout, bone.x0_parentId, nullId);
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
CTreeNode& pNode = x6c_nodes[bone.x0_parentId];
CTreeNode& pNode = x0_treeMap[bone.x0_parentId];
CTreeNode node(origin);
node.x1_sibling = pNode.x0_child;
pNode.x0_child = boneId;
x6c_nodes[boneId] = node;
x0_treeMap[boneId] = node;
}
x8_prevBones[boneId] = x1_curPrevBone;
x1_curPrevBone = boneId;
++x0_boneCount;
}
}
@ -47,7 +43,7 @@ void CHierarchyPoseBuilder::RecursivelyBuildNoScale(const CSegId& boneId, const
CSegId curBone = node.x0_child;
while (curBone != 0)
{
const CTreeNode& node = x6c_nodes[curBone];
const CTreeNode& node = x0_treeMap[curBone];
RecursivelyBuild(curBone, node, pose, quat, xf, xfOffset);
curBone = node.x1_sibling;
}
@ -77,7 +73,7 @@ void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNo
CSegId curBone = node.x0_child;
while (curBone != 0)
{
const CTreeNode& node = x6c_nodes[curBone];
const CTreeNode& node = x0_treeMap[curBone];
RecursivelyBuild(curBone, node, pose, quat, quat, xfOffset);
curBone = node.x1_sibling;
}
@ -106,7 +102,7 @@ void CHierarchyPoseBuilder::BuildTransform(const CSegId& boneId, zeus::CTransfor
while (curId != 2)
{
buildIDs[idCount++] = curId;
curId = layoutInfo.GetRootNode()->GetBone(curId).x0_parentId;
curId = layoutInfo.GetRootNode()->GetBoneMap()[curId].x0_parentId;
}
}
@ -116,7 +112,7 @@ void CHierarchyPoseBuilder::BuildTransform(const CSegId& boneId, zeus::CTransfor
for (CSegId* id=&buildIDs[idCount] ; id != buildIDs ; --id)
{
CSegId& thisId = id[-1];
const CTreeNode& node = x6c_nodes[thisId];
const CTreeNode& node = x0_treeMap[thisId];
accumRot *= node.x4_rotation;
accumPos += accumXF * node.x14_offset;
if (scale == 1.f)
@ -132,7 +128,7 @@ void CHierarchyPoseBuilder::BuildTransform(const CSegId& boneId, zeus::CTransfor
void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose)
{
pose.Clear();
const CTreeNode& node = x6c_nodes[xcec_rootId];
const CTreeNode& node = x0_treeMap[xcec_rootId];
zeus::CQuaternion quat;
zeus::CMatrix3f mtx;
zeus::CVector3f vec;

View File

@ -2,6 +2,7 @@
#define __URDE_CHIERARCHYPOSEBUILDER_HPP__
#include "CSegId.hpp"
#include "TSegIdMap.hpp"
#include "zeus/CQuaternion.hpp"
#include "CLayoutDescription.hpp"
@ -13,10 +14,6 @@ class CPoseAsTransforms;
class CHierarchyPoseBuilder
{
CSegId x0_boneCount = 0;
CSegId x1_curPrevBone = 0;
CSegId x8_prevBones[100];
struct CTreeNode
{
CSegId x0_child = 0;
@ -26,7 +23,8 @@ class CHierarchyPoseBuilder
CTreeNode() = default;
CTreeNode(const zeus::CVector3f& offset) : x14_offset(offset) {}
};
CTreeNode x6c_nodes[100];
TSegIdMap<CTreeNode> x0_treeMap;
CSegId xcec_rootId;
bool xcf0_hasRoot = false;
CLayoutDescription xcf4_layoutDesc;

View File

@ -71,6 +71,8 @@ add_library(RuntimeCommonCharacter
CAnimSource.hpp CAnimSource.cpp
CAllFormatsAnimSource.hpp CAllFormatsAnimSource.cpp
CSegStatementSet.hpp CSegStatementSet.cpp
CAnimPerSegmentData.hpp
CAdditiveAnimPlayback.hpp CAdditiveAnimPlayback.cpp
CActorLights.hpp CActorLights.cpp
CAnimSysContext.hpp
CBodyState.hpp)

View File

@ -12,6 +12,7 @@
#include "GameGlobalObjects.hpp"
#include "CAssetFactory.hpp"
#include "CCharacterFactory.hpp"
#include "CAdditiveAnimPlayback.hpp"
namespace urde
{

View File

@ -0,0 +1,23 @@
#include "CSegStatementSet.hpp"
#include "CSegIdList.hpp"
#include "CCharLayoutInfo.hpp"
namespace urde
{
void CSegStatementSet::Add(const CSegIdList& list, const CCharLayoutInfo& layout,
const CSegStatementSet& other, float weight)
{
for (const CSegId& id : list.GetList())
{
x4_segData[id].x0_rotation *= zeus::CQuaternion::slerp(zeus::CQuaternion::skNoRotation,
other.x4_segData[id].x0_rotation, weight);
if (other.x4_segData[id].x1c_hasOffset && x4_segData[id].x1c_hasOffset)
{
zeus::CVector3f off = other.x4_segData[id].x10_offset - layout.GetFromParentUnrotated(id);
x4_segData[id].x10_offset += off * weight;
}
}
}
}

View File

@ -1,11 +1,21 @@
#ifndef __URDE_CSEGSTATEMENTSET_HPP__
#define __URDE_CSEGSTATEMENTSET_HPP__
#include "CAnimPerSegmentData.hpp"
namespace urde
{
class CSegIdList;
class CCharLayoutInfo;
class CSegStatementSet
{
public:
/* Used to be a pointer to arbitrary subclass-provided storage,
* now it's a self-stored array */
CAnimPerSegmentData x4_segData[100];
void Add(const CSegIdList& list, const CCharLayoutInfo& layout,
const CSegStatementSet& other, float weight);
};
}

View File

@ -29,6 +29,13 @@ struct SAdvancementResults
SAdvancementDeltas x8_deltas;
};
struct CSteadyStateAnimInfo
{
CCharAnimTime x64_duration;
zeus::CVector3f x6c_curRootOffset;
bool x78_ = false;
};
class IAnimReader
{
public:
@ -36,7 +43,7 @@ public:
virtual bool IsCAnimTreeNode() const {return false;}
virtual SAdvancementResults VAdvanceView(const CCharAnimTime& a)=0;
virtual CCharAnimTime VGetTimeRemaining() const=0;
virtual void VGetSteadyStateAnimInfo() const=0;
virtual CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const=0;
virtual bool VHasOffset(const CSegId& seg) const=0;
virtual zeus::CVector3f VGetOffset(const CSegId& seg) const=0;
virtual zeus::CQuaternion VGetRotation(const CSegId& seg) const=0;

View File

@ -10,9 +10,46 @@ namespace urde
template <class T>
class TSegIdMap
{
std::map<CSegId, T> x0_map;
CSegId x0_boneCount = 0;
CSegId x1_curPrevBone = 0;
u32 x4_capacity = 100;
CSegId x8_prevBones[100];
T x6c_bones[100];
public:
const T& AccessElement(const CSegId& id) const {return x0_map[id];}
T& operator[](const CSegId& id) {return SetElement(id);}
const T& operator[](const CSegId& id) const {return x6c_bones[id];}
T& SetElement(const CSegId& id, T&& obj)
{
x6c_bones[id] = std::move(obj);
if (x8_prevBones[id] == 0xff)
{
x8_prevBones[id] = x1_curPrevBone;
x1_curPrevBone = id;
++x0_boneCount;
}
return x6c_bones[id];
}
T& SetElement(const CSegId& id)
{
if (x8_prevBones[id] == 0xff)
{
x8_prevBones[id] = x1_curPrevBone;
x1_curPrevBone = id;
++x0_boneCount;
}
return x6c_bones[id];
}
void DelElement(const CSegId& id)
{
if (x8_prevBones[id] != 0xff)
{
if (id == x1_curPrevBone)
x1_curPrevBone = x8_prevBones[id];
x8_prevBones[id] = 0xff;
--x0_boneCount;
}
}
bool HasElement(const CSegId& id) const {return x8_prevBones[id] != 0xff;}
};
}

View File

@ -161,7 +161,7 @@ public:
bool finished = false;
m_inputGenerator.Update(1.0 / 60.0, m_archQueue);
while(m_archQueue)
while (m_archQueue)
{
CArchitectureMessage msg = m_archQueue.Pop();
if (msg.GetTarget() == EArchMsgTarget::ArchitectureSupport)

@ -1 +1 @@
Subproject commit e40a836ea15a2a2c06a2a8c8ba511db23d4395de
Subproject commit 36cd3fbf9dafdd9c83268593dfcd905edea32a9a