2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-06 13:25:53 +00:00

Tons of animation bug fixes

This commit is contained in:
Jack Andersen 2016-09-05 19:52:51 -10:00
parent 668c4f7eee
commit 9b436b4b23
21 changed files with 168 additions and 85 deletions

View File

@ -325,8 +325,8 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
float quantRangeF = float(quantRange); float quantRangeF = float(quantRange);
/* Pre-pass to calculate translation multiplier */ /* Pre-pass to calculate translation multiplier */
float maxTransDiff = 0.0f; float maxTransVal = 0.0f;
float maxScaleDiff = 0.0f; float maxScaleVal = 0.0f;
auto kit = chanKeys.begin(); auto kit = chanKeys.begin();
for (Channel& chan : channels) for (Channel& chan : channels)
{ {
@ -334,31 +334,27 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
{ {
case Channel::Type::Translation: case Channel::Type::Translation:
{ {
const Value* last = &(*kit)[0]; for (auto it=kit->begin();
for (auto it=kit->begin() + 1;
it != kit->end(); it != kit->end();
++it) ++it)
{ {
const Value* current = &*it; const Value* key = &*it;
maxTransDiff = std::max(maxTransDiff, current->v3.vec[0] - last->v3.vec[0]); maxTransVal = std::max(maxTransVal, std::fabs(key->v3.vec[0]));
maxTransDiff = std::max(maxTransDiff, current->v3.vec[1] - last->v3.vec[1]); maxTransVal = std::max(maxTransVal, std::fabs(key->v3.vec[1]));
maxTransDiff = std::max(maxTransDiff, current->v3.vec[2] - last->v3.vec[2]); maxTransVal = std::max(maxTransVal, std::fabs(key->v3.vec[2]));
last = current;
} }
break; break;
} }
case Channel::Type::Scale: case Channel::Type::Scale:
{ {
const Value* last = &(*kit)[0]; for (auto it=kit->begin();
for (auto it=kit->begin() + 1;
it != kit->end(); it != kit->end();
++it) ++it)
{ {
const Value* current = &*it; const Value* key = &*it;
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[0] - last->v3.vec[0]); maxScaleVal = std::max(maxScaleVal, std::fabs(key->v3.vec[0]));
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[1] - last->v3.vec[1]); maxScaleVal = std::max(maxScaleVal, std::fabs(key->v3.vec[1]));
maxScaleDiff = std::max(maxScaleDiff, current->v3.vec[2] - last->v3.vec[2]); maxScaleVal = std::max(maxScaleVal, std::fabs(key->v3.vec[2]));
last = current;
} }
break; break;
} }
@ -366,8 +362,8 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
} }
++kit; ++kit;
} }
transMultOut = maxTransDiff / quantRangeF; transMultOut = maxTransVal / quantRangeF;
scaleMultOut = maxScaleDiff / quantRangeF; scaleMultOut = maxScaleVal / quantRangeF;
/* Output channel inits */ /* Output channel inits */
std::vector<QuantizedValue> initVals; std::vector<QuantizedValue> initVals;

View File

@ -1148,6 +1148,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
}); });
std::unordered_map<std::string, atInt32> boneIdMap; std::unordered_map<std::string, atInt32> boneIdMap;
std::experimental::optional<CINF> rigCinf;
std::experimental::optional<DNAANIM::RigInverter<CINF>> rigInv; std::experimental::optional<DNAANIM::RigInverter<CINF>> rigInv;
/* Write out CINF resources */ /* Write out CINF resources */
@ -1164,8 +1165,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
if (!rigInv) if (!rigInv)
{ {
rigCinf.emplace(cinf);
auto matrices = ds.getBoneMatrices(arm.name); auto matrices = ds.getBoneMatrices(arm.name);
rigInv.emplace(cinf, matrices); rigInv.emplace(*rigCinf, matrices);
} }
} }
ds.close(); ds.close();

View File

