diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h index 266653ca51eb..bce9903c2f6e 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpNodeWrapper.h @@ -11,6 +11,8 @@ struct aiScene; +struct aiNode; + namespace AZ { namespace AssImpSDKWrapper diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 4cde476d7f8c..6a8d325fb63a 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -8,9 +8,10 @@ #include #include #include -#include -#include #include +#include +#include +#include #include #if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL @@ -38,11 +39,12 @@ namespace AZ } #if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL - void signal_handler([[maybe_unused]] int signal) + void signal_handler([[maybe_unused]] int signal) { AZ_TracePrintf( SceneAPI::Utilities::ErrorWindow, - "Failed to import scene with Asset Importer library. An %s has occurred in the library, this scene file cannot be parsed by the library.", + "Failed to import scene with Asset Importer library. An %s has occurred in the library, this scene file cannot be parsed " + "by the library.", signal == SIGABRT ? "assert" : "unknown error"); } #endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL @@ -58,7 +60,7 @@ namespace AZ #ifdef _WRITE_ABORT_MSG _set_abort_behavior(0, _WRITE_ABORT_MSG); #endif // #ifdef _WRITE_ABORT_MSG - // Instead, capture any calls to abort with a signal handler, and report them. + // Instead, capture any calls to abort with a signal handler, and report them. auto previous_handler = std::signal(SIGABRT, signal_handler); #endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL @@ -71,12 +73,11 @@ namespace AZ // aiProcess_JoinIdenticalVertices is not enabled because O3DE has a mesh optimizer that also does this, // this flag is disabled to keep AssImp output similar to FBX SDK to reduce downstream bugs for the initial AssImp release. // There's currently a minimum of properties and flags set to maximize compatibility with the existing node graph. - unsigned int importFlags = - aiProcess_Triangulate // Triangulates all faces of all meshes - | static_cast(aiProcess_GenBoundingBoxes) // Generate bounding boxes - | aiProcess_GenNormals // Generate normals for meshes - | (importSettings.m_optimizeScene ? aiProcess_OptimizeGraph : 0) // Merge excess scene nodes together - | (importSettings.m_optimizeMeshes ? aiProcess_OptimizeMeshes : 0) // Combines meshes in the scene together + unsigned int importFlags = aiProcess_Triangulate // Triangulates all faces of all meshes + | static_cast(aiProcess_GenBoundingBoxes) // Generate bounding boxes + | aiProcess_GenNormals // Generate normals for meshes + | (importSettings.m_optimizeScene ? aiProcess_OptimizeGraph : 0) // Merge excess scene nodes together + | (importSettings.m_optimizeMeshes ? aiProcess_OptimizeMeshes : 0) // Combines meshes in the scene together ; // aiProcess_LimitBoneWeights is not enabled because it will remove bones which are not associated with a mesh. @@ -100,7 +101,10 @@ namespace AZ if (!m_assImpScene) { - AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Failed to import Asset Importer Scene. Error returned: %s", m_importer->GetErrorString()); + AZ_TracePrintf( + SceneAPI::Utilities::ErrorWindow, + "Failed to import Asset Importer Scene. Error returned: %s", + m_importer->GetErrorString()); return false; } @@ -153,7 +157,7 @@ namespace AZ void AssImpSceneWrapper::Clear() { - if(m_importer) + if (m_importer) { m_importer->FreeScene(); m_importer = AZStd::make_unique(); @@ -184,6 +188,37 @@ namespace AZ result.first = static_cast(frontVectorRead); return result; } - }//namespace AssImpSDKWrapper + + float AssImpSceneWrapper::GetUnitSizeInMeters() const + { + float unitSizeInMeters; + float originalUnitSizeInMeters; + /* Check if metadata has information about "UnitScaleFactor" or "OriginalUnitScaleFactor". + * This particular metadata is FBX format only. */ + if (m_assImpScene->mMetaData->HasKey("UnitScaleFactor") || m_assImpScene->mMetaData->HasKey("OriginalUnitScaleFactor")) + { + // If either metadata piece is not available, the default of 1 will be used. + m_assImpScene->mMetaData->Get("UnitScaleFactor", unitSizeInMeters); + m_assImpScene->mMetaData->Get("OriginalUnitScaleFactor", originalUnitSizeInMeters); + + /* Conversion factor for converting from centimeters to meters. + * This applies to an FBX format in which the default unit is a centimeter. */ + unitSizeInMeters = unitSizeInMeters * .01f; + } + else + { + // Some file formats (like DAE) embed the scale in the root transformation, so extract that scale from here. + auto rootTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(m_assImpScene->mRootNode->mTransformation); + unitSizeInMeters = rootTransform.ExtractScale().GetMaxElement(); + } + return unitSizeInMeters; + } + + AZ::Aabb AssImpSceneWrapper::GetAABB() const + { + return AZ::Aabb::CreateFromMinMaxValues( + m_aabb.mMin.x, m_aabb.mMin.y, m_aabb.mMin.z, m_aabb.mMax.x, m_aabb.mMax.y, m_aabb.mMax.z); + } + } // namespace AssImpSDKWrapper } // namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h index 91591510791d..ae20877f5f10 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.h @@ -34,20 +34,13 @@ namespace AZ void Clear() override; void CalculateAABBandVertices(const aiScene* scene, aiAABB& aabb, uint32_t& vertices); - enum class AxisVector - { - X = 0, - Y = 1, - Z = 2, - Unknown - }; - - AZStd::pair GetUpVectorAndSign() const; - AZStd::pair GetFrontVectorAndSign() const; + AZStd::pair GetUpVectorAndSign() const override; + AZStd::pair GetFrontVectorAndSign() const override; + float GetUnitSizeInMeters() const override; AZStd::string GetSceneFileName() const { return m_sceneFileName; } - aiAABB GetAABB() const { return m_aabb; } - uint32_t GetVertices() const { return m_vertices; } + AZ::Aabb GetAABB() const override; + uint32_t GetVerticesCount() const override { return m_vertices; } protected: const aiScene* m_assImpScene = nullptr; AZStd::unique_ptr m_importer; diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.cpp index 40163632b499..fcd108b30fa8 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.cpp @@ -34,20 +34,6 @@ namespace AZ return transform; } - SceneAPI::DataTypes::MatrixType AssImpTypeConverter::ToTransform(const AZ::Matrix4x4& matrix) - { - SceneAPI::DataTypes::MatrixType transform; - for (int row = 0; row < 3; ++row) - { - for (int column = 0; column < 4; ++column) - { - transform.SetElement(row, column, matrix.GetElement(row, column)); - } - } - - return transform; - } - SceneAPI::DataTypes::Color AssImpTypeConverter::ToColor(const aiColor4D& color) { return AZ::SceneAPI::DataTypes::Color(color.r, color.g, color.b, color.a); diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.h b/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.h index 0e7d6f763dea..c7055073c7d9 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.h +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpTypeConverter.h @@ -27,7 +27,6 @@ namespace AZ { public: static SceneAPI::DataTypes::MatrixType ToTransform(const aiMatrix4x4& matrix); - static SceneAPI::DataTypes::MatrixType ToTransform(const AZ::Matrix4x4& matrix); static SceneAPI::DataTypes::Color ToColor(const aiColor4D& color); static AZ::Vector3 ToVector3(const aiVector3D& vector3); }; diff --git a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h index 53778ea783b9..088b4c5ce1d5 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/MaterialWrapper.h @@ -11,8 +11,6 @@ #include #include -struct aiMaterial; - namespace AZ { namespace SDKMaterial diff --git a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h index dfd216912a80..8339469d7592 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/NodeWrapper.h @@ -9,8 +9,6 @@ #include #include -struct aiNode; - namespace AZ { namespace SDKNode diff --git a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp index c544f0667655..4881dcb8b692 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ +#include #include namespace AZ @@ -36,5 +37,47 @@ namespace AZ void SceneWrapperBase::Clear() { } + + AZStd::pair SceneWrapperBase::GetUpVectorAndSign() const + { + return {AxisVector::Z, 1}; + } + + AZStd::pair SceneWrapperBase::GetFrontVectorAndSign() const + { + return { AxisVector::X, 1}; + } + + float SceneWrapperBase::GetUnitSizeInMeters() const + { + return 1.0f; + } + + AZ::Aabb SceneWrapperBase::GetAABB() const + { + return AZ::Aabb::CreateNull(); + } + + uint32_t SceneWrapperBase::GetVerticesCount() const + { + return 0u; + } + + + SceneAPI::DataTypes::MatrixType SceneTypeConverter::ToTransform(const AZ::Matrix4x4& matrix) + { + SceneAPI::DataTypes::MatrixType transform; + for (int row = 0; row < 3; ++row) + { + for (int column = 0; column < 4; ++column) + { + transform.SetElement(row, column, matrix.GetElement(row, column)); + } + } + + return transform; + } + + } //namespace SDKScene }// namespace AZ diff --git a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h index 1e6cdeeb0462..bd2a450fa0c9 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h +++ b/Code/Tools/SceneAPI/SDKWrapper/SceneWrapper.h @@ -8,11 +8,11 @@ #pragma once #include #include +#include #include +#include #include -struct aiScene; - namespace AZ { namespace SDKScene @@ -31,8 +31,28 @@ namespace AZ virtual void Clear(); + enum class AxisVector + { + X = 0, + Y = 1, + Z = 2, + Unknown + }; + + virtual AZStd::pair GetUpVectorAndSign() const; + virtual AZStd::pair GetFrontVectorAndSign() const; + virtual float GetUnitSizeInMeters() const; + virtual AZ::Aabb GetAABB() const; + virtual uint32_t GetVerticesCount() const; + static const char* s_defaultSceneName; }; - } //namespace Scene -} //namespace AZ + class SceneTypeConverter + { + public: + static SceneAPI::DataTypes::MatrixType ToTransform(const AZ::Matrix4x4& matrix); + }; + + } // namespace SDKScene +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/DllMain.cpp b/Code/Tools/SceneAPI/SceneBuilder/DllMain.cpp index f4d52cf402e3..9a7c4c7e2a66 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/DllMain.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/DllMain.cpp @@ -8,26 +8,30 @@ #if !defined(AZ_MONOLITHIC_BUILD) +#include "ImportContexts/AssImpImportContextProvider.h" +#include "SceneBuilderSystemComponent.h" + #include #include -#include #include +#include +#include #include -#include +#include #include +#include +#include #include #include #include #include +#include +#include #include #include #include -#include -#include -#include -#include -#include +#include namespace AZ { @@ -50,6 +54,9 @@ namespace AZ g_componentDescriptors.push_back(SceneBuilder::SceneImporter::CreateDescriptor()); g_componentDescriptors.push_back(SceneImportRequestHandler::CreateDescriptor()); + // ImportContextProviderRegistry + g_componentDescriptors.push_back(SceneBuilderSystemComponent::CreateDescriptor()); + // Node and attribute importers g_componentDescriptors.push_back(AssImpBitangentStreamImporter::CreateDescriptor()); g_componentDescriptors.push_back(AssImpColorStreamImporter::CreateDescriptor()); @@ -103,6 +110,8 @@ namespace AZ extern "C" AZ_DLL_EXPORT void InitializeDynamicModule() { + // Scott-Meyers singleton as no clear way how to add SystemComponent to module + AZ::SceneAPI::SceneBuilder::ImportContextRegistryManager::GetInstance(); } extern "C" AZ_DLL_EXPORT void Reflect(AZ::SerializeContext* context) { diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistry.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistry.h new file mode 100644 index 000000000000..06c01e8a401e --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistry.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include +#include + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + struct ImportContextProvider; + + // ImportContextRegistry realizes Abstract Factory Pattern. + // It provides a family of objects related to a particular Import Context. + // Those include ImportContext specializations for different stages of the Import pipeline + // as well as Scene and Node wrappers. + // To add a new library for importing scene assets: + // - specialize and implement the ImportContextProvider + // - register specialization with this interface + class ImportContextRegistry + { + public: + AZ_RTTI(ImportContextRegistry, "{5faaaa8a-2497-41d7-8b5c-5af4390af776}"); + AZ_CLASS_ALLOCATOR(ImportContextRegistry, AZ::SystemAllocator, 0); + + virtual ~ImportContextRegistry() = default; + + virtual void RegisterContextProvider(ImportContextProvider* provider) = 0; + virtual void UnregisterContextProvider(ImportContextProvider* provider) = 0; + virtual ImportContextProvider* SelectImportProvider(AZStd::string_view fileExtension) const = 0; + }; + + using ImportContextRegistryInterface = AZ::Interface; + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistryManager.cpp b/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistryManager.cpp new file mode 100644 index 000000000000..496b4e93fb57 --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistryManager.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "ImportContextRegistryManager.h" + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + ImportContextRegistryManager::ImportContextRegistryManager() + { + // register AssImp default provider + auto assimpContextProvider = aznew AssImpImportContextProvider(); + m_importContextProviders.push_back(AZStd::unique_ptr(assimpContextProvider)); + }; + + void ImportContextRegistryManager::RegisterContextProvider(ImportContextProvider* provider) + { + if (provider) + { + m_importContextProviders.push_back(AZStd::unique_ptr(provider)); + } + } + + void ImportContextRegistryManager::UnregisterContextProvider(ImportContextProvider* provider) + { + AZ_TracePrintf("SceneAPI", "Unregistered ImportContextProvider %s", provider->GetImporterName().data()); + for (auto it = m_importContextProviders.begin(); it != m_importContextProviders.end(); ++it) + { + if (it->get() == provider) + { + m_importContextProviders.erase(it); + break; // Assuming only one instance can be registered at a time + } + } + } + + ImportContextProvider* ImportContextRegistryManager::SelectImportProvider(AZStd::string_view fileExtension) const + { + AZ_TracePrintf( + "SceneAPI", + "Finding ImportContextProvider (registered %d) suitable for extension: %.*s", + m_importContextProviders.size(), + static_cast(fileExtension.length()), + fileExtension.data()); + // search in reverse order since the default AssImp Provider can handle all extenstions + for (auto it = m_importContextProviders.rbegin(); it != m_importContextProviders.rend(); ++it) + { + if (it->get()->CanHandleExtension(fileExtension)) + { + return it->get(); + } + else + { + AZ_TracePrintf( + "SceneAPI", + "Importer %s cannot handle %.*s", + it->get()->GetImporterName().data(), + static_cast(fileExtension.length()), + fileExtension.data()); + } + } + return nullptr; // No provider found + } + ImportContextRegistryManager& ImportContextRegistryManager::GetInstance() + { + static ImportContextRegistryManager instance; + return instance; + } + + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistryManager.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistryManager.h new file mode 100644 index 000000000000..95c2f8eb36ff --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContextRegistryManager.h @@ -0,0 +1,44 @@ +/* +* Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once +#include +#include +#include +#include + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + // Implementation of the ImportContextRegistryInterface. + class ImportContextRegistryManager : public ImportContextRegistryInterface::Registrar + { + public: + AZ_RTTI(ImportContextRegistryManager, "{d3107473-4f99-4421-b4a8-ece66a922191}", ImportContextRegistry); + AZ_CLASS_ALLOCATOR(ImportContextRegistryManager, AZ::SystemAllocator, 0); + + ImportContextRegistryManager(); + ImportContextRegistryManager(const ImportContextRegistryManager&) = delete; + ImportContextRegistryManager& operator=(const ImportContextRegistryManager&) = delete; + + ~ImportContextRegistryManager() override = default; + + void RegisterContextProvider(ImportContextProvider* provider) override; + void UnregisterContextProvider(ImportContextProvider* provider) override; + ImportContextProvider* SelectImportProvider(AZStd::string_view fileExtension) const override; + + static ImportContextRegistryManager& GetInstance(); + private: + AZStd::vector> m_importContextProviders; + }; + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.cpp b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.cpp new file mode 100644 index 000000000000..6b56a8065d73 --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "AssImpImportContextProvider.h" +#include + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + AZStd::shared_ptr AssImpImportContextProvider::CreateNodeEncounteredContext( + Containers::Scene& scene, + Containers::SceneGraph::NodeIndex currentGraphPosition, + const SceneSystem& sourceSceneSystem, + RenamedNodesMap& nodeNameMap, + SDKScene::SceneWrapperBase& sourceScene, + SDKNode::NodeWrapper& sourceNode) + { + // need to cast NodeWrapper + auto assImpNode = azrtti_cast(&sourceNode); + auto assImpScene = azrtti_cast(&sourceScene); + + if (!assImpNode) + { + // Handle error: parent is not of the expected type + AZ_Error("SceneBuilder", false, "Incorrect node type. Cannot create NodeEncounteredContext"); + return nullptr; + } + if (!assImpScene) + { + AZ_Error("SceneBuilder", false, "Incorrect scene type. Cannot create NodeEncounteredContext"); + return nullptr; + } + return AZStd::make_shared( + scene, currentGraphPosition, *assImpScene, sourceSceneSystem, nodeNameMap, *assImpNode); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneDataPopulatedContext( + NodeEncounteredContextBase& parent, AZStd::shared_ptr graphData, const AZStd::string& dataName) + { + // Downcast the parent to the AssImp-specific type to access AssImpImportContext members + AssImpNodeEncounteredContext* assImpParent = azrtti_cast(&parent); + if (!assImpParent) + { + AZ_Error("SceneBuilder", false, "Incorrect type of parent. Cannot create SceneDataPopulatedContext"); + return nullptr; + } + + return AZStd::make_shared(*assImpParent, AZStd::move(graphData), dataName); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneNodeAppendedContext( + SceneDataPopulatedContextBase& parent, Containers::SceneGraph::NodeIndex newIndex) + { + // Downcast the parent to the AssImp-specific type + AssImpSceneDataPopulatedContext* assImpParent = azrtti_cast(&parent); + if (!assImpParent) + { + AZ_Error("SceneBuilder", false, "Incorrect type of parent. Cannot create SceneNodeAppendedContext"); + return nullptr; + } + + return AZStd::make_shared(*assImpParent, newIndex); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneAttributeDataPopulatedContext( + SceneNodeAppendedContextBase& parent, + AZStd::shared_ptr nodeData, + const Containers::SceneGraph::NodeIndex attributeNodeIndex, + const AZStd::string& dataName) + { + // Downcast the parent to the AssImp-specific type + AssImpSceneNodeAppendedContext* assImpParent = azrtti_cast(&parent); + if (!assImpParent) + { + AZ_Error("SceneBuilder", false, "Incorrect type of parent. Cannot create SceneAttributeDataPopulatedContext"); + return nullptr; + } + return AZStd::make_shared( + *assImpParent, AZStd::move(nodeData), attributeNodeIndex, dataName); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneAttributeNodeAppendedContext( + SceneAttributeDataPopulatedContextBase& parent, Containers::SceneGraph::NodeIndex newIndex) + { + // Downcast the parent to the AssImp-specific type + AssImpSceneAttributeDataPopulatedContext* assImpParent = azrtti_cast(&parent); + if (!assImpParent) + { + AZ_Error("SceneBuilder", false, "Incorrect type of parent. Cannot create SceneAttributeNodeAppendedContext"); + return nullptr; + } + return AZStd::make_shared(*assImpParent, newIndex); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneNodeAddedAttributesContext( + SceneNodeAppendedContextBase& parent) + { + // Downcast the parent to the AssImp-specific type + AssImpSceneNodeAppendedContext* assImpParent = azrtti_cast(&parent); + if (!assImpParent) + { + AZ_Error("SceneBuilder", false, "Incorrect type of parent. Cannot create SceneNodeAddedAttributesContext"); + return nullptr; + } + return AZStd::make_shared(*assImpParent); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneNodeFinalizeContext( + SceneNodeAddedAttributesContextBase& parent) + { + // Downcast the parent to the AssImp-specific type + AssImpSceneNodeAddedAttributesContext* assImpParent = azrtti_cast(&parent); + if (!assImpParent) + { + AZ_Error("SceneBuilder", false, "Incorrect type of parent. Cannot create SceneNodeFinalizeContext"); + return nullptr; + } + return AZStd::make_shared(*assImpParent); + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateFinalizeSceneContext( + Containers::Scene& scene, + const SceneSystem& sourceSceneSystem, + SDKScene::SceneWrapperBase& sourceScene, + RenamedNodesMap& nodeNameMap) + { + AssImpSDKWrapper::AssImpSceneWrapper* assImpScene = azrtti_cast(&sourceScene); + if (!assImpScene) + { + AZ_Error("SceneBuilder", false, "Incorrect scene type. Cannot create FinalizeSceneContext"); + return nullptr; + } + return AZStd::make_shared(scene, *assImpScene, sourceSceneSystem, nodeNameMap); + } + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.h new file mode 100644 index 000000000000..0506da08287a --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include "ImportContextProvider.h" + +#include +#include +#include +#include + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + // Concrete provider for creating AssImp-specific import classes. + struct AssImpImportContextProvider : public ImportContextProvider + { + AZ_RTTI(AssImpImportContextProvider, "{6c263adb-e73c-4017-955a-9c212ded3637}"); + + AssImpImportContextProvider() = default; + + AZStd::shared_ptr CreateNodeEncounteredContext( + Containers::Scene& scene, + Containers::SceneGraph::NodeIndex currentGraphPosition, + const SceneSystem& sourceSceneSystem, + RenamedNodesMap& nodeNameMap, + SDKScene::SceneWrapperBase& sourceScene, + SDKNode::NodeWrapper& sourceNode) override; + + AZStd::shared_ptr CreateSceneDataPopulatedContext( + NodeEncounteredContextBase& parent, + AZStd::shared_ptr graphData, + const AZStd::string& dataName) override; + + AZStd::shared_ptr CreateSceneNodeAppendedContext( + SceneDataPopulatedContextBase& parent, Containers::SceneGraph::NodeIndex newIndex) override; + + AZStd::shared_ptr CreateSceneAttributeDataPopulatedContext( + SceneNodeAppendedContextBase& parent, + AZStd::shared_ptr nodeData, + const Containers::SceneGraph::NodeIndex attributeNodeIndex, + const AZStd::string& dataName) override; + + AZStd::shared_ptr CreateSceneAttributeNodeAppendedContext( + SceneAttributeDataPopulatedContextBase& parent, Containers::SceneGraph::NodeIndex newIndex) override; + + AZStd::shared_ptr CreateSceneNodeAddedAttributesContext( + SceneNodeAppendedContextBase& parent) override; + + AZStd::shared_ptr CreateSceneNodeFinalizeContext( + SceneNodeAddedAttributesContextBase& parent) override; + + AZStd::shared_ptr CreateFinalizeSceneContext( + Containers::Scene& scene, const SceneSystem& sourceSceneSystem, SDKScene::SceneWrapperBase& sourceScene, RenamedNodesMap& nodeNameMap) override; + + bool CanHandleExtension(AZStd::string_view fileExtension) const override + { + // The AssImp is our default provider and returns true for all registered extensions. + return true; + } + + AZStd::unique_ptr CreateSceneWrapper() const override + { + return AZStd::make_unique(); + } + + AZStd::string_view GetImporterName() const override + { + return "AssImp"; + } + + private: + // const AssImpSDKWrapper::AssImpSceneWrapper* m_sourceScene; + }; + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.cpp b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.cpp index 67a2b26e9833..62198b7e2515 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.cpp @@ -32,7 +32,7 @@ namespace AZ RenamedNodesMap& nodeNameMap, AssImpSDKWrapper::AssImpNodeWrapper& sourceNode) : AssImpImportContext(sourceScene, sourceSceneSystem, sourceNode) - , NodeEncounteredContext(scene, currentGraphPosition, nodeNameMap) + , NodeEncounteredContextBase(scene, currentGraphPosition, nodeNameMap) { } @@ -44,7 +44,7 @@ namespace AZ RenamedNodesMap& nodeNameMap, AssImpSDKWrapper::AssImpNodeWrapper& sourceNode) : AssImpImportContext(sourceScene, sourceSceneSystem, sourceNode) - , NodeEncounteredContext(parent.GetScene(), currentGraphPosition, nodeNameMap) + , NodeEncounteredContextBase(parent.GetScene(), currentGraphPosition, nodeNameMap) { } diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h index 16d5008c8f2d..75fcf5dcb56c 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h @@ -50,9 +50,9 @@ namespace AZ // importers that have means to process the contained data should do so struct AssImpNodeEncounteredContext : public AssImpImportContext - , public NodeEncounteredContext + , public NodeEncounteredContextBase { - AZ_RTTI(AssImpNodeEncounteredContext, "{C2305BC5-EAEC-4515-BAD6-45E63C3FBD3D}", AssImpImportContext, NodeEncounteredContext); + AZ_RTTI(AssImpNodeEncounteredContext, "{C2305BC5-EAEC-4515-BAD6-45E63C3FBD3D}", AssImpImportContext, NodeEncounteredContextBase); AssImpNodeEncounteredContext(Containers::Scene& scene, Containers::SceneGraph::NodeIndex currentGraphPosition, @@ -180,4 +180,3 @@ namespace AZ } // namespace SceneBuilder } // namespace SceneAPI } // namespace AZ - diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContextProvider.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContextProvider.h new file mode 100644 index 000000000000..730524de0fde --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContextProvider.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include "ImportContexts.h" + +#include +#include +#include +#include +#include +#include + +namespace AZ::SDKScene +{ + class SceneWrapperBase; +} +namespace AZ::SDKNode +{ + class NodeWrapper; +} +namespace AZ +{ + namespace SceneAPI + { + class SceneSystem; + namespace SceneBuilder + { + class RenamedNodesMap; + + // ImportContextProvider realizes factory pattern and provides classes specialized for particular Scene Import library. + struct ImportContextProvider + { + AZ_RTTI(ImportContextProvider, "{5df22f6c-8a43-417d-b735-9d9d7d069efc}"); + + virtual ~ImportContextProvider() = default; + + virtual AZStd::shared_ptr CreateNodeEncounteredContext( + Containers::Scene& scene, + Containers::SceneGraph::NodeIndex currentGraphPosition, + const SceneSystem& sourceSceneSystem, + RenamedNodesMap& nodeNameMap, + SDKScene::SceneWrapperBase& sourceScene, + AZ::SDKNode::NodeWrapper& sourceNode) = 0; + + virtual AZStd::shared_ptr CreateSceneDataPopulatedContext( + NodeEncounteredContextBase& parent, + AZStd::shared_ptr graphData, + const AZStd::string& dataName) = 0; + + virtual AZStd::shared_ptr CreateSceneNodeAppendedContext( + SceneDataPopulatedContextBase& parent, Containers::SceneGraph::NodeIndex newIndex) = 0; + + virtual AZStd::shared_ptr CreateSceneAttributeDataPopulatedContext( + SceneNodeAppendedContextBase& parent, + AZStd::shared_ptr nodeData, + const Containers::SceneGraph::NodeIndex attributeNodeIndex, + const AZStd::string& dataName) = 0; + + virtual AZStd::shared_ptr CreateSceneAttributeNodeAppendedContext( + SceneAttributeDataPopulatedContextBase& parent, Containers::SceneGraph::NodeIndex newIndex) = 0; + + virtual AZStd::shared_ptr CreateSceneNodeAddedAttributesContext( + SceneNodeAppendedContextBase& parent) = 0; + + virtual AZStd::shared_ptr CreateSceneNodeFinalizeContext( + SceneNodeAddedAttributesContextBase& parent) = 0; + + virtual AZStd::shared_ptr CreateFinalizeSceneContext( + Containers::Scene& scene, + const SceneSystem& sourceSceneSystem, + SDKScene::SceneWrapperBase& sourceScene, + RenamedNodesMap& nodeNameMap) = 0; + + // Creates an instance of the scene wrapper + virtual AZStd::unique_ptr CreateSceneWrapper() const = 0; + + // Checks if this provider can handle the given file extension + virtual bool CanHandleExtension(AZStd::string_view fileExtension) const = 0; + + // Get a descriptive name for Context Provider + virtual AZStd::string_view GetImporterName() const { return "Unknown Importer"; } + }; + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.cpp b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.cpp index 904c03eba7a2..f02f5f7ffb9e 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.cpp @@ -31,21 +31,21 @@ namespace AZ m_currentGraphPosition = Containers::SceneGraph::NodeIndex(); } - NodeEncounteredContext::NodeEncounteredContext(Containers::Scene& scene, + NodeEncounteredContextBase::NodeEncounteredContextBase(Containers::Scene& scene, Containers::SceneGraph::NodeIndex currentGraphPosition, RenamedNodesMap& nodeNameMap) : ImportContext(scene, currentGraphPosition, nodeNameMap) { } - NodeEncounteredContext::NodeEncounteredContext( + NodeEncounteredContextBase::NodeEncounteredContextBase( Events::ImportEventContext& parent, Containers::SceneGraph::NodeIndex currentGraphPosition, RenamedNodesMap& nodeNameMap) : ImportContext(parent.GetScene(), currentGraphPosition, nodeNameMap) { } - SceneDataPopulatedContextBase::SceneDataPopulatedContextBase(NodeEncounteredContext& parent, + SceneDataPopulatedContextBase::SceneDataPopulatedContextBase(NodeEncounteredContextBase& parent, AZStd::shared_ptr graphData, const AZStd::string& dataName) : ImportContext(parent.m_scene, parent.m_currentGraphPosition, parent.m_nodeNameMap) , m_graphData(AZStd::move(graphData)) diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h index 4787830f36eb..4e408e6fc537 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h @@ -54,22 +54,21 @@ namespace AZ RenamedNodesMap& m_nodeNameMap; // Map of the nodes that have received a new name. }; - // NodeEncounteredContext // Context pushed to indicate that a new Node has been found and any // importers that have means to process the contained data should do so // Member Variables: // m_createdData - out container that importers must add their created data // to. - struct NodeEncounteredContext + struct NodeEncounteredContextBase : public ImportContext { - AZ_RTTI(NodeEncounteredContext, "{40C31D76-7101-4ACD-8849-0D6D0AF62855}", ImportContext); + AZ_RTTI(NodeEncounteredContextBase, "{40C31D76-7101-4ACD-8849-0D6D0AF62855}", ImportContext); - NodeEncounteredContext(Containers::Scene& scene, + NodeEncounteredContextBase(Containers::Scene& scene, Containers::SceneGraph::NodeIndex currentGraphPosition, RenamedNodesMap& nodeNameMap); - NodeEncounteredContext(Events::ImportEventContext& parent, + NodeEncounteredContextBase(Events::ImportEventContext& parent, Containers::SceneGraph::NodeIndex currentGraphPosition, RenamedNodesMap& nodeNameMap); @@ -89,7 +88,7 @@ namespace AZ { AZ_RTTI(SceneDataPopulatedContextBase, "{5F4CE8D2-EEAC-49F7-8065-0B6372162D6F}", ImportContext); - SceneDataPopulatedContextBase(NodeEncounteredContext& parent, + SceneDataPopulatedContextBase(NodeEncounteredContextBase& parent, AZStd::shared_ptr nodeData, const AZStd::string& dataName); @@ -177,4 +176,3 @@ namespace AZ } // namespace SceneBuilder } // namespace SceneAPI } // namespace AZ - diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneBuilderSystemComponent.cpp b/Code/Tools/SceneAPI/SceneBuilder/SceneBuilderSystemComponent.cpp new file mode 100644 index 000000000000..bae5e0799aaa --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneBuilderSystemComponent.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "SceneBuilderSystemComponent.h" +#include "ImportContexts/AssImpImportContextProvider.h" + +#include +#include + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + void SceneBuilderSystemComponent::Activate() + { + // Get the import context registy + if (auto* registry = ImportContextRegistryInterface::Get()) + { + // Create and register the ImportContextProvider for AssImp + // It should be always present and be used as a fallback if no specialized provider is available + auto assImpContextProvider = aznew AssImpImportContextProvider(); + registry->RegisterContextProvider(assImpContextProvider); + AZ_Info("SceneAPI", "AssImp Import Context was registered.\n"); + } + else + { + AZ_Error("SceneAPI", false, "ImportContextRegistryInterface not found. AssImp Import Context was not registered."); + } + } + + void SceneBuilderSystemComponent::Deactivate() + { + } + + void SceneBuilderSystemComponent::Reflect(ReflectContext* context) + { + SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class()->Version(1); + } + } + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneBuilderSystemComponent.h b/Code/Tools/SceneAPI/SceneBuilder/SceneBuilderSystemComponent.h new file mode 100644 index 000000000000..aceeb6d4fad8 --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneBuilderSystemComponent.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace AZ +{ + namespace SceneAPI + { + namespace SceneBuilder + { + // Scene system components are components that can be used to create system components + // in situations where the full initialization and/or construction of regular + // system components don't apply such as in the ResourceCompilerScene. + class SceneBuilderSystemComponent + : public AZ::Component + { + public: + AZ_COMPONENT(SceneBuilderSystemComponent, "{9453ddf4-882c-4675-86eb-834f1d1dc5ef}"); + + ~SceneBuilderSystemComponent() override = default; + + void Activate() override; + void Deactivate() override; + + static void Reflect(ReflectContext* context); + private: + ImportContextRegistryManager m_sceneSystemRegistry; + }; + } // namespace SceneCore + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp index 690d0483cef5..f48030be02d6 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.cpp @@ -12,23 +12,21 @@ #include #include #include -#include -#include #include +#include +#include #include -#include -#include -#include +#include +#include #include #include +#include +#include #include #include #include #include #include -#include -#include - namespace AZ { @@ -51,8 +49,10 @@ namespace AZ SceneImporter::SceneImporter() : m_sceneSystem(new SceneSystem()) + , m_contextProvider(nullptr) + , m_sceneWrapper(nullptr) { - m_sceneWrapper = AZStd::make_unique(); + m_sceneWrapper = AZStd::make_unique(); BindToCall(&SceneImporter::ImportProcessing); } @@ -81,9 +81,7 @@ namespace AZ Containers::Scene scene; Import::ManifestImportRequestHandler manifestHandler; manifestHandler.LoadAsset( - scene, sourceAssetPath, - Uuid::CreateNull(), - Events::AssetImportRequest::RequestingApplication::AssetProcessor); + scene, sourceAssetPath, Uuid::CreateNull(), Events::AssetImportRequest::RequestingApplication::AssetProcessor); // Search for the ImportGroup. If it's there, get the new import settings. If not, we'll just use the defaults. size_t count = scene.GetManifest().GetEntryCount(); @@ -105,17 +103,40 @@ namespace AZ m_sceneWrapper->Clear(); - if (!m_sceneWrapper->LoadSceneFromFile(context.GetInputDirectory().c_str(), importSettings)) + AZStd::string filePath = context.GetInputDirectory(); + AZStd::string extension = AZ::IO::Path(filePath).Extension().String(); + AZStd::to_lower(extension); + + auto* registry = ImportContextRegistryInterface::Get(); + if (registry) { + m_contextProvider.reset(registry->SelectImportProvider(extension)); + } + else + { + AZ_Error("SceneBuilder", false, "ImportContextRegistry interface is not available."); return Events::ProcessingResult::Failure; } - m_sceneSystem->Set(m_sceneWrapper.get()); - if (!azrtti_istypeof(m_sceneWrapper.get())) + if (!m_contextProvider) { + AZ_Error("SceneBuilder", false, "Cannot pick Import Context for file: %s", filePath.c_str()); return Events::ProcessingResult::Failure; } + AZ_TracePrintf( + "SceneBuilder", + "Using '%s' Import Context Provider for file: %s", + m_contextProvider->GetImporterName().data(), + filePath.c_str()); + m_sceneWrapper = m_contextProvider->CreateSceneWrapper(); + if (!m_sceneWrapper->LoadSceneFromFile(context.GetInputDirectory().c_str(), importSettings)) + { + return Events::ProcessingResult::Failure; + } + + m_sceneSystem->Set(m_sceneWrapper.get()); + if (ConvertScene(context.GetScene())) { return Events::ProcessingResult::Success; @@ -134,30 +155,27 @@ namespace AZ return false; } - const AssImpSDKWrapper::AssImpSceneWrapper* assImpSceneWrapper = azrtti_cast (m_sceneWrapper.get()); - - AZStd::pair upAxisAndSign = assImpSceneWrapper->GetUpVectorAndSign(); + AZStd::pair upAxisAndSign = m_sceneWrapper->GetUpVectorAndSign(); - const aiAABB& aabb = assImpSceneWrapper->GetAABB(); - aiVector3t dimension = aabb.mMax - aabb.mMin; - Vector3 t{ dimension.x, dimension.y, dimension.z }; - scene.SetSceneDimension(t); - scene.SetSceneVertices(assImpSceneWrapper->GetVertices()); + const AZ::Aabb& aabb = m_sceneWrapper->GetAABB(); + scene.SetSceneDimension(aabb.GetExtents()); + scene.SetSceneVertices(m_sceneWrapper->GetVerticesCount()); if (upAxisAndSign.second <= 0) { - AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Negative scene orientation is not a currently supported orientation."); + AZ_TracePrintf( + SceneAPI::Utilities::ErrorWindow, "Negative scene orientation is not a currently supported orientation."); return false; } switch (upAxisAndSign.first) { - case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::X: + case SDKScene::SceneWrapperBase::AxisVector::X: scene.SetOriginalSceneOrientation(Containers::Scene::SceneOrientation::XUp); break; - case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Y: + case SDKScene::SceneWrapperBase::AxisVector::Y: scene.SetOriginalSceneOrientation(Containers::Scene::SceneOrientation::YUp); break; - case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Z: + case SDKScene::SceneWrapperBase::AxisVector::Z: scene.SetOriginalSceneOrientation(Containers::Scene::SceneOrientation::ZUp); break; default: @@ -193,84 +211,82 @@ namespace AZ continue; } - AssImpNodeEncounteredContext sourceNodeEncountered(scene, newNode, *assImpSceneWrapper, *m_sceneSystem, nodeNameMap, *azrtti_cast(node.m_node.get())); + auto sourceNodeEncountered = m_contextProvider->CreateNodeEncounteredContext( + scene, newNode, *m_sceneSystem, nodeNameMap, *m_sceneWrapper, *(node.m_node)); Events::ProcessingResultCombiner nodeResult; - nodeResult += Events::Process(sourceNodeEncountered); + nodeResult += Events::Process(*sourceNodeEncountered); // If no importer created data, we still create an empty node that may eventually contain a transform - if (sourceNodeEncountered.m_createdData.empty()) + if (sourceNodeEncountered->m_createdData.empty()) { - AZ_Assert(nodeResult.GetResult() != Events::ProcessingResult::Success, + AZ_Assert( + nodeResult.GetResult() != Events::ProcessingResult::Success, "Importers returned success but no data was created"); AZStd::shared_ptr nullData(nullptr); - sourceNodeEncountered.m_createdData.emplace_back(nullData); + sourceNodeEncountered->m_createdData.emplace_back(nullData); nodeResult += Events::ProcessingResult::Success; } // Create single node since only one piece of graph data was created - if (sourceNodeEncountered.m_createdData.size() == 1) + if (sourceNodeEncountered->m_createdData.size() == 1) { - AZ_Assert(nodeResult.GetResult() != Events::ProcessingResult::Ignored, + AZ_Assert( + nodeResult.GetResult() != Events::ProcessingResult::Ignored, "An importer created data, but did not return success"); if (nodeResult.GetResult() == Events::ProcessingResult::Failure) { AZ_TracePrintf(Utilities::ErrorWindow, "One or more importers failed to create data."); } - AssImpSceneDataPopulatedContext dataProcessed(sourceNodeEncountered, - sourceNodeEncountered.m_createdData[0], nodeName.c_str()); - Events::ProcessingResult result = AddDataNodeWithContexts(dataProcessed); + auto dataProcessed = m_contextProvider->CreateSceneDataPopulatedContext( + *sourceNodeEncountered, sourceNodeEncountered->m_createdData[0], nodeName.c_str()); + Events::ProcessingResult result = AddDataNodeWithContexts(*dataProcessed); if (result != Events::ProcessingResult::Failure) { - newNode = dataProcessed.m_currentGraphPosition; + newNode = dataProcessed->m_currentGraphPosition; } } // Create an empty parent node and place all data under it. The remaining // tree will be built off of this as the logical parent else { - AZ_Assert(nodeResult.GetResult() != Events::ProcessingResult::Ignored, + AZ_Assert( + nodeResult.GetResult() != Events::ProcessingResult::Ignored, "%i importers created data, but did not return success", - sourceNodeEncountered.m_createdData.size()); + sourceNodeEncountered->m_createdData.size()); if (nodeResult.GetResult() == Events::ProcessingResult::Failure) { AZ_TracePrintf(Utilities::ErrorWindow, "One or more importers failed to create data."); } size_t offset = nodeName.length(); - for (size_t i = 0; i < sourceNodeEncountered.m_createdData.size(); ++i) + for (size_t i = 0; i < sourceNodeEncountered->m_createdData.size(); ++i) { nodeName += '_'; nodeName += AZStd::to_string(aznumeric_cast(i + 1)); - Containers::SceneGraph::NodeIndex subNode = - scene.GetGraph().AddChild(newNode, nodeName.c_str()); + Containers::SceneGraph::NodeIndex subNode = scene.GetGraph().AddChild(newNode, nodeName.c_str()); AZ_Assert(subNode.IsValid(), "Failed to create new scene sub node"); - AssImpSceneDataPopulatedContext dataProcessed(sourceNodeEncountered, - sourceNodeEncountered.m_createdData[i], nodeName); - dataProcessed.m_currentGraphPosition = subNode; - AddDataNodeWithContexts(dataProcessed); + auto dataProcessed = m_contextProvider->CreateSceneDataPopulatedContext( + *sourceNodeEncountered, sourceNodeEncountered->m_createdData[i], nodeName); + dataProcessed->m_currentGraphPosition = subNode; + AddDataNodeWithContexts(*dataProcessed); // Remove the temporary extension again. nodeName.erase(offset, nodeName.length() - offset); } } - AZ_Assert(nodeResult.GetResult() == Events::ProcessingResult::Success, + AZ_Assert( + nodeResult.GetResult() == Events::ProcessingResult::Success, "No importers successfully added processed scene data."); - AZ_Assert(newNode != node.m_parent, - "Failed to update current graph position during data processing."); + AZ_Assert(newNode != node.m_parent, "Failed to update current graph position during data processing."); int childCount = node.m_node->GetChildCount(); for (int i = 0; i < childCount; ++i) { const std::shared_ptr nodeWrapper = node.m_node->GetChild(i); - auto assImpNodeWrapper = azrtti_cast(nodeWrapper.get()); - - AZ_Assert(assImpNodeWrapper, "Child node is not the expected AssImpNodeWrapper type"); - - std::shared_ptr child = std::make_shared(assImpNodeWrapper->GetAssImpNode()); - if (child) + if (auto child = nodeWrapper) { nodes.emplace(AZStd::move(child), newNode); } @@ -279,13 +295,10 @@ namespace AZ nodes.pop(); }; - Events::ProcessingResult result = Events::Process(scene, *assImpSceneWrapper, *m_sceneSystem, nodeNameMap); - if (result == Events::ProcessingResult::Failure) - { - return false; - } - - return true; + auto finalizeSceneContext = + m_contextProvider->CreateFinalizeSceneContext(scene, *m_sceneSystem, *m_sceneWrapper, nodeNameMap); + Events::ProcessingResult finalizeResult = Events::Process(*finalizeSceneContext); + return finalizeResult != Events::ProcessingResult::Failure; } void SceneImporter::SanitizeNodeName(AZStd::string& nodeName) const diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.h b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.h index 06675e196051..41523cf06aff 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.h +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneImporter.h @@ -8,14 +8,16 @@ #pragma once -#include #include +#include +#include +#include +#include +#include #include #include #include #include -#include -#include namespace AZ { @@ -48,6 +50,8 @@ namespace AZ AZStd::unique_ptr m_sceneWrapper; AZStd::shared_ptr m_sceneSystem; + AZStd::unique_ptr m_contextProvider {}; + ImportContextRegistryManager m_contextRegistry; }; } // namespace SceneBuilder } // namespace SceneAPI diff --git a/Code/Tools/SceneAPI/SceneBuilder/SceneSystem.cpp b/Code/Tools/SceneAPI/SceneBuilder/SceneSystem.cpp index b8c1939e6aa9..f6ae2dd64f47 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/SceneSystem.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/SceneSystem.cpp @@ -6,12 +6,11 @@ * */ +#include "SceneWrapper.h" + #include #include #include -#include -#include -#include namespace AZ @@ -28,36 +27,9 @@ namespace AZ void SceneSystem::Set(const SDKScene::SceneWrapperBase* scene) { - // Get unit conversion factor to meter. - if (!azrtti_istypeof(scene)) - { - return; - } - - const AssImpSDKWrapper::AssImpSceneWrapper* assImpScene = azrtti_cast(scene); - - /* Check if metadata has information about "UnitScaleFactor" or "OriginalUnitScaleFactor". - * This particular metadata is FBX format only. */ - if (assImpScene->GetAssImpScene()->mMetaData->HasKey("UnitScaleFactor") || - assImpScene->GetAssImpScene()->mMetaData->HasKey("OriginalUnitScaleFactor")) - { - // If either metadata piece is not available, the default of 1 will be used. - assImpScene->GetAssImpScene()->mMetaData->Get("UnitScaleFactor", m_unitSizeInMeters); - assImpScene->GetAssImpScene()->mMetaData->Get("OriginalUnitScaleFactor", m_originalUnitSizeInMeters); - - /* Conversion factor for converting from centimeters to meters. - * This applies to an FBX format in which the default unit is a centimeter. */ - m_unitSizeInMeters = m_unitSizeInMeters * .01f; - } - else - { - // Some file formats (like DAE) embed the scale in the root transformation, so extract that scale from here. - auto rootTransform = - AssImpSDKWrapper::AssImpTypeConverter::ToTransform(assImpScene->GetAssImpScene()->mRootNode->mTransformation); - m_unitSizeInMeters = rootTransform.ExtractScale().GetMaxElement(); - } + m_unitSizeInMeters = scene->GetUnitSizeInMeters(); - AZStd::pair upAxisAndSign = assImpScene->GetUpVectorAndSign(); + AZStd::pair upAxisAndSign = scene->GetUpVectorAndSign(); if (upAxisAndSign.second <= 0) { @@ -65,10 +37,10 @@ namespace AZ return; } - AZStd::pair frontAxisAndSign = assImpScene->GetFrontVectorAndSign(); + AZStd::pair frontAxisAndSign = scene->GetFrontVectorAndSign(); - if (upAxisAndSign.first != AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Z && - upAxisAndSign.first != AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Unknown) + if (upAxisAndSign.first != SDKScene::SceneWrapperBase::AxisVector::Z && + upAxisAndSign.first != SDKScene::SceneWrapperBase::AxisVector::Unknown) { AZ::Matrix4x4 currentCoordMatrix = AZ::Matrix4x4::CreateIdentity(); //(UpVector = +Z, FrontVector = +Y, CoordSystem = -X(RightHanded)) @@ -80,7 +52,7 @@ namespace AZ switch (upAxisAndSign.first) { - case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::X: { + case SDKScene::SceneWrapperBase::AxisVector::X: { if (frontAxisAndSign.second == 1) { currentCoordMatrix = AZ::Matrix4x4::CreateFromColumns( @@ -99,7 +71,7 @@ namespace AZ } } break; - case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Y: { + case SDKScene::SceneWrapperBase::AxisVector::Y: { if (frontAxisAndSign.second == 1) { currentCoordMatrix = AZ::Matrix4x4::CreateFromColumns( @@ -120,7 +92,7 @@ namespace AZ break; } AZ::Matrix4x4 adjustmatrix = targetCoordMatrix * currentCoordMatrix.GetInverseTransform(); - m_adjustTransform.reset(new DataTypes::MatrixType(AssImpSDKWrapper::AssImpTypeConverter::ToTransform(adjustmatrix))); + m_adjustTransform.reset(new DataTypes::MatrixType(SDKScene::SceneTypeConverter::ToTransform(adjustmatrix))); m_adjustTransformInverse.reset(new DataTypes::MatrixType(m_adjustTransform->GetInverseFull())); } } diff --git a/Code/Tools/SceneAPI/SceneBuilder/scenebuilder_files.cmake b/Code/Tools/SceneAPI/SceneBuilder/scenebuilder_files.cmake index 5defd364f639..1a89d8b3de20 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/scenebuilder_files.cmake +++ b/Code/Tools/SceneAPI/SceneBuilder/scenebuilder_files.cmake @@ -14,10 +14,18 @@ set(FILES SceneImporter.cpp SceneSystem.h SceneSystem.cpp + SceneBuilderSystemComponent.h + SceneBuilderSystemComponent.cpp + ImportContextRegistry.h + ImportContextRegistryManager.h + ImportContextRegistryManager.cpp ImportContexts/ImportContexts.h ImportContexts/ImportContexts.cpp + ImportContexts/ImportContextProvider.h ImportContexts/AssImpImportContexts.h ImportContexts/AssImpImportContexts.cpp + ImportContexts/AssImpImportContextProvider.h + ImportContexts/AssImpImportContextProvider.cpp Importers/Utilities/AssImpMeshImporterUtilities.h Importers/Utilities/AssImpMeshImporterUtilities.cpp Importers/Utilities/RenamedNodesMap.h