Merge pull request #1656 from aws-lumberyard-dev/Helios_LYN-4880-IncorrectBoneNodes

[LYN-4880] Fix incorrect detection of bone nodes
main
amzn-mike 5 years ago committed by GitHub
commit 8f7a0a0dbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -36,60 +36,46 @@ namespace AZ
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<AssImpBoneImporter, SceneCore::LoadingComponent>()->Version(1);
serializeContext->Class<AssImpBoneImporter, SceneCore::LoadingComponent>()->Version(2);
}
}
void EnumBonesInNode(
const aiScene* scene, const aiNode* node, AZStd::unordered_map<AZStd::string, const aiNode*>& mainBoneList,
AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
void MakeBoneMap(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
{
/* From AssImp Documentation
a) Create a map or a similar container to store which nodes are necessary for the skeleton. Pre-initialise it for all nodes with a "no".
b) For each bone in the mesh:
b1) Find the corresponding node in the scene's hierarchy by comparing their names.
b2) Mark this node as "yes" in the necessityMap.
b3) Mark all of its parents the same way until you 1) find the mesh's node or 2) the parent of the mesh's node.
c) Recursively iterate over the node hierarchy
c1) If the node is marked as necessary, copy it into the skeleton and check its children
c2) If the node is marked as not necessary, skip it and do not iterate over its children.
*/
for (unsigned meshIndex = 0; meshIndex < node->mNumMeshes; ++meshIndex)
{
const aiMesh* mesh = scene->mMeshes[node->mMeshes[meshIndex]];
for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
{
const aiBone* bone = mesh->mBones[boneIndex];
AZStd::queue<const aiNode*> queue;
AZStd::unordered_set<AZStd::string> nodesWithNoMesh;
const aiNode* boneNode = scene->mRootNode->FindNode(bone->mName);
const aiNode* boneParent = boneNode->mParent;
queue.push(scene->mRootNode);
mainBoneList[bone->mName.C_Str()] = boneNode;
boneLookup[bone->mName.C_Str()] = bone;
while (!queue.empty())
{
const aiNode* currentNode = queue.front();
queue.pop();
while (boneParent && boneParent != node && boneParent != node->mParent && boneParent != scene->mRootNode)
{
mainBoneList[boneParent->mName.C_Str()] = boneParent;
if (currentNode->mNumMeshes == 0)
{
nodesWithNoMesh.emplace(currentNode->mName.C_Str());
}
boneParent = boneParent->mParent;
}
for (int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex)
{
queue.push(currentNode->mChildren[childIndex]);
}
}
}
void EnumChildren(
const aiScene* scene, const aiNode* node, AZStd::unordered_map<AZStd::string, const aiNode*>& mainBoneList,
AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
{
EnumBonesInNode(scene, node, mainBoneList, boneLookup);
for (unsigned childIndex = 0; childIndex < node->mNumChildren; ++childIndex)
for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
const aiNode* child = node->mChildren[childIndex];
const aiMesh* mesh = scene->mMeshes[meshIndex];
for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
{
const aiBone* bone = mesh->mBones[boneIndex];
EnumChildren(scene, child, mainBoneList, boneLookup);
if (nodesWithNoMesh.contains(bone->mName.C_Str()))
{
boneLookup.emplace(bone->mName.C_Str(), bone);
}
}
}
}
@ -122,14 +108,10 @@ namespace AZ
bool isBone = false;
{
AZStd::unordered_map<AZStd::string, const aiNode*> mainBoneList;
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
EnumChildren(scene, scene->mRootNode, mainBoneList, boneLookup);
MakeBoneMap(scene, boneLookup);
if (mainBoneList.find(currentNode->mName.C_Str()) != mainBoneList.end())
{
isBone = true;
}
isBone = boneLookup.contains(currentNode->mName.C_Str());
// If we have an animation, the bones will be listed in there
if (!isBone)

@ -42,9 +42,29 @@ namespace AZ
}
}
void GetAllBones(
const aiScene* scene, AZStd::unordered_multimap<AZStd::string, const aiBone*>& boneLookup)
void GetAllBones(const aiScene* scene, AZStd::unordered_multimap<AZStd::string, const aiBone*>& boneLookup)
{
AZStd::queue<const aiNode*> queue;
AZStd::unordered_set<AZStd::string> nodesWithNoMesh;
queue.push(scene->mRootNode);
while (!queue.empty())
{
const aiNode* currentNode = queue.front();
queue.pop();
if (currentNode->mNumMeshes == 0)
{
nodesWithNoMesh.emplace(currentNode->mName.C_Str());
}
for (int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex)
{
queue.push(currentNode->mChildren[childIndex]);
}
}
for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
const aiMesh* mesh = scene->mMeshes[meshIndex];
@ -53,7 +73,10 @@ namespace AZ
{
const aiBone* bone = mesh->mBones[boneIndex];
boneLookup.emplace(bone->mName.C_Str(), bone);
if (nodesWithNoMesh.contains(bone->mName.C_Str()))
{
boneLookup.emplace(bone->mName.C_Str(), bone);
}
}
}
}

Loading…
Cancel
Save