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,63 +36,49 @@ namespace AZ
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context); SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext) if (serializeContext)
{ {
serializeContext->Class<AssImpBoneImporter, SceneCore::LoadingComponent>()->Version(1); serializeContext->Class<AssImpBoneImporter, SceneCore::LoadingComponent>()->Version(2);
} }
} }
void EnumBonesInNode( void MakeBoneMap(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
const aiScene* scene, const aiNode* node, AZStd::unordered_map<AZStd::string, const aiNode*>& mainBoneList,
AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
{ {
/* From AssImp Documentation AZStd::queue<const aiNode*> queue;
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". AZStd::unordered_set<AZStd::string> nodesWithNoMesh;
b) For each bone in the mesh:
b1) Find the corresponding node in the scene's hierarchy by comparing their names. queue.push(scene->mRootNode);
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. while (!queue.empty())
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]]; const aiNode* currentNode = queue.front();
queue.pop();
for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex) if (currentNode->mNumMeshes == 0)
{ {
const aiBone* bone = mesh->mBones[boneIndex]; nodesWithNoMesh.emplace(currentNode->mName.C_Str());
}
const aiNode* boneNode = scene->mRootNode->FindNode(bone->mName); for (int childIndex = 0; childIndex < currentNode->mNumChildren; ++childIndex)
const aiNode* boneParent = boneNode->mParent; {
queue.push(currentNode->mChildren[childIndex]);
}
}
mainBoneList[bone->mName.C_Str()] = boneNode; for (unsigned int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
boneLookup[bone->mName.C_Str()] = bone; {
const aiMesh* mesh = scene->mMeshes[meshIndex];
while (boneParent && boneParent != node && boneParent != node->mParent && boneParent != scene->mRootNode) for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
{ {
mainBoneList[boneParent->mName.C_Str()] = boneParent; const aiBone* bone = mesh->mBones[boneIndex];
boneParent = boneParent->mParent; if (nodesWithNoMesh.contains(bone->mName.C_Str()))
{
boneLookup.emplace(bone->mName.C_Str(), bone);
} }
} }
} }
} }
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)
{
const aiNode* child = node->mChildren[childIndex];
EnumChildren(scene, child, mainBoneList, boneLookup);
}
}
aiMatrix4x4 CalculateWorldTransform(const aiNode* currentNode) aiMatrix4x4 CalculateWorldTransform(const aiNode* currentNode)
{ {
aiMatrix4x4 transform = {}; aiMatrix4x4 transform = {};
@ -122,14 +108,10 @@ namespace AZ
bool isBone = false; bool isBone = false;
{ {
AZStd::unordered_map<AZStd::string, const aiNode*> mainBoneList;
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup; 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 = boneLookup.contains(currentNode->mName.C_Str());
{
isBone = true;
}
// If we have an animation, the bones will be listed in there // If we have an animation, the bones will be listed in there
if (!isBone) if (!isBone)

@ -42,9 +42,29 @@ namespace AZ
} }
} }
void GetAllBones( void GetAllBones(const aiScene* scene, AZStd::unordered_multimap<AZStd::string, const aiBone*>& boneLookup)
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) for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{ {
const aiMesh* mesh = scene->mMeshes[meshIndex]; const aiMesh* mesh = scene->mMeshes[meshIndex];
@ -53,7 +73,10 @@ namespace AZ
{ {
const aiBone* bone = mesh->mBones[boneIndex]; 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