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..3007ebbf8cb5 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL @@ -38,7 +39,7 @@ 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, @@ -184,6 +185,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..5a0744c92b2a 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/DllMain.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/DllMain.cpp @@ -28,6 +28,9 @@ #include #include #include +#include +#include + namespace AZ { @@ -50,6 +53,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 +109,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..45b86c837b5b --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContextProvider.cpp @@ -0,0 +1,162 @@ +/* + * 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; + } + auto context = AZStd::make_shared( + scene, currentGraphPosition, *assImpScene, sourceSceneSystem, nodeNameMap, *assImpNode); + context->m_contextProvider = this; + return context; + } + + AZStd::shared_ptr AssImpImportContextProvider::CreateSceneDataPopulatedContext( + NodeEncounteredContext& 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; + } + + auto context = AZStd::make_shared(*assImpParent, AZStd::move(graphData), dataName); + + context->m_contextProvider = this; + return context; + } + + 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; + } + + auto context = AZStd::make_shared(*assImpParent, newIndex); + context->m_contextProvider = this; + return context; + } + + 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; + } + auto context = AZStd::make_shared( + *assImpParent, AZStd::move(nodeData), attributeNodeIndex, dataName); + context->m_contextProvider = this; + return context; + } + + 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; + } + auto context = AZStd::make_shared(*assImpParent, newIndex); + context->m_contextProvider = this; + return context; + } + + 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; + } + auto context = AZStd::make_shared(*assImpParent); + context->m_contextProvider = this; + return context; + } + + 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; + } + auto context = AZStd::make_shared(*assImpParent); + context->m_contextProvider = this; + return context; + } + + 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; + } + auto context = AZStd::make_shared(scene, *assImpScene, sourceSceneSystem, nodeNameMap); + context->m_contextProvider = this; + return context; + } + } // 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..8c4cbf8184fb --- /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( + NodeEncounteredContext& 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"; + } + }; + } // namespace SceneBuilder + } // namespace SceneAPI +} // namespace AZ diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h index 16d5008c8f2d..0c0e08be2b6d 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/AssImpImportContexts.h @@ -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..399c620a99e0 --- /dev/null +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContextProvider.h @@ -0,0 +1,103 @@ +/* + * 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 + { + namespace Containers + { + class Scene; + } + + namespace SceneBuilder + { + class RenamedNodesMap; + struct NodeEncounteredContext; + struct SceneDataPopulatedContextBase; + struct SceneNodeAppendedContextBase; + struct SceneAttributeDataPopulatedContextBase; + struct SceneAttributeNodeAppendedContextBase; + struct SceneNodeAddedAttributesContextBase; + struct SceneNodeFinalizeContextBase; + struct FinalizeSceneContextBase; + // 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( + NodeEncounteredContext& 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..6d7e09cd7c99 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.cpp @@ -21,12 +21,14 @@ namespace AZ : m_scene(scene) , m_currentGraphPosition(currentGraphPosition) , m_nodeNameMap(nodeNameMap) + , m_contextProvider(nullptr) { } ImportContext::ImportContext(Containers::Scene& scene, RenamedNodesMap& nodeNameMap) : m_scene(scene) , m_nodeNameMap(nodeNameMap) + , m_contextProvider(nullptr) { m_currentGraphPosition = Containers::SceneGraph::NodeIndex(); } diff --git a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h index 4787830f36eb..423718256b0d 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h +++ b/Code/Tools/SceneAPI/SceneBuilder/ImportContexts/ImportContexts.h @@ -8,12 +8,13 @@ #pragma once +#include "ImportContextProvider.h" + #include #include -#include -#include #include - +#include +#include namespace AZ { @@ -36,6 +37,7 @@ namespace AZ namespace SceneBuilder { + struct ImportContextProvider; class RenamedNodesMap; // ImportContext @@ -52,6 +54,7 @@ namespace AZ Containers::Scene& m_scene; Containers::SceneGraph::NodeIndex m_currentGraphPosition; RenamedNodesMap& m_nodeNameMap; // Map of the nodes that have received a new name. + ImportContextProvider* m_contextProvider; // The provider that created this context. }; // NodeEncounteredContext @@ -177,4 +180,3 @@ namespace AZ } // namespace SceneBuilder } // namespace SceneAPI } // namespace AZ - diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp index b9b9af1e65e0..8784387e2696 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp @@ -116,12 +116,12 @@ namespace AZ context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, m_defaultNodeName); Events::ProcessingResult bitangentResults; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, bitangentStream, newIndex, m_defaultNodeName); - bitangentResults = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, bitangentStream, newIndex, m_defaultNodeName); + bitangentResults = Events::Process(*dataPopulated); if (bitangentResults != Events::ProcessingResult::Failure) { - bitangentResults = AddAttributeDataNodeWithContexts(dataPopulated); + bitangentResults = AddAttributeDataNodeWithContexts(*dataPopulated); } return bitangentResults; } diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp index 2dd7fff8e2e2..6f6b4093a7ce 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBlendShapeImporter.cpp @@ -285,12 +285,12 @@ namespace AZ context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str()); Events::ProcessingResult blendShapeResult; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, blendShapeData, newIndex, nodeName); - blendShapeResult = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, blendShapeData, newIndex, nodeName); + blendShapeResult = Events::Process(*dataPopulated); if (blendShapeResult != Events::ProcessingResult::Failure) { - blendShapeResult = AddAttributeDataNodeWithContexts(dataPopulated); + blendShapeResult = AddAttributeDataNodeWithContexts(*dataPopulated); } combinedBlendShapeResult += blendShapeResult; } diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp index f9b3de6df11d..fbd4b12ed359 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpColorStreamImporter.cpp @@ -113,12 +113,12 @@ namespace AZ context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, nodeName.c_str()); Events::ProcessingResult colorMapResults; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, vertexColors, newIndex, nodeName.c_str()); - colorMapResults = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, vertexColors, newIndex, nodeName.c_str()); + colorMapResults = Events::Process(*dataPopulated); if (colorMapResults != Events::ProcessingResult::Failure) { - colorMapResults = AddAttributeDataNodeWithContexts(dataPopulated); + colorMapResults = AddAttributeDataNodeWithContexts(*dataPopulated); } combinedVertexColorResults += colorMapResults; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpCustomPropertyImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpCustomPropertyImporter.cpp index 6da90557d31b..9628476db914 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpCustomPropertyImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpCustomPropertyImporter.cpp @@ -114,12 +114,12 @@ namespace AZ::SceneAPI::SceneBuilder } Events::ProcessingResult attributeResult; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, customPropertyMapData, newIndex, nodeName); - attributeResult = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, customPropertyMapData, newIndex, nodeName); + attributeResult = Events::Process(*dataPopulated); if (attributeResult != Events::ProcessingResult::Failure) { - attributeResult = AddAttributeDataNodeWithContexts(dataPopulated); + attributeResult = AddAttributeDataNodeWithContexts(*dataPopulated); } return attributeResult; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp index c4452b0e75a1..0b897397cbcd 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpMaterialImporter.cpp @@ -156,12 +156,12 @@ namespace AZ continue; } - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, material, newIndex, materialName); - materialResult = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, material, newIndex, materialName); + materialResult = Events::Process(*dataPopulated); if (materialResult != Events::ProcessingResult::Failure) { - materialResult = SceneAPI::SceneBuilder::AddAttributeDataNodeWithContexts(dataPopulated); + materialResult = SceneAPI::SceneBuilder::AddAttributeDataNodeWithContexts(*dataPopulated); } combinedMaterialImportResults += materialResult; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp index f37f05e4175a..c95049c15b0a 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpSkinWeightsImporter.cpp @@ -111,12 +111,13 @@ namespace AZ } Events::ProcessingResult skinWeightsResult; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, skinWeightData, weightsIndexForMesh, skinWeightName); - skinWeightsResult = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext( + context, skinWeightData, weightsIndexForMesh, skinWeightName); + skinWeightsResult = Events::Process(*dataPopulated); if (skinWeightsResult != Events::ProcessingResult::Failure) { - skinWeightsResult = AddAttributeDataNodeWithContexts(dataPopulated); + skinWeightsResult = AddAttributeDataNodeWithContexts(*dataPopulated); } combinedSkinWeightsResult += skinWeightsResult; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp index fbafd3d24fda..be6d66441766 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp @@ -54,7 +54,6 @@ namespace AZ } const aiNode* currentNode = context.m_sourceNode.GetAssImpNode(); const aiScene* scene = context.m_sourceScene.GetAssImpScene(); - const auto meshHasTangentsAndBitangents = [&scene](const unsigned int meshIndex) { return scene->mMeshes[meshIndex]->HasTangentsAndBitangents(); @@ -118,12 +117,13 @@ namespace AZ context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, m_defaultNodeName); Events::ProcessingResult tangentResults; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, tangentStream, newIndex, m_defaultNodeName); - tangentResults = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext( + context, tangentStream, newIndex, m_defaultNodeName); + tangentResults = Events::Process(*dataPopulated); if (tangentResults != Events::ProcessingResult::Failure) { - tangentResults = AddAttributeDataNodeWithContexts(dataPopulated); + tangentResults = AddAttributeDataNodeWithContexts(*dataPopulated); } return tangentResults; } diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTransformImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTransformImporter.cpp index f632b2bd7f95..670819a9e2de 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTransformImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTransformImporter.cpp @@ -86,12 +86,13 @@ namespace AZ } Events::ProcessingResult transformAttributeResult; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, transformData, newIndex, nodeName); - transformAttributeResult = Events::Process(dataPopulated); + auto dataPopulated = + context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, transformData, newIndex, nodeName); + transformAttributeResult = Events::Process(*dataPopulated); if (transformAttributeResult != Events::ProcessingResult::Failure) { - transformAttributeResult = AddAttributeDataNodeWithContexts(dataPopulated); + transformAttributeResult = AddAttributeDataNodeWithContexts(*dataPopulated); } return transformAttributeResult; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp index 31c155c7eb7d..ad3775c16cd6 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpUvMapImporter.cpp @@ -161,12 +161,12 @@ namespace AZ context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, name.c_str()); Events::ProcessingResult uvMapResults; - AssImpSceneAttributeDataPopulatedContext dataPopulated(context, uvMap, newIndex, name); - uvMapResults = Events::Process(dataPopulated); + auto dataPopulated = context.m_contextProvider->CreateSceneAttributeDataPopulatedContext(context, uvMap, newIndex, name); + uvMapResults = Events::Process(*dataPopulated); if (uvMapResults != Events::ProcessingResult::Failure) { - uvMapResults = AddAttributeDataNodeWithContexts(dataPopulated); + uvMapResults = AddAttributeDataNodeWithContexts(*dataPopulated); } combinedUvMapResults += uvMapResults; diff --git a/Code/Tools/SceneAPI/SceneBuilder/Importers/ImporterUtilities.cpp b/Code/Tools/SceneAPI/SceneBuilder/Importers/ImporterUtilities.cpp index 4d390fcfc444..eb1883364411 100644 --- a/Code/Tools/SceneAPI/SceneBuilder/Importers/ImporterUtilities.cpp +++ b/Code/Tools/SceneAPI/SceneBuilder/Importers/ImporterUtilities.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -42,17 +43,26 @@ namespace AZ dataPopulated.m_scene.GetGraph().SetContent(dataPopulated.m_currentGraphPosition, AZStd::move(dataPopulated.m_graphData)); - if (azrtti_istypeof(dataPopulated)) + // Use context provider to create the appropriate context objects + AZStd::shared_ptr nodeAppended = + dataPopulated.m_contextProvider->CreateSceneNodeAppendedContext(dataPopulated, dataPopulated.m_currentGraphPosition); + if (nodeAppended) { - AssImpSceneDataPopulatedContext* dataPopulatedContext = azrtti_cast(&dataPopulated); - AssImpSceneNodeAppendedContext nodeAppended(*dataPopulatedContext, dataPopulated.m_currentGraphPosition); - nodeResults += Events::Process(nodeAppended); + nodeResults += Events::Process(*nodeAppended); - AssImpSceneNodeAddedAttributesContext addedAttributes(nodeAppended); - nodeResults += Events::Process(addedAttributes); + AZStd::shared_ptr addedAttributes = + dataPopulated.m_contextProvider->CreateSceneNodeAddedAttributesContext(*nodeAppended); + if (addedAttributes) + { + nodeResults += Events::Process(*addedAttributes); - AssImpSceneNodeFinalizeContext finalizeNode(addedAttributes); - nodeResults += Events::Process(finalizeNode); + AZStd::shared_ptr finalizeNode = + dataPopulated.m_contextProvider->CreateSceneNodeFinalizeContext(*addedAttributes); + if (finalizeNode) + { + nodeResults += Events::Process(*finalizeNode); + } + } } return nodeResults.GetResult(); @@ -71,11 +81,12 @@ namespace AZ dataPopulated.m_scene.GetGraph().SetContent(dataPopulated.m_currentGraphPosition, AZStd::move(dataPopulated.m_graphData)); - if (azrtti_istypeof(dataPopulated)) + // Use context provider to create the appropriate attribute node context + AZStd::shared_ptr nodeAppended = + dataPopulated.m_contextProvider->CreateSceneAttributeNodeAppendedContext(dataPopulated, dataPopulated.m_currentGraphPosition); + if (nodeAppended) { - AssImpSceneAttributeDataPopulatedContext* dataPopulatedContext = azrtti_cast(&dataPopulated); - AssImpSceneAttributeNodeAppendedContext nodeAppended(*dataPopulatedContext, dataPopulated.m_currentGraphPosition); - nodeResults += Events::Process(nodeAppended); + nodeResults += Events::Process(*nodeAppended); } return nodeResults.GetResult(); @@ -432,4 +443,4 @@ namespace AZ } } // namespace SceneBuilder } // namespace SceneAPI -} // namespace AZ +} // namespace AZ \ No newline at end of file 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..f8c0f74656d6 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); } @@ -105,17 +105,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 +157,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 +213,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 +297,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