CHierarchyPoseBuilder imps

This commit is contained in:
Jack Andersen 2016-04-13 13:07:18 -10:00
parent 1429e30df0
commit a2f400274f
10 changed files with 324 additions and 41 deletions

View File

@ -122,7 +122,7 @@ struct CINF : BigDNA
using Armature = hecl::BlenderConnection::DataStream::Actor::Armature; using Armature = hecl::BlenderConnection::DataStream::Actor::Armature;
int RecursiveAddArmatureBone(const Armature& armature, const Armature::Bone* bone, int parent, int& curId, int RecursiveAddArmatureBone(const Armature& armature, const Armature::Bone* bone, int parent, int& curId,
std::unordered_map<std::string, atInt32>& idMap) std::unordered_map<std::string, atInt32>& idMap, std::map<std::string, int>& nameMap)
{ {
int selId; int selId;
auto search = idMap.find(bone->name); auto search = idMap.find(bone->name);
@ -135,11 +135,8 @@ struct CINF : BigDNA
selId = search->second; selId = search->second;
bones.emplace_back(); bones.emplace_back();
names.emplace_back();
Bone& boneOut = bones.back(); Bone& boneOut = bones.back();
Name& nameOut = names.back(); nameMap[bone->name] = selId;
nameOut.name = bone->name;
nameOut.boneId = selId;
boneOut.id = selId; boneOut.id = selId;
boneOut.parentId = parent; boneOut.parentId = parent;
boneOut.origin = bone->origin; boneOut.origin = bone->origin;
@ -149,7 +146,7 @@ struct CINF : BigDNA
const Armature::Bone* child; const Armature::Bone* child;
boneOut.linked.push_back(parent); boneOut.linked.push_back(parent);
for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i) for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i)
boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, selId, idMap)); boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, selId, idMap, nameMap));
return boneOut.id; return boneOut.id;
} }
@ -158,15 +155,48 @@ struct CINF : BigDNA
{ {
idMap.reserve(armature.bones.size()); idMap.reserve(armature.bones.size());
bones.reserve(armature.bones.size()); bones.reserve(armature.bones.size());
names.reserve(armature.bones.size());
std::map<std::string, int> nameMap;
const Armature::Bone* bone = armature.getRoot(); const Armature::Bone* bone = armature.getRoot();
int curId = 3;
if (bone) if (bone)
RecursiveAddArmatureBone(armature, bone, 2, curId, idMap); {
if (bone->children.size())
{
int curId = 4;
RecursiveAddArmatureBone(armature, armature.getChild(bone, 0), 3, curId, idMap, nameMap);
}
bones.emplace_back();
Bone& boneOut = bones.back();
nameMap[bone->name] = 3;
boneOut.id = 3;
boneOut.parentId = 2;
boneOut.origin = bone->origin;
if (bone->children.size())
{
boneOut.linkedCount = 2;
boneOut.linked = {2, 4};
}
else
{
boneOut.linkedCount = 1;
boneOut.linked = {2};
}
}
boneCount = bones.size(); boneCount = bones.size();
nameCount = names.size();
names.reserve(nameMap.size());
nameCount = nameMap.size();
for (const auto& name : nameMap)
{
names.emplace_back();
Name& nameOut = names.back();
nameOut.name = name.first;
nameOut.boneId = name.second;
}
boneIdCount = boneCount; boneIdCount = boneCount;
boneIds.reserve(boneIdCount); boneIds.reserve(boneIdCount);

View File

@ -7,7 +7,6 @@
#include "CParticleDatabase.hpp" #include "CParticleDatabase.hpp"
#include "CPoseAsTransforms.hpp" #include "CPoseAsTransforms.hpp"
#include "CHierarchyPoseBuilder.hpp" #include "CHierarchyPoseBuilder.hpp"
#include "optional.hpp"
namespace urde namespace urde
{ {
@ -19,23 +18,6 @@ class CTransitionManager;
class CCharacterFactory; class CCharacterFactory;
class IMetaAnim; class IMetaAnim;
class CLayoutDescription
{
public:
class CScaledLayoutDescription
{
TLockedToken<CCharLayoutInfo> x0_layoutToken;
float xc_scale;
std::experimental::optional<zeus::CVector3f> x10_scaleVec;
};
private:
TLockedToken<CCharLayoutInfo> x0_layoutToken;
std::experimental::optional<CScaledLayoutDescription> xc_scaled;
public:
CLayoutDescription(const TLockedToken<CCharLayoutInfo>& token)
: x0_layoutToken(token) {}
};
class CAnimData class CAnimData
{ {
TLockedToken<CCharacterFactory> x0_charFactory; TLockedToken<CCharacterFactory> x0_charFactory;

View File

@ -4,6 +4,19 @@
namespace urde 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)
return bone.x4_origin;
else
{
const CCharLayoutNode::Bone& pBone = x0_node->GetBone(bone.x0_parentId);
return bone.x4_origin - pBone.x4_origin;
}
}
void CCharLayoutNode::Bone::read(CInputStream& in) void CCharLayoutNode::Bone::read(CInputStream& in)
{ {
x0_parentId = CSegId(in); x0_parentId = CSegId(in);
@ -17,17 +30,15 @@ void CCharLayoutNode::Bone::read(CInputStream& in)
CCharLayoutNode::CCharLayoutNode(CInputStream& in) CCharLayoutNode::CCharLayoutNode(CInputStream& in)
{ {
x0_boneCount = in.readUint32Big(); u32 count = in.readUint32Big();
for (u32 i=0 ; i<x0_boneCount ; ++i) for (u32 i=0 ; i<count ; ++i)
{ {
u32 thisId = in.readUint32Big(); u32 thisId = in.readUint32Big();
if (thisId >= 100) Bone& bone = x6c_bones[thisId];
{ bone.read(in);
Bone dummy; x8_prevBones[thisId] = x1_curPrevBone;
dummy.read(in); x1_curPrevBone = thisId;
} ++x0_boneCount;
else
x108_bones[i].read(in);
} }
} }

View File

@ -20,11 +20,15 @@ public:
void read(CInputStream& in); void read(CInputStream& in);
}; };
private: private:
u8 x0_boneCount; CSegId x0_boneCount = 0;
CSegId x8_ids[100]; CSegId x1_curPrevBone = 0;
Bone x108_bones[100]; CSegId x8_prevBones[100];
Bone x6c_bones[100];
public: public:
CCharLayoutNode(CInputStream& in); 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];}
}; };
class CCharLayoutInfo class CCharLayoutInfo
@ -34,7 +38,9 @@ class CCharLayoutInfo
std::map<std::string, CSegId> x18_segIdMap; std::map<std::string, CSegId> x18_segIdMap;
public: public:
CCharLayoutInfo(CInputStream& in); CCharLayoutInfo(CInputStream& in);
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;
}; };
CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream&, const CVParamTransfer&); CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream&, const CVParamTransfer&);

