diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpBoneImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpBoneImporter.cpp index 1828919c46..6ae228a8a8 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpBoneImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpBoneImporter.cpp @@ -40,59 +40,45 @@ namespace AZ } } - void EnumBonesInNode( - const aiScene* scene, const aiNode* node, AZStd::unordered_map& mainBoneList, - AZStd::unordered_map& boneLookup) + void MakeBoneMap(const aiScene* scene, AZStd::unordered_map& 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. - */ + AZStd::queue queue; + AZStd::unordered_set nodesWithNoMesh; - for (unsigned meshIndex = 0; meshIndex < node->mNumMeshes; ++meshIndex) + queue.push(scene->mRootNode); + + while (!queue.empty()) { - const aiMesh* mesh = scene->mMeshes[node->mMeshes[meshIndex]]; + 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]; for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex) { const aiBone* bone = mesh->mBones[boneIndex]; - const aiNode* boneNode = scene->mRootNode->FindNode(bone->mName); - const aiNode* boneParent = boneNode->mParent; - - mainBoneList[bone->mName.C_Str()] = boneNode; - boneLookup[bone->mName.C_Str()] = bone; - - while (boneParent && boneParent != node && boneParent != node->mParent && boneParent != scene->mRootNode) + if (nodesWithNoMesh.contains(bone->mName.C_Str())) { - mainBoneList[boneParent->mName.C_Str()] = boneParent; - - boneParent = boneParent->mParent; + boneLookup.emplace(bone->mName.C_Str(), bone); } } } } - void EnumChildren( - const aiScene* scene, const aiNode* node, AZStd::unordered_map& mainBoneList, - AZStd::unordered_map& 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 transform = {}; @@ -122,14 +108,10 @@ namespace AZ bool isBone = false; { - AZStd::unordered_map mainBoneList; AZStd::unordered_map 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) diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp index 5f9ffbd9b3..2f515c6174 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpTransformImporter.cpp @@ -42,9 +42,29 @@ namespace AZ } } - void GetAllBones( - const aiScene* scene, AZStd::unordered_multimap& boneLookup) + void GetAllBones(const aiScene* scene, AZStd::unordered_multimap& boneLookup) { + AZStd::queue queue; + AZStd::unordered_set 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); + } } } }