mirror of https://github.com/AxioDL/metaforce.git
Tons of animation bug fixes
This commit is contained in:
parent
668c4f7eee
commit
9b436b4b23
|
@ -325,8 +325,8 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
float quantRangeF = float(quantRange);
|
||||
|
||||
/* Pre-pass to calculate translation multiplier */
|
||||
float maxTransDiff = 0.0f;
|
||||
float maxScaleDiff = 0.0f;
|
||||
float maxTransVal = 0.0f;
|
||||
float maxScaleVal = 0.0f;
|
||||
auto kit = chanKeys.begin();
|
||||
for (Channel& chan : channels)
|
||||
{
|
||||
|
@ -334,31 +334,27 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
{
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
const Value* last = &(*kit)[0];
|
||||
for (auto it=kit->begin() + 1;
|
||||
for (auto it=kit->begin();
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
const Value* current = &*it;
|
||||
maxTransDiff = std::max(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]);
|
||||
maxTransDiff = std::max(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]);
|
||||
maxTransDiff = std::max(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]);
|
||||
last = current;
|
||||
const Value* key = &*it;
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(key->v3.vec[0]));
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(key->v3.vec[1]));
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(key->v3.vec[2]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
const Value* last = &(*kit)[0];
|
||||
for (auto it=kit->begin() + 1;
|
||||
for (auto it=kit->begin();
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
const Value* current = &*it;
|
||||
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[0] - last->v3.vec[0]);
|
||||
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[1] - last->v3.vec[1]);
|
||||
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[2] - last->v3.vec[2]);
|
||||
last = current;
|
||||
const Value* key = &*it;
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(key->v3.vec[0]));
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(key->v3.vec[1]));
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(key->v3.vec[2]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -366,8 +362,8 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
|||
}
|
||||
++kit;
|
||||
}
|
||||
transMultOut = maxTransDiff / quantRangeF;
|
||||
scaleMultOut = maxScaleDiff / quantRangeF;
|
||||
transMultOut = maxTransVal / quantRangeF;
|
||||
scaleMultOut = maxScaleVal / quantRangeF;
|
||||
|
||||
/* Output channel inits */
|
||||
std::vector<QuantizedValue> initVals;
|
||||
|
|
|
@ -1148,6 +1148,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
|||
});
|
||||
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
std::experimental::optional<CINF> rigCinf;
|
||||
std::experimental::optional<DNAANIM::RigInverter<CINF>> rigInv;
|
||||
|
||||
/* Write out CINF resources */
|
||||
|
@ -1164,8 +1165,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
|||
|
||||
if (!rigInv)
|
||||
{
|
||||
rigCinf.emplace(cinf);
|
||||
auto matrices = ds.getBoneMatrices(arm.name);
|
||||
rigInv.emplace(cinf, matrices);
|
||||
rigInv.emplace(*rigCinf, matrices);
|
||||
}
|
||||
}
|
||||
ds.close();
|
||||
|
|
|
@ -10,7 +10,9 @@ using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream;
|
|||
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const
|
||||
{
|
||||
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
|
||||
os.format("act.hecl_fps = round(%f)\n"
|
||||
"act.hecl_looping = %s\n",
|
||||
(1.0f / mainInterval), looping ? "True" : "False");
|
||||
|
||||
auto kit = chanKeys.begin();
|
||||
|
||||
|
@ -270,6 +272,7 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
|
|||
head.read(reader);
|
||||
evnt = head.evnt;
|
||||
mainInterval = head.interval;
|
||||
looping = bool(head.looping);
|
||||
|
||||
WordBitmap keyBmp;
|
||||
keyBmp.read(reader, head.keyBitmapBitCount);
|
||||
|
@ -379,7 +382,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
|||
head.unk0 = 1;
|
||||
head.interval = mainInterval;
|
||||
head.rootBoneId = 3;
|
||||
head.looping = 0;
|
||||
head.looping = looping;
|
||||
head.unk3 = 1;
|
||||
|
||||
WordBitmap keyBmp;
|
||||
|
@ -530,6 +533,7 @@ ANIM::ANIM(const BlenderAction& act,
|
|||
{
|
||||
m_anim.reset(new struct ANIM2(pc));
|
||||
IANIM& newAnim = *m_anim;
|
||||
newAnim.looping = act.looping;
|
||||
|
||||
newAnim.bones.reserve(act.channels.size());
|
||||
size_t extChanCount = 0;
|
||||
|
|
|
@ -28,6 +28,7 @@ struct ANIM : BigDNA
|
|||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
UniqueID32 evnt;
|
||||
bool looping = false;
|
||||
|
||||
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const;
|
||||
};
|
||||
|
@ -235,6 +236,13 @@ struct ANIM : BigDNA
|
|||
m_anim->sendANIMToBlender(os, rig);
|
||||
}
|
||||
|
||||
bool isLooping() const
|
||||
{
|
||||
if (!m_anim)
|
||||
return false;
|
||||
return m_anim->looping;
|
||||
}
|
||||
|
||||
using BlenderAction = hecl::BlenderConnection::DataStream::Actor::Action;
|
||||
|
||||
ANIM() = default;
|
||||
|
|
|
@ -135,7 +135,7 @@ CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& i
|
|||
if (bone->children.size())
|
||||
{
|
||||
int curId = 4;
|
||||
RecursiveAddArmatureBone(armature, bone, 3, curId, idMap, nameMap);
|
||||
RecursiveAddArmatureBone(armature, armature.getChild(bone, 0), 3, curId, idMap, nameMap);
|
||||
}
|
||||
|
||||
bones.emplace_back();
|
||||
|
@ -144,6 +144,7 @@ CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& i
|
|||
boneOut.id = 3;
|
||||
boneOut.parentId = 2;
|
||||
boneOut.origin = bone->origin;
|
||||
idMap.emplace(std::make_pair(bone->name, 3));
|
||||
|
||||
if (bone->children.size())
|
||||
{
|
||||
|
|
|
@ -9,7 +9,9 @@ using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream;
|
|||
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const
|
||||
{
|
||||
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
|
||||
os.format("act.hecl_fps = round(%f)\n"
|
||||
"act.hecl_looping = %s\n",
|
||||
(1.0f / mainInterval), looping ? "True" : "False");
|
||||
|
||||
auto kit = chanKeys.begin();
|
||||
|
||||
|
@ -398,6 +400,7 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
|
|||
Header head;
|
||||
head.read(reader);
|
||||
mainInterval = head.interval;
|
||||
looping = bool(head.looping);
|
||||
|
||||
WordBitmap keyBmp;
|
||||
keyBmp.read(reader, head.keyBitmapBitCount);
|
||||
|
@ -476,7 +479,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
|||
/* TODO: conform to MP1 ANIM3 */
|
||||
Header head;
|
||||
head.unk1 = 1;
|
||||
head.looping = 1;
|
||||
head.looping = looping;
|
||||
head.interval = mainInterval;
|
||||
head.rootBoneId = 0;
|
||||
head.scaleMult = 0.f;
|
||||
|
|
|
@ -27,6 +27,7 @@ struct ANIM : BigDNA
|
|||
std::vector<DNAANIM::Channel> channels;
|
||||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
bool looping = false;
|
||||
|
||||
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const;
|
||||
};
|
||||
|
|
|
@ -9,11 +9,14 @@ namespace DNAMP3
|
|||
|
||||
using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream;
|
||||
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig, bool additive) const
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os,
|
||||
const DNAANIM::RigInverter<CINF>& rig,
|
||||
bool additive) const
|
||||
{
|
||||
os.format("act.hecl_fps = round(%f)\n"
|
||||
"act.hecl_additive = %s\n",
|
||||
1.0f / mainInterval, additive ? "True" : "False");
|
||||
"act.hecl_additive = %s\n"
|
||||
"act.hecl_looping = %s\n",
|
||||
1.0f / mainInterval, additive ? "True" : "False", looping ? "True" : "False");
|
||||
|
||||
auto kit = chanKeys.begin() + 1;
|
||||
|
||||
|
@ -47,13 +50,11 @@ void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, co
|
|||
"\n";
|
||||
|
||||
if (std::get<1>(bone.second))
|
||||
{
|
||||
os << "transCurves = []\n"
|
||||
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n"
|
||||
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n"
|
||||
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
if (std::get<2>(bone.second))
|
||||
os << "scaleCurves = []\n"
|
||||
|
|
|
@ -27,8 +27,11 @@ struct ANIM : BigDNA
|
|||
std::vector<DNAANIM::Channel> channels;
|
||||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
bool looping = false;
|
||||
|
||||
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig, bool additive) const;
|
||||
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&,
|
||||
const DNAANIM::RigInverter<CINF>& rig,
|
||||
bool additive) const;
|
||||
};
|
||||
|
||||
struct ANIM0 : IANIM
|
||||
|
@ -111,7 +114,9 @@ struct ANIM : BigDNA
|
|||
return m_anim->binarySize(__isz + 4);
|
||||
}
|
||||
|
||||
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig, bool additive) const
|
||||
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os,
|
||||
const DNAANIM::RigInverter<CINF>& rig,
|
||||
bool additive) const
|
||||
{
|
||||
m_anim->sendANIMToBlender(os, rig, additive);
|
||||
}
|
||||
|
|
|
@ -47,18 +47,18 @@ CAnimData::CAnimData(ResId id,
|
|||
const std::shared_ptr<CAnimationManager>& animMgr,
|
||||
const std::shared_ptr<CTransitionManager>& transMgr,
|
||||
const TLockedToken<CCharacterFactory>& charFactory)
|
||||
: x0_charFactory(charFactory),
|
||||
xc_charInfo(character),
|
||||
xcc_layoutData(layout),
|
||||
xd8_modelData(model),
|
||||
xfc_animCtx(ctx.lock()),
|
||||
x100_animMgr(animMgr),
|
||||
x1d8_selfId(id),
|
||||
x1fc_transMgr(transMgr),
|
||||
x204_charIdx(charIdx),
|
||||
x208_defaultAnim(defaultAnim),
|
||||
x224_pose(layout->GetSegIdList().GetList().size()),
|
||||
x2fc_poseBuilder(layout)
|
||||
: x0_charFactory(charFactory),
|
||||
xc_charInfo(character),
|
||||
xcc_layoutData(layout),
|
||||
xd8_modelData(model),
|
||||
xfc_animCtx(ctx.lock()),
|
||||
x100_animMgr(animMgr),
|
||||
x1d8_selfId(id),
|
||||
x1fc_transMgr(transMgr),
|
||||
x204_charIdx(charIdx),
|
||||
x208_defaultAnim(defaultAnim),
|
||||
x224_pose(layout->GetSegIdList().GetList().size()),
|
||||
x2fc_poseBuilder(layout)
|
||||
{
|
||||
x220_25_loop = loop;
|
||||
|
||||
|
|
|
@ -16,6 +16,12 @@ zeus::CVector3f CCharLayoutInfo::GetFromParentUnrotated(const CSegId& id) const
|
|||
}
|
||||
}
|
||||
|
||||
zeus::CVector3f CCharLayoutInfo::GetFromRootUnrotated(const CSegId& id) const
|
||||
{
|
||||
const CCharLayoutNode::Bone& bone = x0_node->GetBoneMap()[id];
|
||||
return bone.x4_origin;
|
||||
}
|
||||
|
||||
CSegId CCharLayoutInfo::GetSegIdFromString(const std::string& name) const
|
||||
{
|
||||
auto it = x18_segIdMap.find(name);
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
const std::shared_ptr<CCharLayoutNode>& GetRootNode() const {return x0_node;}
|
||||
const CSegIdList& GetSegIdList() const {return x8_segIdList;}
|
||||
zeus::CVector3f GetFromParentUnrotated(const CSegId& id) const;
|
||||
zeus::CVector3f GetFromRootUnrotated(const CSegId& id) const;
|
||||
CSegId GetSegIdFromString(const std::string& name) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,9 +35,10 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
|
|||
|
||||
s32* cumulativesOut = &x4_cumulativeInts32[8*b];
|
||||
const s32* cumulativesIn = reinterpret_cast<const s32*>(chans);
|
||||
cumulativesOut[0] = cumulativesIn[0] >> 8;
|
||||
cumulativesOut[1] = cumulativesIn[1] >> 8;
|
||||
cumulativesOut[2] = cumulativesIn[2] >> 8;
|
||||
cumulativesOut[0] = 0;
|
||||
cumulativesOut[1] = cumulativesIn[0] >> 8;
|
||||
cumulativesOut[2] = cumulativesIn[1] >> 8;
|
||||
cumulativesOut[3] = cumulativesIn[2] >> 8;
|
||||
chans += 12;
|
||||
|
||||
u32 tCount = *reinterpret_cast<const u32*>(chans);
|
||||
|
@ -46,9 +47,9 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
|
|||
{
|
||||
x8_hasTrans1[b] = true;
|
||||
const s32* cumulativesIn = reinterpret_cast<const s32*>(chans);
|
||||
cumulativesOut[3] = cumulativesIn[0] >> 8;
|
||||
cumulativesOut[4] = cumulativesIn[1] >> 8;
|
||||
cumulativesOut[5] = cumulativesIn[2] >> 8;
|
||||
cumulativesOut[4] = cumulativesIn[0] >> 8;
|
||||
cumulativesOut[5] = cumulativesIn[1] >> 8;
|
||||
cumulativesOut[6] = cumulativesIn[2] >> 8;
|
||||
chans += 12;
|
||||
}
|
||||
else
|
||||
|
@ -63,9 +64,10 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
|
|||
chans += 6;
|
||||
|
||||
s32* cumulativesOut = &x4_cumulativeInts32[8*b];
|
||||
cumulativesOut[0] = *reinterpret_cast<const s16*>(chans);
|
||||
cumulativesOut[1] = *reinterpret_cast<const s16*>(chans + 3);
|
||||
cumulativesOut[2] = *reinterpret_cast<const s16*>(chans + 6);
|
||||
cumulativesOut[0] = 0;
|
||||
cumulativesOut[1] = *reinterpret_cast<const s16*>(chans);
|
||||
cumulativesOut[2] = *reinterpret_cast<const s16*>(chans + 3);
|
||||
cumulativesOut[3] = *reinterpret_cast<const s16*>(chans + 6);
|
||||
chans += 9;
|
||||
|
||||
u16 tCount = *reinterpret_cast<const u16*>(chans);
|
||||
|
@ -73,9 +75,9 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
|
|||
if (tCount)
|
||||
{
|
||||
x8_hasTrans1[b] = true;
|
||||
cumulativesOut[3] = *reinterpret_cast<const s16*>(chans);
|
||||
cumulativesOut[4] = *reinterpret_cast<const s16*>(chans + 3);
|
||||
cumulativesOut[5] = *reinterpret_cast<const s16*>(chans + 6);
|
||||
cumulativesOut[4] = *reinterpret_cast<const s16*>(chans);
|
||||
cumulativesOut[5] = *reinterpret_cast<const s16*>(chans + 3);
|
||||
cumulativesOut[6] = *reinterpret_cast<const s16*>(chans + 6);
|
||||
chans += 9;
|
||||
}
|
||||
else
|
||||
|
@ -491,8 +493,9 @@ SAdvancementResults CFBStreamedAnimReader::VAdvanceView(const CCharAnimTime& dt)
|
|||
nextTime = animDur;
|
||||
res.x0_remTime = nextTime - animDur;
|
||||
}
|
||||
xc_curTime = nextTime;
|
||||
|
||||
x7c_totals.SetTime(x108_bitLoader, nextTime);
|
||||
x7c_totals.SetTime(x108_bitLoader, xc_curTime);
|
||||
UpdatePOIStates();
|
||||
zeus::CQuaternion nextQ = GetRotation(3);
|
||||
zeus::CVector3f nextV = GetOffset(3);
|
||||
|
|
|
@ -16,17 +16,18 @@ void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout,
|
|||
xcec_rootId = boneId;
|
||||
xcf0_hasRoot = true;
|
||||
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
|
||||
x38_treeMap[boneId] = CTreeNode(origin);
|
||||
CTreeNode& node = x38_treeMap[boneId];
|
||||
node.x14_offset = origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildIntoHierarchy(layout, bone.x0_parentId, nullId);
|
||||
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
|
||||
CTreeNode& pNode = x38_treeMap[bone.x0_parentId];
|
||||
CTreeNode node(origin);
|
||||
CTreeNode& node = x38_treeMap[boneId];
|
||||
node.x14_offset = origin;
|
||||
node.x1_sibling = pNode.x0_child;
|
||||
pNode.x0_child = boneId;
|
||||
x38_treeMap[boneId] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,10 +36,19 @@ void CHierarchyPoseBuilder::RecursivelyBuildNoScale(const CSegId& boneId, const
|
|||
CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot,
|
||||
const zeus::CMatrix3f& parentXf, const zeus::CVector3f& parentOffset) const
|
||||
{
|
||||
zeus::CVector3f bindOffset;
|
||||
if (x0_layoutDesc.GetScaledLayoutDescription())
|
||||
{
|
||||
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription();
|
||||
bindOffset = desc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
|
||||
}
|
||||
else
|
||||
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
|
||||
|
||||
zeus::CQuaternion quat = parentRot * node.x4_rotation;
|
||||
zeus::CMatrix3f xf = quat;
|
||||
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
|
||||
pose.Insert(boneId, quat, xfOffset);
|
||||
pose.Insert(boneId, quat, xfOffset, bindOffset);
|
||||
|
||||
CSegId curBone = node.x0_child;
|
||||
while (curBone != 0)
|
||||
|
@ -56,19 +66,27 @@ void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNo
|
|||
zeus::CQuaternion quat = parentRot * node.x4_rotation;
|
||||
|
||||
float scale;
|
||||
zeus::CVector3f bindOffset;
|
||||
if (x0_layoutDesc.GetScaledLayoutDescription())
|
||||
scale = x0_layoutDesc.GetScaledLayoutDescription()->GetScale();
|
||||
{
|
||||
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription();
|
||||
scale = desc.GetScale();
|
||||
bindOffset = desc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = 1.f;
|
||||
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
|
||||
}
|
||||
|
||||
zeus::CMatrix3f mtxXf;
|
||||
if (scale == 1.f)
|
||||
mtxXf = quat;
|
||||
else
|
||||
mtxXf = parentXf * quat * zeus::CMatrix3f(scale);
|
||||
mtxXf = parentXf * zeus::CMatrix3f(scale);
|
||||
|
||||
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
|
||||
pose.Insert(boneId, mtxXf, xfOffset);
|
||||
pose.Insert(boneId, mtxXf, xfOffset, bindOffset);
|
||||
|
||||
CSegId curBone = node.x0_child;
|
||||
while (curBone != 0)
|
||||
|
@ -137,12 +155,15 @@ void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose)
|
|||
|
||||
void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat)
|
||||
{
|
||||
x38_treeMap[boneId] = CTreeNode(quat);
|
||||
CTreeNode& node = x38_treeMap[boneId];
|
||||
node.x4_rotation = quat;
|
||||
}
|
||||
|
||||
void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset)
|
||||
{
|
||||
x38_treeMap[boneId] = CTreeNode(quat, offset);
|
||||
CTreeNode& node = x38_treeMap[boneId];
|
||||
node.x4_rotation = quat;
|
||||
node.x14_offset = offset;
|
||||
}
|
||||
|
||||
CHierarchyPoseBuilder::CHierarchyPoseBuilder(const CLayoutDescription& layout)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "CPoseAsTransforms.hpp"
|
||||
#include "CCharLayoutInfo.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CPoseAsTransforms::CPoseAsTransforms(u8 boneCount)
|
||||
: x1_count(boneCount), xd0_transformArr(new zeus::CTransform[boneCount])
|
||||
: x1_count(boneCount), xd0_transformArr(new Transform[boneCount])
|
||||
{}
|
||||
|
||||
bool CPoseAsTransforms::ContainsDataFor(const CSegId& id) const
|
||||
|
@ -33,26 +34,38 @@ void CPoseAsTransforms::AccumulateScaledTransform(const CSegId& id,
|
|||
const zeus::CTransform& CPoseAsTransforms::GetTransform(const CSegId& id) const
|
||||
{
|
||||
const std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
return xd0_transformArr[link.second];
|
||||
return xd0_transformArr[link.second].m_originToAccum;
|
||||
}
|
||||
|
||||
const zeus::CTransform& CPoseAsTransforms::GetRestToAccumTransform(const CSegId& id) const
|
||||
{
|
||||
const std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
return xd0_transformArr[link.second].m_restPoseToAccum;
|
||||
}
|
||||
|
||||
const zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const
|
||||
{
|
||||
const std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
return xd0_transformArr[link.second].origin;
|
||||
return xd0_transformArr[link.second].m_originToAccum.origin;
|
||||
}
|
||||
|
||||
const zeus::CMatrix3f& CPoseAsTransforms::GetRotation(const CSegId& id) const
|
||||
{
|
||||
const std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
return xd0_transformArr[link.second].basis;
|
||||
return xd0_transformArr[link.second].m_originToAccum.basis;
|
||||
}
|
||||
|
||||
void CPoseAsTransforms::Insert(const CSegId& id,
|
||||
const zeus::CMatrix3f& rotation,
|
||||
const zeus::CVector3f& offset)
|
||||
const zeus::CVector3f& offset,
|
||||
const zeus::CVector3f& restOffset)
|
||||
{
|
||||
xd0_transformArr[x0_nextId] = zeus::CTransform(rotation, offset);
|
||||
Transform& xfOut = xd0_transformArr[x0_nextId];
|
||||
xfOut.m_originToAccum = zeus::CTransform(rotation, offset);
|
||||
xfOut.m_restPoseToAccum = xfOut.m_originToAccum * zeus::CTransform::Translate(-restOffset);
|
||||
printf("INSBONE %d\n", int(id));
|
||||
xfOut.m_originToAccum.printMatrix();
|
||||
|
||||
std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
link.first = xd4_lastInserted;
|
||||
link.second = x0_nextId;
|
||||
|
|
|
@ -7,13 +7,21 @@
|
|||
|
||||
namespace urde
|
||||
{
|
||||
class CCharLayoutInfo;
|
||||
|
||||
class CPoseAsTransforms
|
||||
{
|
||||
public:
|
||||
struct Transform
|
||||
{
|
||||
zeus::CTransform m_originToAccum;
|
||||
zeus::CTransform m_restPoseToAccum;
|
||||
};
|
||||
private:
|
||||
CSegId x0_nextId = 0;
|
||||
CSegId x1_count;
|
||||
std::pair<CSegId, CSegId> x8_links[100];
|
||||
std::unique_ptr<zeus::CTransform[]> xd0_transformArr;
|
||||
std::unique_ptr<Transform[]> xd0_transformArr;
|
||||
CSegId xd4_lastInserted = 0;
|
||||
public:
|
||||
CPoseAsTransforms(u8 boneCount);
|
||||
|
@ -21,9 +29,13 @@ public:
|
|||
void Clear();
|
||||
void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const;
|
||||
const zeus::CTransform& GetTransform(const CSegId& id) const;
|
||||
const zeus::CTransform& GetRestToAccumTransform(const CSegId& id) const;
|
||||
const zeus::CVector3f& GetOffset(const CSegId& id) const;
|
||||
const zeus::CMatrix3f& GetRotation(const CSegId& id) const;
|
||||
void Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset);
|
||||
void Insert(const CSegId& id,
|
||||
const zeus::CMatrix3f& rotation,
|
||||
const zeus::CVector3f& offset,
|
||||
const zeus::CVector3f& restOffset);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,12 @@ void CSkinBank::GetBankTransforms(std::vector<const zeus::CTransform*>& out,
|
|||
const CPoseAsTransforms& pose) const
|
||||
{
|
||||
for (CSegId id : x0_segments)
|
||||
out.push_back(&pose.GetTransform(id));
|
||||
{
|
||||
const zeus::CTransform& xf = pose.GetRestToAccumTransform(id);
|
||||
//printf("BONE %d\n", int(id));
|
||||
//xf.printMatrix();
|
||||
out.push_back(&xf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -474,14 +474,15 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
|
|||
{
|
||||
/* Skinned */
|
||||
std::vector<const zeus::CTransform*> bankTransforms;
|
||||
bankTransforms.reserve(m_weightVecCount*4);
|
||||
size_t weightCount = m_weightVecCount * 4;
|
||||
bankTransforms.reserve(weightCount);
|
||||
for (size_t i=0 ; i<m_skinBankCount ; ++i)
|
||||
{
|
||||
if (cskr && pose)
|
||||
{
|
||||
cskr->GetBankTransforms(bankTransforms, *pose, i);
|
||||
|
||||
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
|
||||
for (size_t w=0 ; w<weightCount ; ++w)
|
||||
{
|
||||
zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
|
||||
if (w >= bankTransforms.size())
|
||||
|
@ -490,15 +491,15 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
|
|||
mv = (CGraphics::g_GXModelView * *bankTransforms[w]).toMatrix4f();
|
||||
dataCur += sizeof(zeus::CMatrix4f);
|
||||
}
|
||||
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
|
||||
for (size_t w=0 ; w<weightCount ; ++w)
|
||||
{
|
||||
zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
|
||||
if (w >= bankTransforms.size())
|
||||
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f();
|
||||
else
|
||||
{
|
||||
zeus::CTransform xf = (CGraphics::g_GXModelView * *bankTransforms[w]).inverse();
|
||||
xf.origin.zeroOut();
|
||||
zeus::CTransform xf = (CGraphics::g_GXModelView.basis * bankTransforms[w]->basis);
|
||||
xf.basis.invert();
|
||||
xf.basis.transpose();
|
||||
mvinv = xf.toMatrix4f();
|
||||
}
|
||||
|
@ -509,13 +510,13 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
|
|||
}
|
||||
else
|
||||
{
|
||||
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
|
||||
for (size_t w=0 ; w<weightCount ; ++w)
|
||||
{
|
||||
zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
|
||||
mv = CGraphics::g_GXModelView.toMatrix4f();
|
||||
dataCur += sizeof(zeus::CMatrix4f);
|
||||
}
|
||||
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
|
||||
for (size_t w=0 ; w<weightCount ; ++w)
|
||||
{
|
||||
zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
|
||||
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f();
|
||||
|
@ -675,7 +676,7 @@ CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* stor
|
|||
{
|
||||
hecl::Runtime::ShaderTag tag(mat.heclIr,
|
||||
hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount,
|
||||
0, 8, boo::Primitive(hmdlMeta.topology),
|
||||
hmdlMeta.weightCount * 4, 8, boo::Primitive(hmdlMeta.topology),
|
||||
true, true, true);
|
||||
matSet.m_shaders.push_back(CModelShaders::g_ModelShaders->buildExtendedShader(tag, mat.heclIr, "CMDL", ctx));
|
||||
}
|
||||
|
|
2
amuse
2
amuse
|
@ -1 +1 @@
|
|||
Subproject commit af68ee61e15567e74f057964fb2b852476c1e666
|
||||
Subproject commit 38f24ce3e43200a1dde31f97fa37c2cf4a816ba0
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit 29c77ef93ca9c5102c01e4f81ef3b5b7675150dd
|
||||
Subproject commit c4206ca8007bf9d0b7fd9752be932b9a285905ef
|
2
specter
2
specter
|
@ -1 +1 @@
|
|||
Subproject commit 24414bf4d447697caa048a9346ffa9870cb530a5
|
||||
Subproject commit 2ec24ac74cf269d29926c6e78372a279eeb1cd74
|
Loading…
Reference in New Issue