View File

@ -0,0 +1,157 @@
#include "CHierarchyPoseBuilder.hpp"
#include "CAnimData.hpp"
#include "CCharLayoutInfo.hpp"
namespace urde
{
void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout,
const CSegId& boneId, const CSegId& nullId)
{
const CSegId& idA = x8_prevBones[boneId];
if (idA == 0xff)
{
const CCharLayoutNode::Bone& bone = layout.GetRootNode()->GetBone(boneId);
if (bone.x0_parentId == nullId)
{
xcec_rootId = boneId;
xcf0_hasRoot = true;
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
x6c_nodes[boneId] = CTreeNode(origin);
}
else
{
BuildIntoHierarchy(layout, bone.x0_parentId, nullId);
zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId);
CTreeNode& pNode = x6c_nodes[bone.x0_parentId];
CTreeNode node(origin);
node.x1_sibling = pNode.x0_child;
pNode.x0_child = boneId;
x6c_nodes[boneId] = node;
}
x8_prevBones[boneId] = x1_curPrevBone;
x1_curPrevBone = boneId;
++x0_boneCount;
}
}
void CHierarchyPoseBuilder::RecursivelyBuildNoScale(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;
zeus::CMatrix3f xf = quat;
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
pose.Insert(boneId, quat, xfOffset);
CSegId curBone = node.x0_child;
while (curBone != 0)
{
const CTreeNode& node = x6c_nodes[curBone];
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;
if (xcf4_layoutDesc.GetScaledLayoutDescription())
scale = xcf4_layoutDesc.GetScaledLayoutDescription()->GetScale();
else
scale = 1.f;
zeus::CMatrix3f mtxXf;
if (scale == 1.f)
mtxXf = quat;
else
mtxXf = parentXf * quat * zeus::CMatrix3f(scale);
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
pose.Insert(boneId, mtxXf, xfOffset);
CSegId curBone = node.x0_child;
while (curBone != 0)
{
const CTreeNode& node = x6c_nodes[curBone];
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;
if (xcf4_layoutDesc.GetScaledLayoutDescription())
{
layoutInfoTok = xcf4_layoutDesc.GetScaledLayoutDescription()->GetCharLayoutInfo();
scale = xcf4_layoutDesc.GetScaledLayoutDescription()->GetScale();
}
else
{
layoutInfoTok = xcf4_layoutDesc.GetCharLayoutInfo();
scale = 1.f;
}
const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj();
u32 idCount = 0;
CSegId buildIDs[100];
{
CSegId curId = boneId;
while (curId != 2)
{
buildIDs[idCount++] = curId;
curId = layoutInfo.GetRootNode()->GetBone(curId).x0_parentId;
}
}
zeus::CQuaternion accumRot;
zeus::CMatrix3f accumXF;
zeus::CVector3f accumPos;
for (CSegId* id=&buildIDs[idCount] ; id != buildIDs ; --id)
{
CSegId& thisId = id[-1];
const CTreeNode& node = x6c_nodes[thisId];
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);
xfOut.m_origin = accumPos;
}
void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose)
{
pose.Clear();
const CTreeNode& node = x6c_nodes[xcec_rootId];
zeus::CQuaternion quat;
zeus::CMatrix3f mtx;
zeus::CVector3f vec;
RecursivelyBuildNoScale(xcec_rootId, node, pose, quat, mtx, vec);
}
CHierarchyPoseBuilder::CHierarchyPoseBuilder(const CLayoutDescription& layout)
: xcf4_layoutDesc(layout)
{
TLockedToken<CCharLayoutInfo> layoutInfoTok;
if (layout.GetScaledLayoutDescription())
layoutInfoTok = layout.GetScaledLayoutDescription()->GetCharLayoutInfo();
else
layoutInfoTok = layout.GetCharLayoutInfo();
const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj();
const CSegIdList& segIDs = layoutInfo.GetSegIdList();
for (const CSegId& id : segIDs.GetList())
BuildIntoHierarchy(layoutInfo, id, 2);
}
}