@ -10,7 +10,9 @@ using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream;
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const 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(); auto kit = chanKeys.begin();
@ -270,6 +272,7 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
head.read(reader); head.read(reader);
evnt = head.evnt; evnt = head.evnt;
mainInterval = head.interval; mainInterval = head.interval;
looping = bool(head.looping);
WordBitmap keyBmp; WordBitmap keyBmp;
keyBmp.read(reader, head.keyBitmapBitCount); keyBmp.read(reader, head.keyBitmapBitCount);
@ -379,7 +382,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
head.unk0 = 1; head.unk0 = 1;
head.interval = mainInterval; head.interval = mainInterval;
head.rootBoneId = 3; head.rootBoneId = 3;
head.looping = 0; head.looping = looping;
head.unk3 = 1; head.unk3 = 1;
WordBitmap keyBmp; WordBitmap keyBmp;
@ -530,6 +533,7 @@ ANIM::ANIM(const BlenderAction& act,
{ {
m_anim.reset(new struct ANIM2(pc)); m_anim.reset(new struct ANIM2(pc));
IANIM& newAnim = *m_anim; IANIM& newAnim = *m_anim;
newAnim.looping = act.looping;
newAnim.bones.reserve(act.channels.size()); newAnim.bones.reserve(act.channels.size());
size_t extChanCount = 0; size_t extChanCount = 0;

View File

@ -28,6 +28,7 @@ struct ANIM : BigDNA
std::vector<std::vector<DNAANIM::Value>> chanKeys; std::vector<std::vector<DNAANIM::Value>> chanKeys;
float mainInterval = 0.0; float mainInterval = 0.0;
UniqueID32 evnt; UniqueID32 evnt;
bool looping = false;
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const; void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const;
}; };
@ -235,6 +236,13 @@ struct ANIM : BigDNA
m_anim->sendANIMToBlender(os, rig); m_anim->sendANIMToBlender(os, rig);
} }
bool isLooping() const
{
if (!m_anim)
return false;
return m_anim->looping;
}
using BlenderAction = hecl::BlenderConnection::DataStream::Actor::Action; using BlenderAction = hecl::BlenderConnection::DataStream::Actor::Action;
ANIM() = default; ANIM() = default;

View File

@ -135,7 +135,7 @@ CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& i
if (bone->children.size()) if (bone->children.size())
{ {
int curId = 4; int curId = 4;
RecursiveAddArmatureBone(armature, bone, 3, curId, idMap, nameMap); RecursiveAddArmatureBone(armature, armature.getChild(bone, 0), 3, curId, idMap, nameMap);
} }
bones.emplace_back(); bones.emplace_back();
@ -144,6 +144,7 @@ CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& i
boneOut.id = 3; boneOut.id = 3;
boneOut.parentId = 2; boneOut.parentId = 2;
boneOut.origin = bone->origin; boneOut.origin = bone->origin;
idMap.emplace(std::make_pair(bone->name, 3));
if (bone->children.size()) if (bone->children.size())
{ {

View File

@ -9,7 +9,9 @@ using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream;
void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const 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(); auto kit = chanKeys.begin();
@ -398,6 +400,7 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
Header head; Header head;
head.read(reader); head.read(reader);
mainInterval = head.interval; mainInterval = head.interval;
looping = bool(head.looping);
WordBitmap keyBmp; WordBitmap keyBmp;
keyBmp.read(reader, head.keyBitmapBitCount); keyBmp.read(reader, head.keyBitmapBitCount);
@ -476,7 +479,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
/* TODO: conform to MP1 ANIM3 */ /* TODO: conform to MP1 ANIM3 */
Header head; Header head;
head.unk1 = 1; head.unk1 = 1;
head.looping = 1; head.looping = looping;
head.interval = mainInterval; head.interval = mainInterval;
head.rootBoneId = 0; head.rootBoneId = 0;
head.scaleMult = 0.f; head.scaleMult = 0.f;

View File

@ -27,6 +27,7 @@ struct ANIM : BigDNA
std::vector<DNAANIM::Channel> channels; std::vector<DNAANIM::Channel> channels;
std::vector<std::vector<DNAANIM::Value>> chanKeys; std::vector<std::vector<DNAANIM::Value>> chanKeys;
float mainInterval = 0.0; float mainInterval = 0.0;
bool looping = false;
void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const; void sendANIMToBlender(hecl::BlenderConnection::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const;
}; };

View File

@ -9,11 +9,14 @@ namespace DNAMP3
using ANIMOutStream = hecl::BlenderConnection::PyOutStream::ANIMOutStream; 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" os.format("act.hecl_fps = round(%f)\n"
"act.hecl_additive = %s\n", "act.hecl_additive = %s\n"
1.0f / mainInterval, additive ? "True" : "False"); "act.hecl_looping = %s\n",
1.0f / mainInterval, additive ? "True" : "False", looping ? "True" : "False");
auto kit = chanKeys.begin() + 1; auto kit = chanKeys.begin() + 1;
@ -47,13 +50,11 @@ void ANIM::IANIM::sendANIMToBlender(hecl::BlenderConnection::PyOutStream& os, co
"\n"; "\n";
if (std::get<1>(bone.second)) if (std::get<1>(bone.second))
{
os << "transCurves = []\n" 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=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=1, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n" "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
"\n"; "\n";
}
if (std::get<2>(bone.second)) if (std::get<2>(bone.second))
os << "scaleCurves = []\n" os << "scaleCurves = []\n"

View File

@ -27,8 +27,11 @@ struct ANIM : BigDNA
std::vector<DNAANIM::Channel> channels; std::vector<DNAANIM::Channel> channels;
std::vector<std::vector<DNAANIM::Value>> chanKeys; std::vector<std::vector<DNAANIM::Value>> chanKeys;
float mainInterval = 0.0; 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 struct ANIM0 : IANIM
@ -111,7 +114,9 @@ struct ANIM : BigDNA
return m_anim->binarySize(__isz + 4); 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); m_anim->sendANIMToBlender(os, rig, additive);
} }

