AssImpBoneImporter.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Serialization/SerializeContext.h>
  9. #include <AzCore/std/smart_ptr/make_shared.h>
  10. #include <AzCore/StringFunc/StringFunc.h>
  11. #include <AzToolsFramework/Debug/TraceContext.h>
  12. #include <SceneAPI/SceneBuilder/SceneSystem.h>
  13. #include <SceneAPI/SceneBuilder/Importers/AssImpBoneImporter.h>
  14. #include <SceneAPI/SceneBuilder/Importers/AssImpImporterUtilities.h>
  15. #include <SceneAPI/SceneBuilder/Importers/ImporterUtilities.h>
  16. #include <SceneAPI/SceneCore/Containers/Scene.h>
  17. #include <SceneAPI/SceneData/GraphData/BoneData.h>
  18. #include <SceneAPI/SceneData/GraphData/RootBoneData.h>
  19. #include <SceneAPI/SDKWrapper/AssImpNodeWrapper.h>
  20. #include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
  21. #include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
  22. namespace AZ
  23. {
  24. namespace SceneAPI
  25. {
  26. namespace SceneBuilder
  27. {
  28. AssImpBoneImporter::AssImpBoneImporter()
  29. {
  30. BindToCall(&AssImpBoneImporter::ImportBone);
  31. }
  32. void AssImpBoneImporter::Reflect(ReflectContext* context)
  33. {
  34. SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
  35. if (serializeContext)
  36. {
  37. serializeContext->Class<AssImpBoneImporter, SceneCore::LoadingComponent>()->Version(2);
  38. }
  39. }
  40. aiMatrix4x4 CalculateWorldTransform(const aiNode* currentNode)
  41. {
  42. aiMatrix4x4 transform = {};
  43. const aiNode* iteratingNode = currentNode;
  44. while (iteratingNode)
  45. {
  46. transform = iteratingNode->mTransformation * transform;
  47. iteratingNode = iteratingNode->mParent;
  48. }
  49. return transform;
  50. }
  51. Events::ProcessingResult AssImpBoneImporter::ImportBone(AssImpNodeEncounteredContext& context)
  52. {
  53. AZ_TraceContext("Importer", "Bone");
  54. const aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
  55. const aiScene* scene = context.m_sourceScene.GetAssImpScene();
  56. if (IsPivotNode(currentNode->mName))
  57. {
  58. return Events::ProcessingResult::Ignored;
  59. }
  60. AZStd::unordered_multimap<AZStd::string, const aiBone*> boneByNameMap;
  61. FindAllBones(scene, boneByNameMap);
  62. bool isBone = FindFirstBoneByNodeName(currentNode, boneByNameMap);
  63. // Export the scene root node as a bone.
  64. if (!isBone)
  65. {
  66. isBone = (currentNode == scene->mRootNode);
  67. }
  68. if (!isBone)
  69. {
  70. // In case the bone is not listed in any of the meshes in the scene, populate a set of animated bone names from
  71. // the animations. This set of names will help varify if the current node is a bone.
  72. AZStd::unordered_set<AZStd::string> animatedNodesMap;
  73. for(unsigned animIndex = 0; animIndex < scene->mNumAnimations; ++animIndex)
  74. {
  75. aiAnimation* animation = scene->mAnimations[animIndex];
  76. for (unsigned channelIndex = 0; channelIndex < animation->mNumChannels; ++channelIndex)
  77. {
  78. aiNodeAnim* nodeAnim = animation->mChannels[channelIndex];
  79. animatedNodesMap.emplace(nodeAnim->mNodeName.C_Str());
  80. }
  81. }
  82. // In case any of the children, or children of children is a bone, make sure to not skip this node.
  83. // Don't do this for the scene root itself, else wise all mesh nodes will be exported as bones and pollute the skeleton.
  84. if (currentNode != scene->mRootNode &&
  85. RecursiveHasChildBone(currentNode, boneByNameMap, animatedNodesMap))
  86. {
  87. isBone = true;
  88. }
  89. }
  90. if (!isBone)
  91. {
  92. return Events::ProcessingResult::Ignored;
  93. }
  94. // If the current scene node (our eventual parent) contains bone data, we are not a root bone
  95. AZStd::shared_ptr<SceneData::GraphData::BoneData> createdBoneData;
  96. if (NodeHasAncestorOfType(
  97. context.m_scene.GetGraph(), context.m_currentGraphPosition, DataTypes::IBoneData::TYPEINFO_Uuid()))
  98. {
  99. createdBoneData = AZStd::make_shared<SceneData::GraphData::BoneData>();
  100. }
  101. else
  102. {
  103. createdBoneData = AZStd::make_shared<SceneData::GraphData::RootBoneData>();
  104. }
  105. aiMatrix4x4 transform = CalculateWorldTransform(currentNode);
  106. SceneAPI::DataTypes::MatrixType globalTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform);
  107. context.m_sourceSceneSystem.SwapTransformForUpAxis(globalTransform);
  108. context.m_sourceSceneSystem.ConvertBoneUnit(globalTransform);
  109. createdBoneData->SetWorldTransform(globalTransform);
  110. context.m_createdData.push_back(AZStd::move(createdBoneData));
  111. return Events::ProcessingResult::Success;
  112. }
  113. } // namespace SceneBuilder
  114. } // namespace SceneAPI
  115. } // namespace AZ