View File

@ -1,14 +1,49 @@
#ifndef __URDE_CHIERARCHYPOSEBUILDER_HPP__ #ifndef __URDE_CHIERARCHYPOSEBUILDER_HPP__
#define __URDE_CHIERARCHYPOSEBUILDER_HPP__ #define __URDE_CHIERARCHYPOSEBUILDER_HPP__
#include "CSegId.hpp"
#include "zeus/CQuaternion.hpp"
#include "CLayoutDescription.hpp"
namespace urde namespace urde
{ {
class CLayoutDescription; class CLayoutDescription;
class CCharLayoutInfo;
class CPoseAsTransforms;
class CHierarchyPoseBuilder class CHierarchyPoseBuilder
{ {
CSegId x0_boneCount = 0;
CSegId x1_curPrevBone = 0;
CSegId x8_prevBones[100];
struct CTreeNode
{
CSegId x0_child = 0;
CSegId x1_sibling = 0;
zeus::CQuaternion x4_rotation;
zeus::CVector3f x14_offset;
CTreeNode() = default;
CTreeNode(const zeus::CVector3f& offset) : x14_offset(offset) {}
};
CTreeNode x6c_nodes[100];
CSegId xcec_rootId;
bool xcf0_hasRoot = false;
CLayoutDescription xcf4_layoutDesc;
void BuildIntoHierarchy(const CCharLayoutInfo& layout,
const CSegId& boneId, const CSegId& nullId);
void RecursivelyBuildNoScale(const CSegId& boneId, const CTreeNode& node,
CPoseAsTransforms& pose, const zeus::CQuaternion& rot,
const zeus::CMatrix3f& scale, const zeus::CVector3f& offset) const;
void RecursivelyBuild(const CSegId& boneId, const CTreeNode& node,
CPoseAsTransforms& pose, const zeus::CQuaternion& rot,
const zeus::CMatrix3f& scale, const zeus::CVector3f& offset) const;
public: public:
CHierarchyPoseBuilder(const CLayoutDescription& layout); CHierarchyPoseBuilder(const CLayoutDescription& layout);
void BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const;
void BuildNoScale(CPoseAsTransforms& pose);
}; };
} }