View File

@ -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 CSegId CCharLayoutInfo::GetSegIdFromString(const std::string& name) const
{ {
auto it = x18_segIdMap.find(name); auto it = x18_segIdMap.find(name);

View File

@ -37,6 +37,7 @@ public:
const std::shared_ptr<CCharLayoutNode>& GetRootNode() const {return x0_node;} const std::shared_ptr<CCharLayoutNode>& GetRootNode() const {return x0_node;}
const CSegIdList& GetSegIdList() const {return x8_segIdList;} const CSegIdList& GetSegIdList() const {return x8_segIdList;}
zeus::CVector3f GetFromParentUnrotated(const CSegId& id) const; zeus::CVector3f GetFromParentUnrotated(const CSegId& id) const;
zeus::CVector3f GetFromRootUnrotated(const CSegId& id) const;
CSegId GetSegIdFromString(const std::string& name) const; CSegId GetSegIdFromString(const std::string& name) const;
}; };

View File

@ -35,9 +35,10 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
s32* cumulativesOut = &x4_cumulativeInts32[8*b]; s32* cumulativesOut = &x4_cumulativeInts32[8*b];
const s32* cumulativesIn = reinterpret_cast<const s32*>(chans); const s32* cumulativesIn = reinterpret_cast<const s32*>(chans);
cumulativesOut[0] = cumulativesIn[0] >> 8; cumulativesOut[0] = 0;
cumulativesOut[1] = cumulativesIn[1] >> 8; cumulativesOut[1] = cumulativesIn[0] >> 8;
cumulativesOut[2] = cumulativesIn[2] >> 8; cumulativesOut[2] = cumulativesIn[1] >> 8;
cumulativesOut[3] = cumulativesIn[2] >> 8;
chans += 12; chans += 12;
u32 tCount = *reinterpret_cast<const u32*>(chans); u32 tCount = *reinterpret_cast<const u32*>(chans);
@ -46,9 +47,9 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
{ {
x8_hasTrans1[b] = true; x8_hasTrans1[b] = true;
const s32* cumulativesIn = reinterpret_cast<const s32*>(chans); const s32* cumulativesIn = reinterpret_cast<const s32*>(chans);
cumulativesOut[3] = cumulativesIn[0] >> 8; cumulativesOut[4] = cumulativesIn[0] >> 8;
cumulativesOut[4] = cumulativesIn[1] >> 8; cumulativesOut[5] = cumulativesIn[1] >> 8;
cumulativesOut[5] = cumulativesIn[2] >> 8; cumulativesOut[6] = cumulativesIn[2] >> 8;
chans += 12; chans += 12;
} }
else else
@ -63,9 +64,10 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
chans += 6; chans += 6;
s32* cumulativesOut = &x4_cumulativeInts32[8*b]; s32* cumulativesOut = &x4_cumulativeInts32[8*b];
cumulativesOut[0] = *reinterpret_cast<const s16*>(chans); cumulativesOut[0] = 0;
cumulativesOut[1] = *reinterpret_cast<const s16*>(chans + 3); cumulativesOut[1] = *reinterpret_cast<const s16*>(chans);
cumulativesOut[2] = *reinterpret_cast<const s16*>(chans + 6); cumulativesOut[2] = *reinterpret_cast<const s16*>(chans + 3);
cumulativesOut[3] = *reinterpret_cast<const s16*>(chans + 6);
chans += 9; chans += 9;
u16 tCount = *reinterpret_cast<const u16*>(chans); u16 tCount = *reinterpret_cast<const u16*>(chans);
@ -73,9 +75,9 @@ void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& sourc
if (tCount) if (tCount)
{ {
x8_hasTrans1[b] = true; x8_hasTrans1[b] = true;
cumulativesOut[3] = *reinterpret_cast<const s16*>(chans); cumulativesOut[4] = *reinterpret_cast<const s16*>(chans);
cumulativesOut[4] = *reinterpret_cast<const s16*>(chans + 3); cumulativesOut[5] = *reinterpret_cast<const s16*>(chans + 3);
cumulativesOut[5] = *reinterpret_cast<const s16*>(chans + 6); cumulativesOut[6] = *reinterpret_cast<const s16*>(chans + 6);
chans += 9; chans += 9;
} }
else else
@ -491,8 +493,9 @@ SAdvancementResults CFBStreamedAnimReader::VAdvanceView(const CCharAnimTime& dt)
nextTime = animDur; nextTime = animDur;
res.x0_remTime = nextTime - animDur; res.x0_remTime = nextTime - animDur;
} }
xc_curTime = nextTime;
x7c_totals.SetTime(x108_bitLoader, nextTime); x7c_totals.SetTime(x108_bitLoader, xc_curTime);
UpdatePOIStates(); UpdatePOIStates();
zeus::CQuaternion nextQ = GetRotation(3); zeus::CQuaternion nextQ = GetRotation(3);
zeus::CVector3f nextV = GetOffset(3); zeus::CVector3f nextV = GetOffset(3);

