metaforce/Runtime/Character/CHierarchyPoseBuilder.cpp

185 lines
6.2 KiB
C++
Raw Normal View History

2016-04-13 23:07:18 +00:00
#include "CHierarchyPoseBuilder.hpp"
#include "CAnimData.hpp"
#include "CCharLayoutInfo.hpp"
namespace urde
{
void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout,
const CSegId& boneId, const CSegId& nullId)
{
2016-09-04 02:27:35 +00:00
if (!x38_treeMap.HasElement(boneId))
2016-04-13 23:07:18 +00:00
{
2016-04-16 03:24:25 +00:00
const CCharLayoutNode::Bone& bone = layout.GetRootNode()->GetBoneMap()[boneId];
2016-04-13 23:07:18 +00:00
if (bone.x0_parentId == nullId)
{
xcec_rootId = boneId;
xcf0_hasRoot = true;
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
CTreeNode& node = x38_treeMap[boneId];
node.x14_offset = origin;
2016-04-13 23:07:18 +00:00
}
else
{
BuildIntoHierarchy(layout, bone.x0_parentId, nullId);
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
2016-09-04 02:27:35 +00:00
CTreeNode& pNode = x38_treeMap[bone.x0_parentId];
2016-09-06 05:52:51 +00:00
CTreeNode& node = x38_treeMap[boneId];
node.x14_offset = origin;
2016-04-13 23:07:18 +00:00
node.x1_sibling = pNode.x0_child;
pNode.x0_child = boneId;
}
}
}
void CHierarchyPoseBuilder::RecursivelyBuildNoScale(const CSegId& boneId, const CTreeNode& node,
CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot,
const zeus::CMatrix3f& parentXf, const zeus::CVector3f& parentOffset) const
{
2016-09-06 05:52:51 +00:00
zeus::CVector3f bindOffset;
if (x0_layoutDesc.GetScaledLayoutDescription())
{
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription();
2017-01-08 03:36:24 +00:00
bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId);
2016-09-06 05:52:51 +00:00
}
else
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
2016-04-13 23:07:18 +00:00
zeus::CQuaternion quat = parentRot * node.x4_rotation;
zeus::CMatrix3f xf = quat;
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
2016-09-06 05:52:51 +00:00
pose.Insert(boneId, quat, xfOffset, bindOffset);
2016-04-13 23:07:18 +00:00
CSegId curBone = node.x0_child;
while (curBone != 0)
{
2016-09-04 02:27:35 +00:00
const CTreeNode& node = x38_treeMap[curBone];
2016-04-13 23:07:18 +00:00
RecursivelyBuild(curBone, node, pose, quat, xf, xfOffset);
curBone = node.x1_sibling;
}
}
void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNode& node,
CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot,
const zeus::CMatrix3f& parentXf, const zeus::CVector3f& parentOffset) const
{
zeus::CQuaternion quat = parentRot * node.x4_rotation;
float scale;
2016-09-06 05:52:51 +00:00
zeus::CVector3f bindOffset;
2016-09-04 02:27:35 +00:00
if (x0_layoutDesc.GetScaledLayoutDescription())
2016-09-06 05:52:51 +00:00
{
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription();
2017-01-08 03:36:24 +00:00
scale = desc.GlobalScale();
bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId);
2016-09-06 05:52:51 +00:00
}
2016-04-13 23:07:18 +00:00
else
2016-09-06 05:52:51 +00:00
{
2016-04-13 23:07:18 +00:00
scale = 1.f;
2016-09-06 05:52:51 +00:00
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
}
2016-04-13 23:07:18 +00:00
zeus::CMatrix3f mtxXf;
if (scale == 1.f)
mtxXf = quat;
else
2016-09-06 05:52:51 +00:00
mtxXf = parentXf * zeus::CMatrix3f(scale);
2016-04-13 23:07:18 +00:00
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
2016-09-06 05:52:51 +00:00
pose.Insert(boneId, mtxXf, xfOffset, bindOffset);
2016-04-13 23:07:18 +00:00
CSegId curBone = node.x0_child;
while (curBone != 0)
{
2016-09-04 02:27:35 +00:00
const CTreeNode& node = x38_treeMap[curBone];
2016-04-13 23:07:18 +00:00
RecursivelyBuild(curBone, node, pose, quat, quat, xfOffset);
curBone = node.x1_sibling;
}
}
void CHierarchyPoseBuilder::BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const
{
TLockedToken<CCharLayoutInfo> layoutInfoTok;
float scale;
2016-09-04 02:27:35 +00:00
if (x0_layoutDesc.GetScaledLayoutDescription())
2016-04-13 23:07:18 +00:00
{
2017-01-08 03:36:24 +00:00
layoutInfoTok = x0_layoutDesc.GetScaledLayoutDescription()->ScaledLayout();
scale = x0_layoutDesc.GetScaledLayoutDescription()->GlobalScale();
2016-04-13 23:07:18 +00:00
}
else
{
2016-09-04 02:27:35 +00:00
layoutInfoTok = x0_layoutDesc.GetCharLayoutInfo();
2016-04-13 23:07:18 +00:00
scale = 1.f;
}
const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj();
u32 idCount = 0;
CSegId buildIDs[100];
{
CSegId curId = boneId;
while (curId != 2)
{
buildIDs[idCount++] = curId;
2016-04-16 03:24:25 +00:00
curId = layoutInfo.GetRootNode()->GetBoneMap()[curId].x0_parentId;
2016-04-13 23:07:18 +00:00
}
}
zeus::CQuaternion accumRot;
zeus::CMatrix3f accumXF;
zeus::CVector3f accumPos;
for (CSegId* id=&buildIDs[idCount] ; id != buildIDs ; --id)
{
CSegId& thisId = id[-1];
2016-09-04 02:27:35 +00:00
const CTreeNode& node = x38_treeMap[thisId];
2016-04-13 23:07:18 +00:00
accumRot *= node.x4_rotation;
accumPos += accumXF * node.x14_offset;
if (scale == 1.f)
accumXF = accumRot;
else
accumXF = accumXF * zeus::CMatrix3f(node.x4_rotation) * zeus::CMatrix3f(scale);
}
xfOut.setRotation(accumXF);
2016-04-29 10:08:46 +00:00
xfOut.origin = accumPos;
2016-04-13 23:07:18 +00:00
}
void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose)
{
pose.Clear();
2016-09-04 02:27:35 +00:00
const CTreeNode& node = x38_treeMap[xcec_rootId];
2016-04-13 23:07:18 +00:00
zeus::CQuaternion quat;
zeus::CMatrix3f mtx;
zeus::CVector3f vec;
RecursivelyBuildNoScale(xcec_rootId, node, pose, quat, mtx, vec);
}
2016-08-21 00:04:50 +00:00
void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat)
{
2016-09-06 05:52:51 +00:00
CTreeNode& node = x38_treeMap[boneId];
node.x4_rotation = quat;
2016-08-21 00:04:50 +00:00
}
void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset)
{
2016-09-06 05:52:51 +00:00
CTreeNode& node = x38_treeMap[boneId];
node.x4_rotation = quat;
node.x14_offset = offset;
2016-08-21 00:04:50 +00:00
}
2016-04-13 23:07:18 +00:00
CHierarchyPoseBuilder::CHierarchyPoseBuilder(const CLayoutDescription& layout)
2016-09-04 02:27:35 +00:00
: x0_layoutDesc(layout), x38_treeMap(layout.GetCharLayoutInfo()->GetSegIdList().GetList().size())
2016-04-13 23:07:18 +00:00
{
TLockedToken<CCharLayoutInfo> layoutInfoTok;
if (layout.GetScaledLayoutDescription())
2017-01-08 03:36:24 +00:00
layoutInfoTok = layout.GetScaledLayoutDescription()->ScaledLayout();
2016-04-13 23:07:18 +00:00
else
layoutInfoTok = layout.GetCharLayoutInfo();
const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj();
const CSegIdList& segIDs = layoutInfo.GetSegIdList();
for (const CSegId& id : segIDs.GetList())
BuildIntoHierarchy(layoutInfo, id, 2);
}
}