View File

@ -0,0 +1,40 @@
#ifndef __URDE_CLAYOUTDESCRIPTION_HPP__
#define __URDE_CLAYOUTDESCRIPTION_HPP__
#include "optional.hpp"
#include "CToken.hpp"
#include "zeus/CVector3f.hpp"
namespace urde
{
class CCharLayoutInfo;
class CLayoutDescription
{
public:
class CScaledLayoutDescription
{
TLockedToken<CCharLayoutInfo> x0_layoutToken;
float xc_scale;
std::experimental::optional<zeus::CVector3f> x10_scaleVec;
public:
const TLockedToken<CCharLayoutInfo>& GetCharLayoutInfo() const {return x0_layoutToken;}
float GetScale() const {return xc_scale;}
const std::experimental::optional<zeus::CVector3f>& GetScaleVec() const {return x10_scaleVec;}
};
private:
TLockedToken<CCharLayoutInfo> x0_layoutToken;
std::experimental::optional<CScaledLayoutDescription> xc_scaled;
public:
CLayoutDescription(const TLockedToken<CCharLayoutInfo>& token)
: x0_layoutToken(token) {}
const std::experimental::optional<CScaledLayoutDescription>&
GetScaledLayoutDescription() const {return xc_scaled;}
const TLockedToken<CCharLayoutInfo>& GetCharLayoutInfo() const {return x0_layoutToken;}
};
}
#endif // __URDE_CLAYOUTDESCRIPTION_HPP__

View File

@ -14,8 +14,10 @@ add_library(RuntimeCommonCharacter
CPoseAsTransforms.hpp CPoseAsTransforms.cpp CPoseAsTransforms.hpp CPoseAsTransforms.cpp
CSkinBank.hpp CSkinBank.cpp CSkinBank.hpp CSkinBank.cpp
CCharLayoutInfo.hpp CCharLayoutInfo.cpp CCharLayoutInfo.hpp CCharLayoutInfo.cpp
CLayoutDescription.hpp
CSegIdList.hpp CSegIdList.cpp CSegIdList.hpp CSegIdList.cpp
CSegId.hpp CSegId.cpp CSegId.hpp CSegId.cpp
TSegIdMap.hpp
CSkinRules.hpp CSkinRules.cpp CSkinRules.hpp CSkinRules.cpp
CAnimCharacterSet.hpp CAnimCharacterSet.cpp CAnimCharacterSet.hpp CAnimCharacterSet.cpp
CAnimationSet.hpp CAnimationSet.cpp CAnimationSet.hpp CAnimationSet.cpp

View File

@ -0,0 +1,20 @@
#ifndef __URDE_TSEGIDMAP_HPP__
#define __URDE_TSEGIDMAP_HPP__
#include <map>
#include "CSegId.hpp"
namespace urde
{
template <class T>
class TSegIdMap
{
std::map<CSegId, T> x0_map;
public:
const T& AccessElement(const CSegId& id) const {return x0_map[id];}
};
}
#endif // __URDE_TSEGIDMAP_HPP__

@ -1 +1 @@
Subproject commit 87e8161a2bb7aa6e6447b7f149cdf3ed014a0dae Subproject commit 1cc8a922f7e015c76f8dd071c713b09b26912a33