View File

@ -16,17 +16,18 @@ void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout,
xcec_rootId = boneId; xcec_rootId = boneId;
xcf0_hasRoot = true; xcf0_hasRoot = true;
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId); zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
x38_treeMap[boneId] = CTreeNode(origin); CTreeNode& node = x38_treeMap[boneId];
node.x14_offset = origin;
} }
else else
{ {
BuildIntoHierarchy(layout, bone.x0_parentId, nullId); BuildIntoHierarchy(layout, bone.x0_parentId, nullId);
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId); zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
CTreeNode& pNode = x38_treeMap[bone.x0_parentId]; 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; node.x1_sibling = pNode.x0_child;
pNode.x0_child = boneId; 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, CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot,
const zeus::CMatrix3f& parentXf, const zeus::CVector3f& parentOffset) const 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::CQuaternion quat = parentRot * node.x4_rotation;
zeus::CMatrix3f xf = quat; zeus::CMatrix3f xf = quat;
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
pose.Insert(boneId, quat, xfOffset); pose.Insert(boneId, quat, xfOffset, bindOffset);
CSegId curBone = node.x0_child; CSegId curBone = node.x0_child;
while (curBone != 0) while (curBone != 0)
@ -56,19 +66,27 @@ void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNo
zeus::CQuaternion quat = parentRot * node.x4_rotation; zeus::CQuaternion quat = parentRot * node.x4_rotation;
float scale; float scale;
zeus::CVector3f bindOffset;
if (x0_layoutDesc.GetScaledLayoutDescription()) 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 else
{
scale = 1.f; scale = 1.f;
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
}
zeus::CMatrix3f mtxXf; zeus::CMatrix3f mtxXf;
if (scale == 1.f) if (scale == 1.f)
mtxXf = quat; mtxXf = quat;
else else
mtxXf = parentXf * quat * zeus::CMatrix3f(scale); mtxXf = parentXf * zeus::CMatrix3f(scale);
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
pose.Insert(boneId, mtxXf, xfOffset); pose.Insert(boneId, mtxXf, xfOffset, bindOffset);
CSegId curBone = node.x0_child; CSegId curBone = node.x0_child;
while (curBone != 0) while (curBone != 0)
@ -137,12 +155,15 @@ void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose)
void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat) 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) 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) CHierarchyPoseBuilder::CHierarchyPoseBuilder(const CLayoutDescription& layout)

View File

