/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include <AzCore/Serialization/SerializeContext.h> #include <AzCore/std/smart_ptr/make_shared.h> #include <AzToolsFramework/Debug/TraceContext.h> #include <SceneAPI/FbxSceneBuilder/Importers/FbxMaterialImporter.h> #include <SceneAPI/FbxSceneBuilder/Importers/FbxImporterUtilities.h> #include <SceneAPI/FbxSceneBuilder/Importers/Utilities/RenamedNodesMap.h> #include <SceneAPI/FbxSDKWrapper/FbxNodeWrapper.h> #include <SceneAPI/FbxSDKWrapper/FbxMaterialWrapper.h> #include <SceneAPI/SceneData/GraphData/MeshData.h> #include <SceneAPI/SceneData/GraphData/SkinMeshData.h> #include <SceneAPI/SceneData/GraphData/MaterialData.h> #include <SceneAPI/SceneCore/Utilities/Reporting.h> namespace AZ { namespace SceneAPI { namespace FbxSceneBuilder { FbxMaterialImporter::FbxMaterialImporter() { BindToCall(&FbxMaterialImporter::ImportMaterials); } void FbxMaterialImporter::Reflect(ReflectContext* context) { SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context); if (serializeContext) { serializeContext->Class<FbxMaterialImporter, SceneCore::LoadingComponent>()->Version(1); } } Events::ProcessingResult FbxMaterialImporter::ImportMaterials(SceneNodeAppendedContext& context) { AZ_TraceContext("Importer", "Material"); if (!context.m_sourceNode.GetMesh()) { return Events::ProcessingResult::Ignored; } Events::ProcessingResultCombiner combinedMaterialImportResults; for (int materialIndex = 0; materialIndex < context.m_sourceNode.GetMaterialCount(); ++materialIndex) { AZ_TraceContext("Material Index", materialIndex); const std::shared_ptr<FbxSDKWrapper::FbxMaterialWrapper> fbxMaterial = context.m_sourceNode.GetMaterial(materialIndex); if (!fbxMaterial) { AZ_TracePrintf(Utilities::WarningWindow, "Invalid material data found, ignoring."); continue; } AZStd::string materialName = fbxMaterial->GetName().c_str(); RenamedNodesMap::SanitizeNodeName(materialName, context.m_scene.GetGraph(), context.m_currentGraphPosition, "Material"); AZ_TraceContext("Material Name", materialName); AZStd::shared_ptr<SceneData::GraphData::MaterialData> materialData = BuildMaterial(context.m_sourceNode, materialIndex); AZ_Assert(materialData, "Failed to allocate scene material data."); if (!materialData) { combinedMaterialImportResults += Events::ProcessingResult::Failure; continue; } Events::ProcessingResult materialResult; Containers::SceneGraph::NodeIndex newIndex = context.m_scene.GetGraph().AddChild(context.m_currentGraphPosition, materialName.c_str()); AZ_Assert(newIndex.IsValid(), "Failed to create SceneGraph node for attribute."); if(!newIndex.IsValid()) { combinedMaterialImportResults += Events::ProcessingResult::Failure; continue; } SceneAttributeDataPopulatedContext dataPopulated(context, materialData, newIndex, materialName); materialResult = Events::Process(dataPopulated); if (materialResult != Events::ProcessingResult::Failure) { materialResult = AddAttributeDataNodeWithContexts(dataPopulated); } combinedMaterialImportResults += materialResult; } return combinedMaterialImportResults.GetResult(); } AZStd::shared_ptr<SceneData::GraphData::MaterialData> FbxMaterialImporter::BuildMaterial(FbxSDKWrapper::FbxNodeWrapper& node, int materialIndex) const { AZ_Assert(materialIndex < node.GetMaterialCount(), "Invalid material index (%i)", materialIndex); const std::shared_ptr<FbxSDKWrapper::FbxMaterialWrapper> fbxMaterial = node.GetMaterial(materialIndex); if (!fbxMaterial) { return nullptr; } AZStd::shared_ptr<SceneData::GraphData::MaterialData> material = AZStd::make_shared<SceneData::GraphData::MaterialData>(); material->SetMaterialName(fbxMaterial->GetName()); material->SetTexture(DataTypes::IMaterialData::TextureMapType::Diffuse, fbxMaterial->GetTextureFileName(FbxSDKWrapper::FbxMaterialWrapper::MaterialMapType::Diffuse).c_str()); material->SetTexture(DataTypes::IMaterialData::TextureMapType::Specular, fbxMaterial->GetTextureFileName(FbxSDKWrapper::FbxMaterialWrapper::MaterialMapType::Specular).c_str()); material->SetTexture(DataTypes::IMaterialData::TextureMapType::Bump, fbxMaterial->GetTextureFileName(FbxSDKWrapper::FbxMaterialWrapper::MaterialMapType::Bump).c_str()); material->SetTexture(DataTypes::IMaterialData::TextureMapType::Normal, fbxMaterial->GetTextureFileName(FbxSDKWrapper::FbxMaterialWrapper::MaterialMapType::Normal).c_str()); material->SetDiffuseColor(fbxMaterial->GetDiffuseColor()); material->SetSpecularColor(fbxMaterial->GetSpecularColor()); material->SetEmissiveColor(fbxMaterial->GetEmissiveColor()); material->SetShininess(fbxMaterial->GetShininess()); float opacity = fbxMaterial->GetOpacity(); if (opacity == 0.0f) { opacity = 1.0f; AZ_TracePrintf(Utilities::WarningWindow, "Opacity has been changed from 0 to full. Some DCC tools ignore the opacity and " "write 0 to indicate opacity is not used. This causes meshes to turn invisible, which is often not the intention so " "the opacity has been set to full automatically. If the intention was for a fully transparent mesh, please update " "the opacity in Lumberyards material editor."); } material->SetOpacity(opacity); material->SetUniqueId(fbxMaterial->GetUniqueId()); return material; } } // namespace FbxSceneBuilder } // namespace SceneAPI } // namespace AZ