@ -1,10 +1,11 @@
#include "CPoseAsTransforms.hpp" #include "CPoseAsTransforms.hpp"
#include "CCharLayoutInfo.hpp"
namespace urde namespace urde
{ {
CPoseAsTransforms::CPoseAsTransforms(u8 boneCount) 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 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 zeus::CTransform& CPoseAsTransforms::GetTransform(const CSegId& id) const
{ {
const std::pair<CSegId, CSegId>& link = x8_links[id]; 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 zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const
{ {
const std::pair<CSegId, CSegId>& link = x8_links[id]; 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 zeus::CMatrix3f& CPoseAsTransforms::GetRotation(const CSegId& id) const
{ {
const std::pair<CSegId, CSegId>& link = x8_links[id]; 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, void CPoseAsTransforms::Insert(const CSegId& id,
const zeus::CMatrix3f& rotation, 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]; std::pair<CSegId, CSegId>& link = x8_links[id];
link.first = xd4_lastInserted; link.first = xd4_lastInserted;
link.second = x0_nextId; link.second = x0_nextId;

View File

@ -7,13 +7,21 @@
namespace urde namespace urde
{ {
class CCharLayoutInfo;
class CPoseAsTransforms class CPoseAsTransforms
{ {
public:
struct Transform
{
zeus::CTransform m_originToAccum;
zeus::CTransform m_restPoseToAccum;
};
private:
CSegId x0_nextId = 0; CSegId x0_nextId = 0;
CSegId x1_count; CSegId x1_count;
std::pair<CSegId, CSegId> x8_links[100]; std::pair<CSegId, CSegId> x8_links[100];
std::unique_ptr<zeus::CTransform[]> xd0_transformArr; std::unique_ptr<Transform[]> xd0_transformArr;
CSegId xd4_lastInserted = 0; CSegId xd4_lastInserted = 0;
public: public:
CPoseAsTransforms(u8 boneCount); CPoseAsTransforms(u8 boneCount);
@ -21,9 +29,13 @@ public:
void Clear(); void Clear();
void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const; void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const;
const zeus::CTransform& GetTransform(const CSegId& id) 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::CVector3f& GetOffset(const CSegId& id) const;
const zeus::CMatrix3f& GetRotation(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);
}; };
} }

View File

@ -16,7 +16,12 @@ void CSkinBank::GetBankTransforms(std::vector<const zeus::CTransform*>& out,
const CPoseAsTransforms& pose) const const CPoseAsTransforms& pose) const
{ {
for (CSegId id : x0_segments) 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);
}
} }
} }

View File

@ -474,14 +474,15 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
{ {
/* Skinned */ /* Skinned */
std::vector<const zeus::CTransform*> bankTransforms; 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) for (size_t i=0 ; i<m_skinBankCount ; ++i)
{ {
if (cskr && pose) if (cskr && pose)
{ {
cskr->GetBankTransforms(bankTransforms, *pose, i); 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); zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
if (w >= bankTransforms.size()) if (w >= bankTransforms.size())
@ -490,15 +491,15 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
mv = (CGraphics::g_GXModelView * *bankTransforms[w]).toMatrix4f(); mv = (CGraphics::g_GXModelView * *bankTransforms[w]).toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f); 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); zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
if (w >= bankTransforms.size()) if (w >= bankTransforms.size())
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f();
else else
{ {
zeus::CTransform xf = (CGraphics::g_GXModelView * *bankTransforms[w]).inverse(); zeus::CTransform xf = (CGraphics::g_GXModelView.basis * bankTransforms[w]->basis);
xf.origin.zeroOut(); xf.basis.invert();
xf.basis.transpose(); xf.basis.transpose();
mvinv = xf.toMatrix4f(); mvinv = xf.toMatrix4f();
} }
@ -509,13 +510,13 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
} }
else 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); zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
mv = CGraphics::g_GXModelView.toMatrix4f(); mv = CGraphics::g_GXModelView.toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f); 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); zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); 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, hecl::Runtime::ShaderTag tag(mat.heclIr,
hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount, hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount,
0, 8, boo::Primitive(hmdlMeta.topology), hmdlMeta.weightCount * 4, 8, boo::Primitive(hmdlMeta.topology),
true, true, true); true, true, true);
matSet.m_shaders.push_back(CModelShaders::g_ModelShaders->buildExtendedShader(tag, mat.heclIr, "CMDL", ctx)); matSet.m_shaders.push_back(CModelShaders::g_ModelShaders->buildExtendedShader(tag, mat.heclIr, "CMDL", ctx));
} }

2
amuse

@ -1 +1 @@
Subproject commit af68ee61e15567e74f057964fb2b852476c1e666 Subproject commit 38f24ce3e43200a1dde31f97fa37c2cf4a816ba0

2
hecl

@ -1 +1 @@
Subproject commit 29c77ef93ca9c5102c01e4f81ef3b5b7675150dd Subproject commit c4206ca8007bf9d0b7fd9752be932b9a285905ef

@ -1 +1 @@
Subproject commit 24414bf4d447697caa048a9346ffa9870cb530a5 Subproject commit 2ec24ac74cf269d29926c6e78372a279eeb1cd74